xref: /aosp_15_r20/external/llvm/test/CodeGen/ARM/sub-cmp-peephole.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s --check-prefix=V7
3*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv8-none-linux-gnueabi | FileCheck %s -check-prefix=V8
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker
6*9880d681SAndroid Build Coastguard Workerdefine i32 @f(i32 %a, i32 %b) nounwind ssp {
7*9880d681SAndroid Build Coastguard Workerentry:
8*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f:
9*9880d681SAndroid Build Coastguard Worker; CHECK: subs
10*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
11*9880d681SAndroid Build Coastguard Worker  %cmp = icmp sgt i32 %a, %b
12*9880d681SAndroid Build Coastguard Worker  %sub = sub nsw i32 %a, %b
13*9880d681SAndroid Build Coastguard Worker  %sub. = select i1 %cmp, i32 %sub, i32 0
14*9880d681SAndroid Build Coastguard Worker  ret i32 %sub.
15*9880d681SAndroid Build Coastguard Worker}
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Workerdefine i32 @g(i32 %a, i32 %b) nounwind ssp {
18*9880d681SAndroid Build Coastguard Workerentry:
19*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: g:
20*9880d681SAndroid Build Coastguard Worker; CHECK: subs
21*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
22*9880d681SAndroid Build Coastguard Worker  %cmp = icmp slt i32 %a, %b
23*9880d681SAndroid Build Coastguard Worker  %sub = sub nsw i32 %b, %a
24*9880d681SAndroid Build Coastguard Worker  %sub. = select i1 %cmp, i32 %sub, i32 0
25*9880d681SAndroid Build Coastguard Worker  ret i32 %sub.
26*9880d681SAndroid Build Coastguard Worker}
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Workerdefine i32 @h(i32 %a, i32 %b) nounwind ssp {
29*9880d681SAndroid Build Coastguard Workerentry:
30*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: h:
31*9880d681SAndroid Build Coastguard Worker; CHECK: subs
32*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
33*9880d681SAndroid Build Coastguard Worker  %cmp = icmp sgt i32 %a, 3
34*9880d681SAndroid Build Coastguard Worker  %sub = sub nsw i32 %a, 3
35*9880d681SAndroid Build Coastguard Worker  %sub. = select i1 %cmp, i32 %sub, i32 %b
36*9880d681SAndroid Build Coastguard Worker  ret i32 %sub.
37*9880d681SAndroid Build Coastguard Worker}
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker; rdar://11725965
40*9880d681SAndroid Build Coastguard Workerdefine i32 @i(i32 %a, i32 %b) nounwind readnone ssp {
41*9880d681SAndroid Build Coastguard Workerentry:
42*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: i:
43*9880d681SAndroid Build Coastguard Worker; CHECK: subs
44*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
45*9880d681SAndroid Build Coastguard Worker  %cmp = icmp ult i32 %a, %b
46*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %b, %a
47*9880d681SAndroid Build Coastguard Worker  %sub. = select i1 %cmp, i32 %sub, i32 0
48*9880d681SAndroid Build Coastguard Worker  ret i32 %sub.
49*9880d681SAndroid Build Coastguard Worker}
50*9880d681SAndroid Build Coastguard Worker; If CPSR is live-out, we can't remove cmp if there exists
51*9880d681SAndroid Build Coastguard Worker; a swapped sub.
52*9880d681SAndroid Build Coastguard Workerdefine i32 @j(i32 %a, i32 %b) nounwind {
53*9880d681SAndroid Build Coastguard Workerentry:
54*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: j:
55*9880d681SAndroid Build Coastguard Worker; CHECK: sub
56*9880d681SAndroid Build Coastguard Worker; CHECK: cmp
57*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 %b, %a
58*9880d681SAndroid Build Coastguard Worker  %sub = sub nsw i32 %a, %b
59*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %if.then, label %if.else
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Workerif.then:
62*9880d681SAndroid Build Coastguard Worker  %cmp2 = icmp sgt i32 %b, %a
63*9880d681SAndroid Build Coastguard Worker  %sel = select i1 %cmp2, i32 %sub, i32 %a
64*9880d681SAndroid Build Coastguard Worker  ret i32 %sel
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Workerif.else:
67*9880d681SAndroid Build Coastguard Worker  ret i32 %sub
68*9880d681SAndroid Build Coastguard Worker}
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker; If the sub/rsb instruction is predicated, we can't use the flags.
71*9880d681SAndroid Build Coastguard Worker; <rdar://problem/12263428>
72*9880d681SAndroid Build Coastguard Worker; Test case from MultiSource/Benchmarks/Ptrdist/bc/number.s
73*9880d681SAndroid Build Coastguard Worker; CHECK: bc_raise
74*9880d681SAndroid Build Coastguard Worker; CHECK: rsbeq
75*9880d681SAndroid Build Coastguard Worker; CHECK: cmp
76*9880d681SAndroid Build Coastguard Workerdefine i32 @bc_raise() nounwind ssp {
77*9880d681SAndroid Build Coastguard Workerentry:
78*9880d681SAndroid Build Coastguard Worker  %val.2.i = select i1 undef, i32 0, i32 undef
79*9880d681SAndroid Build Coastguard Worker  %sub.i = sub nsw i32 0, %val.2.i
80*9880d681SAndroid Build Coastguard Worker  %retval.0.i = select i1 undef, i32 %val.2.i, i32 %sub.i
81*9880d681SAndroid Build Coastguard Worker  %cmp1 = icmp eq i32 %retval.0.i, 0
82*9880d681SAndroid Build Coastguard Worker  br i1 %cmp1, label %land.lhs.true, label %if.end11
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Workerland.lhs.true:                                    ; preds = %num2long.exit
85*9880d681SAndroid Build Coastguard Worker  ret i32 17
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Workerif.end11:                                         ; preds = %num2long.exit
88*9880d681SAndroid Build Coastguard Worker  ret i32 23
89*9880d681SAndroid Build Coastguard Worker}
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker; When considering the producer of cmp's src as the subsuming instruction,
92*9880d681SAndroid Build Coastguard Worker; only consider that when the comparison is to 0.
93*9880d681SAndroid Build Coastguard Workerdefine i32 @cmp_src_nonzero(i32 %a, i32 %b, i32 %x, i32 %y) {
94*9880d681SAndroid Build Coastguard Workerentry:
95*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: cmp_src_nonzero:
96*9880d681SAndroid Build Coastguard Worker; CHECK: sub
97*9880d681SAndroid Build Coastguard Worker; CHECK: cmp
98*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %a, %b
99*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 %sub, 17
100*9880d681SAndroid Build Coastguard Worker  %ret = select i1 %cmp, i32 %x, i32 %y
101*9880d681SAndroid Build Coastguard Worker  ret i32 %ret
102*9880d681SAndroid Build Coastguard Worker}
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Workerdefine float @float_sel(i32 %a, i32 %b, float %x, float %y) {
105*9880d681SAndroid Build Coastguard Workerentry:
106*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: float_sel:
107*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
108*9880d681SAndroid Build Coastguard Worker; V8-LABEL: float_sel:
109*9880d681SAndroid Build Coastguard Worker; V8-NOT: cmp
110*9880d681SAndroid Build Coastguard Worker; V8: vseleq.f32
111*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %a, %b
112*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 %sub, 0
113*9880d681SAndroid Build Coastguard Worker  %ret = select i1 %cmp, float %x, float %y
114*9880d681SAndroid Build Coastguard Worker  ret float %ret
115*9880d681SAndroid Build Coastguard Worker}
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Workerdefine double @double_sel(i32 %a, i32 %b, double %x, double %y) {
118*9880d681SAndroid Build Coastguard Workerentry:
119*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: double_sel:
120*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
121*9880d681SAndroid Build Coastguard Worker; V8-LABEL: double_sel:
122*9880d681SAndroid Build Coastguard Worker; V8-NOT: cmp
123*9880d681SAndroid Build Coastguard Worker; V8: vseleq.f64
124*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %a, %b
125*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 %sub, 0
126*9880d681SAndroid Build Coastguard Worker  %ret = select i1 %cmp, double %x, double %y
127*9880d681SAndroid Build Coastguard Worker  ret double %ret
128*9880d681SAndroid Build Coastguard Worker}
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker@t = common global i32 0
131*9880d681SAndroid Build Coastguard Workerdefine double @double_sub(i32 %a, i32 %b, double %x, double %y) {
132*9880d681SAndroid Build Coastguard Workerentry:
133*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: double_sub:
134*9880d681SAndroid Build Coastguard Worker; CHECK: subs
135*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cmp
136*9880d681SAndroid Build Coastguard Worker; V8-LABEL: double_sub:
137*9880d681SAndroid Build Coastguard Worker; V8: vsel
138*9880d681SAndroid Build Coastguard Worker  %cmp = icmp sgt i32 %a, %b
139*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %a, %b
140*9880d681SAndroid Build Coastguard Worker  store i32 %sub, i32* @t
141*9880d681SAndroid Build Coastguard Worker  %ret = select i1 %cmp, double %x, double %y
142*9880d681SAndroid Build Coastguard Worker  ret double %ret
143*9880d681SAndroid Build Coastguard Worker}
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Workerdefine double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) {
146*9880d681SAndroid Build Coastguard Workerentry:
147*9880d681SAndroid Build Coastguard Worker; V7-LABEL: double_sub_swap:
148*9880d681SAndroid Build Coastguard Worker; V7-NOT: cmp
149*9880d681SAndroid Build Coastguard Worker; V7: subs
150*9880d681SAndroid Build Coastguard Worker; V8-LABEL: double_sub_swap:
151*9880d681SAndroid Build Coastguard Worker; V8-NOT: subs
152*9880d681SAndroid Build Coastguard Worker; V8: cmp
153*9880d681SAndroid Build Coastguard Worker; V8: vsel
154*9880d681SAndroid Build Coastguard Worker  %cmp = icmp sgt i32 %a, %b
155*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %b, %a
156*9880d681SAndroid Build Coastguard Worker  %ret = select i1 %cmp, double %x, double %y
157*9880d681SAndroid Build Coastguard Worker  store i32 %sub, i32* @t
158*9880d681SAndroid Build Coastguard Worker  ret double %ret
159*9880d681SAndroid Build Coastguard Worker}
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Workerdeclare void @abort()
162*9880d681SAndroid Build Coastguard Workerdeclare void @exit(i32)
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker; If the comparison uses the V bit (signed overflow/underflow), we can't
165*9880d681SAndroid Build Coastguard Worker; omit the comparison.
166*9880d681SAndroid Build Coastguard Workerdefine i32 @cmp_slt0(i32 %a, i32 %b, i32 %x, i32 %y) {
167*9880d681SAndroid Build Coastguard Workerentry:
168*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: cmp_slt0
169*9880d681SAndroid Build Coastguard Worker; CHECK: sub
170*9880d681SAndroid Build Coastguard Worker; CHECK: cmp
171*9880d681SAndroid Build Coastguard Worker; CHECK: bge
172*9880d681SAndroid Build Coastguard Worker  %load = load i32, i32* @t, align 4
173*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %load, 17
174*9880d681SAndroid Build Coastguard Worker  %cmp = icmp slt i32 %sub, 0
175*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %if.then, label %if.else
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Workerif.then:
178*9880d681SAndroid Build Coastguard Worker  call void @abort()
179*9880d681SAndroid Build Coastguard Worker  unreachable
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Workerif.else:
182*9880d681SAndroid Build Coastguard Worker  call void @exit(i32 0)
183*9880d681SAndroid Build Coastguard Worker  unreachable
184*9880d681SAndroid Build Coastguard Worker}
185*9880d681SAndroid Build Coastguard Worker
186*9880d681SAndroid Build Coastguard Worker; Same for the C bit. (Note the ult X, 0 is trivially
187*9880d681SAndroid Build Coastguard Worker; false, so the DAG combiner may or may not optimize it).
188*9880d681SAndroid Build Coastguard Workerdefine i32 @cmp_ult0(i32 %a, i32 %b, i32 %x, i32 %y) {
189*9880d681SAndroid Build Coastguard Workerentry:
190*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: cmp_ult0
191*9880d681SAndroid Build Coastguard Worker; CHECK: sub
192*9880d681SAndroid Build Coastguard Worker; CHECK: cmp
193*9880d681SAndroid Build Coastguard Worker; CHECK: bhs
194*9880d681SAndroid Build Coastguard Worker  %load = load i32, i32* @t, align 4
195*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 %load, 17
196*9880d681SAndroid Build Coastguard Worker  %cmp = icmp ult i32 %sub, 0
197*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %if.then, label %if.else
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Workerif.then:
200*9880d681SAndroid Build Coastguard Worker  call void @abort()
201*9880d681SAndroid Build Coastguard Worker  unreachable
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Workerif.else:
204*9880d681SAndroid Build Coastguard Worker  call void @exit(i32 0)
205*9880d681SAndroid Build Coastguard Worker  unreachable
206*9880d681SAndroid Build Coastguard Worker}
207