1; RUN: llc -O3 < %s | FileCheck %s
2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64"
3target triple = "arm64-unknown-unknown"
4
5; CHECK-LABEL: foo1
6; CHECK: cinc w{{[0-9]+}}, w{{[0-9]+}}, ne
7define i32 @foo1(i32 %b, i32 %c) nounwind readnone ssp {
8entry:
9  %not.tobool = icmp ne i32 %c, 0
10  %add = zext i1 %not.tobool to i32
11  %b.add = add i32 %c, %b
12  %add1 = add i32 %b.add, %add
13  ret i32 %add1
14}
15
16; CHECK-LABEL: foo2
17; CHECK: cneg w{{[0-9]+}}, w{{[0-9]+}}, ne
18define i32 @foo2(i32 %b, i32 %c) nounwind readnone ssp {
19entry:
20  %mul = sub i32 0, %b
21  %tobool = icmp eq i32 %c, 0
22  %b.mul = select i1 %tobool, i32 %b, i32 %mul
23  %add = add nsw i32 %b.mul, %c
24  ret i32 %add
25}
26
27; CHECK-LABEL: foo3
28; CHECK: cinv w{{[0-9]+}}, w{{[0-9]+}}, ne
29define i32 @foo3(i32 %b, i32 %c) nounwind readnone ssp {
30entry:
31  %not.tobool = icmp ne i32 %c, 0
32  %xor = sext i1 %not.tobool to i32
33  %b.xor = xor i32 %xor, %b
34  %add = add nsw i32 %b.xor, %c
35  ret i32 %add
36}
37
38; rdar://11632325
39define i32@foo4(i32 %a) nounwind ssp {
40; CHECK-LABEL: foo4
41; CHECK: cneg
42; CHECK-NEXT: ret
43  %cmp = icmp sgt i32 %a, -1
44  %neg = sub nsw i32 0, %a
45  %cond = select i1 %cmp, i32 %a, i32 %neg
46  ret i32 %cond
47}
48
49define i32@foo5(i32 %a, i32 %b) nounwind ssp {
50entry:
51; CHECK-LABEL: foo5
52; CHECK: subs
53; CHECK-NEXT: cneg
54; CHECK-NEXT: ret
55  %sub = sub nsw i32 %a, %b
56  %cmp = icmp sgt i32 %sub, -1
57  %sub3 = sub nsw i32 0, %sub
58  %cond = select i1 %cmp, i32 %sub, i32 %sub3
59  ret i32 %cond
60}
61
62; make sure we can handle branch instruction in optimizeCompare.
63define i32@foo6(i32 %a, i32 %b) nounwind ssp {
64; CHECK-LABEL: foo6
65; CHECK: b
66  %sub = sub nsw i32 %a, %b
67  %cmp = icmp sgt i32 %sub, 0
68  br i1 %cmp, label %l.if, label %l.else
69
70l.if:
71  ret i32 1
72
73l.else:
74  ret i32 %sub
75}
76
77; If CPSR is used multiple times and V flag is used, we don't remove cmp.
78define i32 @foo7(i32 %a, i32 %b) nounwind {
79entry:
80; CHECK-LABEL: foo7:
81; CHECK: sub
82; FIXME: Misspelled CHECK-NEXT
83; CHECK-next: adds
84; CHECK-next: csneg
85; CHECK-next: b
86  %sub = sub nsw i32 %a, %b
87  %cmp = icmp sgt i32 %sub, -1
88  %sub3 = sub nsw i32 0, %sub
89  %cond = select i1 %cmp, i32 %sub, i32 %sub3
90  br i1 %cmp, label %if.then, label %if.else
91
92if.then:
93  %cmp2 = icmp slt i32 %sub, -1
94  %sel = select i1 %cmp2, i32 %cond, i32 %a
95  ret i32 %sel
96
97if.else:
98  ret i32 %cond
99}
100
101define i32 @foo8(i32 %v, i32 %a, i32 %b) nounwind readnone ssp {
102entry:
103; CHECK-LABEL: foo8:
104; CHECK: cmp w0, #0
105; CHECK: csinv w0, w1, w2, ne
106  %tobool = icmp eq i32 %v, 0
107  %neg = xor i32 -1, %b
108  %cond = select i1 %tobool, i32 %neg, i32 %a
109  ret i32 %cond
110}
111
112define i32 @foo9(i32 %v) nounwind readnone optsize ssp {
113entry:
114; CHECK-LABEL: foo9:
115; CHECK: cmp w0, #0
116; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4
117; CHECK: cinv w0, w[[REG]], eq
118  %tobool = icmp ne i32 %v, 0
119  %cond = select i1 %tobool, i32 4, i32 -5
120  ret i32 %cond
121}
122
123define i64 @foo10(i64 %v) nounwind readnone optsize ssp {
124entry:
125; CHECK-LABEL: foo10:
126; CHECK: cmp x0, #0
127; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4
128; CHECK: cinv x0, x[[REG]], eq
129  %tobool = icmp ne i64 %v, 0
130  %cond = select i1 %tobool, i64 4, i64 -5
131  ret i64 %cond
132}
133
134define i32 @foo11(i32 %v) nounwind readnone optsize ssp {
135entry:
136; CHECK-LABEL: foo11:
137; CHECK: cmp w0, #0
138; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4
139; CHECK: cneg w0, w[[REG]], eq
140  %tobool = icmp ne i32 %v, 0
141  %cond = select i1 %tobool, i32 4, i32 -4
142  ret i32 %cond
143}
144
145define i64 @foo12(i64 %v) nounwind readnone optsize ssp {
146entry:
147; CHECK-LABEL: foo12:
148; CHECK: cmp x0, #0
149; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4
150; CHECK: cneg x0, x[[REG]], eq
151  %tobool = icmp ne i64 %v, 0
152  %cond = select i1 %tobool, i64 4, i64 -4
153  ret i64 %cond
154}
155
156define i32 @foo13(i32 %v, i32 %a, i32 %b) nounwind readnone optsize ssp {
157entry:
158; CHECK-LABEL: foo13:
159; CHECK: cmp w0, #0
160; CHECK: csneg w0, w1, w2, ne
161  %tobool = icmp eq i32 %v, 0
162  %sub = sub i32 0, %b
163  %cond = select i1 %tobool, i32 %sub, i32 %a
164  ret i32 %cond
165}
166
167define i64 @foo14(i64 %v, i64 %a, i64 %b) nounwind readnone optsize ssp {
168entry:
169; CHECK-LABEL: foo14:
170; CHECK: cmp x0, #0
171; CHECK: csneg x0, x1, x2, ne
172  %tobool = icmp eq i64 %v, 0
173  %sub = sub i64 0, %b
174  %cond = select i1 %tobool, i64 %sub, i64 %a
175  ret i64 %cond
176}
177
178define i32 @foo15(i32 %a, i32 %b) nounwind readnone optsize ssp {
179entry:
180; CHECK-LABEL: foo15:
181; CHECK: cmp w0, w1
182; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1
183; CHECK: cinc w0, w[[REG]], gt
184  %cmp = icmp sgt i32 %a, %b
185  %. = select i1 %cmp, i32 2, i32 1
186  ret i32 %.
187}
188
189define i32 @foo16(i32 %a, i32 %b) nounwind readnone optsize ssp {
190entry:
191; CHECK-LABEL: foo16:
192; CHECK: cmp w0, w1
193; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1
194; CHECK: cinc w0, w[[REG]], le
195  %cmp = icmp sgt i32 %a, %b
196  %. = select i1 %cmp, i32 1, i32 2
197  ret i32 %.
198}
199
200define i64 @foo17(i64 %a, i64 %b) nounwind readnone optsize ssp {
201entry:
202; CHECK-LABEL: foo17:
203; CHECK: cmp x0, x1
204; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1
205; CHECK: cinc x0, x[[REG]], gt
206  %cmp = icmp sgt i64 %a, %b
207  %. = select i1 %cmp, i64 2, i64 1
208  ret i64 %.
209}
210
211define i64 @foo18(i64 %a, i64 %b) nounwind readnone optsize ssp {
212entry:
213; CHECK-LABEL: foo18:
214; CHECK: cmp x0, x1
215; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1
216; CHECK: cinc x0, x[[REG]], le
217  %cmp = icmp sgt i64 %a, %b
218  %. = select i1 %cmp, i64 1, i64 2
219  ret i64 %.
220}
221
222define i64 @foo19(i64 %a, i64 %b, i64 %c) {
223entry:
224; CHECK-LABEL: foo19:
225; CHECK: cinc x0, x2
226; CHECK-NOT: add
227  %cmp = icmp ult i64 %a, %b
228  %inc = zext i1 %cmp to i64
229  %inc.c = add i64 %inc, %c
230  ret i64 %inc.c
231}
232
233define i32 @foo20(i32 %x) {
234; CHECK-LABEL: foo20:
235; CHECK: cmp w0, #5
236; CHECK: orr w[[REG:[0-9]+]], wzr, #0x6
237; CHECK: csinc w0, w[[REG]], wzr, eq
238  %cmp = icmp eq i32 %x, 5
239  %res = select i1 %cmp, i32 6, i32 1
240  ret i32 %res
241}
242
243define i64 @foo21(i64 %x) {
244; CHECK-LABEL: foo21:
245; CHECK: cmp x0, #5
246; CHECK: orr w[[REG:[0-9]+]], wzr, #0x6
247; CHECK: csinc x0, x[[REG]], xzr, eq
248  %cmp = icmp eq i64 %x, 5
249  %res = select i1 %cmp, i64 6, i64 1
250  ret i64 %res
251}
252
253define i32 @foo22(i32 %x) {
254; CHECK-LABEL: foo22:
255; CHECK: cmp w0, #5
256; CHECK: orr w[[REG:[0-9]+]], wzr, #0x6
257; CHECK: csinc w0, w[[REG]], wzr, ne
258  %cmp = icmp eq i32 %x, 5
259  %res = select i1 %cmp, i32 1, i32 6
260  ret i32 %res
261}
262
263define i64 @foo23(i64 %x) {
264; CHECK-LABEL: foo23:
265; CHECK: cmp x0, #5
266; CHECK: orr w[[REG:[0-9]+]], wzr, #0x6
267; CHECK: csinc x0, x[[REG]], xzr, ne
268  %cmp = icmp eq i64 %x, 5
269  %res = select i1 %cmp, i64 1, i64 6
270  ret i64 %res
271}
272