xref: /llvm-project/llvm/test/CodeGen/AArch64/rm_redundant_cmp.ll (revision 3a8e009f97d2ed4b751365e514e0bf7131c7ab11)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-linux-gnuabi -O2 | FileCheck %s
3
4; The following cases are for i16
5
6%struct.s_signed_i16 = type { i16, i16, i16 }
7%struct.s_unsigned_i16 = type { i16, i16, i16 }
8
9@cost_s_i8_i16 = common global %struct.s_signed_i16 zeroinitializer, align 2
10@cost_u_i16 = common global %struct.s_unsigned_i16 zeroinitializer, align 2
11
12define void @test_i16_2cmp_signed_1() {
13; CHECK-LABEL: test_i16_2cmp_signed_1:
14; CHECK:       // %bb.0: // %entry
15; CHECK-NEXT:    adrp x8, :got:cost_s_i8_i16
16; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_s_i8_i16]
17; CHECK-NEXT:    ldrsh w9, [x8, #2]
18; CHECK-NEXT:    ldrsh w10, [x8, #4]
19; CHECK-NEXT:    cmp w9, w10
20; CHECK-NEXT:    b.lt .LBB0_2
21; CHECK-NEXT:  // %bb.1: // %if.end8.sink.split
22; CHECK-NEXT:    strh w9, [x8]
23; CHECK-NEXT:  .LBB0_2: // %if.end8
24; CHECK-NEXT:    ret
25entry:
26  %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2
27  %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2
28  %cmp = icmp sgt i16 %0, %1
29  br i1 %cmp, label %if.then, label %if.else
30
31if.then:                                          ; preds = %entry
32  store i16 %0, ptr @cost_s_i8_i16, align 2
33  br label %if.end8
34
35if.else:                                          ; preds = %entry
36  %cmp5 = icmp eq i16 %0, %1
37  br i1 %cmp5, label %if.then7, label %if.end8
38
39if.then7:                                         ; preds = %if.else
40  store i16 %0, ptr @cost_s_i8_i16, align 2
41  br label %if.end8
42
43if.end8:                                          ; preds = %if.else, %if.then7, %if.then
44  ret void
45}
46
47define void @test_i16_2cmp_signed_2() {
48; CHECK-LABEL: test_i16_2cmp_signed_2:
49; CHECK:       // %bb.0: // %entry
50; CHECK-NEXT:    adrp x8, :got:cost_s_i8_i16
51; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_s_i8_i16]
52; CHECK-NEXT:    ldrsh w9, [x8, #2]
53; CHECK-NEXT:    ldrsh w10, [x8, #4]
54; CHECK-NEXT:    cmp w9, w10
55; CHECK-NEXT:    b.gt .LBB1_2
56; CHECK-NEXT:  // %bb.1: // %if.else
57; CHECK-NEXT:    mov w9, w10
58; CHECK-NEXT:    b.ge .LBB1_3
59; CHECK-NEXT:  .LBB1_2: // %if.end8.sink.split
60; CHECK-NEXT:    strh w9, [x8]
61; CHECK-NEXT:  .LBB1_3: // %if.end8
62; CHECK-NEXT:    ret
63entry:
64  %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2
65  %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2
66  %cmp = icmp sgt i16 %0, %1
67  br i1 %cmp, label %if.then, label %if.else
68
69if.then:                                          ; preds = %entry
70  store i16 %0, ptr @cost_s_i8_i16, align 2
71  br label %if.end8
72
73if.else:                                          ; preds = %entry
74  %cmp5 = icmp slt i16 %0, %1
75  br i1 %cmp5, label %if.then7, label %if.end8
76
77if.then7:                                         ; preds = %if.else
78  store i16 %1, ptr @cost_s_i8_i16, align 2
79  br label %if.end8
80
81if.end8:                                          ; preds = %if.else, %if.then7, %if.then
82  ret void
83}
84
85define void @test_i16_2cmp_unsigned_1() {
86; CHECK-LABEL: test_i16_2cmp_unsigned_1:
87; CHECK:       // %bb.0: // %entry
88; CHECK-NEXT:    adrp x8, :got:cost_u_i16
89; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_u_i16]
90; CHECK-NEXT:    ldrh w9, [x8, #2]
91; CHECK-NEXT:    ldrh w10, [x8, #4]
92; CHECK-NEXT:    cmp w9, w10
93; CHECK-NEXT:    b.lo .LBB2_2
94; CHECK-NEXT:  // %bb.1: // %if.end8.sink.split
95; CHECK-NEXT:    strh w9, [x8]
96; CHECK-NEXT:  .LBB2_2: // %if.end8
97; CHECK-NEXT:    ret
98entry:
99  %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2
100  %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2
101  %cmp = icmp ugt i16 %0, %1
102  br i1 %cmp, label %if.then, label %if.else
103
104if.then:                                          ; preds = %entry
105  store i16 %0, ptr @cost_u_i16, align 2
106  br label %if.end8
107
108if.else:                                          ; preds = %entry
109  %cmp5 = icmp eq i16 %0, %1
110  br i1 %cmp5, label %if.then7, label %if.end8
111
112if.then7:                                         ; preds = %if.else
113  store i16 %0, ptr @cost_u_i16, align 2
114  br label %if.end8
115
116if.end8:                                          ; preds = %if.else, %if.then7, %if.then
117  ret void
118}
119
120define void @test_i16_2cmp_unsigned_2() {
121; CHECK-LABEL: test_i16_2cmp_unsigned_2:
122; CHECK:       // %bb.0: // %entry
123; CHECK-NEXT:    adrp x8, :got:cost_u_i16
124; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_u_i16]
125; CHECK-NEXT:    ldrh w9, [x8, #2]
126; CHECK-NEXT:    ldrh w10, [x8, #4]
127; CHECK-NEXT:    cmp w9, w10
128; CHECK-NEXT:    b.hi .LBB3_2
129; CHECK-NEXT:  // %bb.1: // %if.else
130; CHECK-NEXT:    mov w9, w10
131; CHECK-NEXT:    b.hs .LBB3_3
132; CHECK-NEXT:  .LBB3_2: // %if.end8.sink.split
133; CHECK-NEXT:    strh w9, [x8]
134; CHECK-NEXT:  .LBB3_3: // %if.end8
135; CHECK-NEXT:    ret
136entry:
137  %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2
138  %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2
139  %cmp = icmp ugt i16 %0, %1
140  br i1 %cmp, label %if.then, label %if.else
141
142if.then:                                          ; preds = %entry
143  store i16 %0, ptr @cost_u_i16, align 2
144  br label %if.end8
145
146if.else:                                          ; preds = %entry
147  %cmp5 = icmp ult i16 %0, %1
148  br i1 %cmp5, label %if.then7, label %if.end8
149
150if.then7:                                         ; preds = %if.else
151  store i16 %1, ptr @cost_u_i16, align 2
152  br label %if.end8
153
154if.end8:                                          ; preds = %if.else, %if.then7, %if.then
155  ret void
156}
157
158; The following cases are for i8
159
160%struct.s_signed_i8 = type { i8, i8, i8 }
161%struct.s_unsigned_i8 = type { i8, i8, i8 }
162
163@cost_s = common global %struct.s_signed_i8 zeroinitializer, align 2
164@cost_u_i8 = common global %struct.s_unsigned_i8 zeroinitializer, align 2
165
166
167define void @test_i8_2cmp_signed_1() {
168; CHECK-LABEL: test_i8_2cmp_signed_1:
169; CHECK:       // %bb.0: // %entry
170; CHECK-NEXT:    adrp x8, :got:cost_s
171; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_s]
172; CHECK-NEXT:    ldrsb w9, [x8, #1]
173; CHECK-NEXT:    ldrsb w10, [x8, #2]
174; CHECK-NEXT:    cmp w9, w10
175; CHECK-NEXT:    b.lt .LBB4_2
176; CHECK-NEXT:  // %bb.1: // %if.end8.sink.split
177; CHECK-NEXT:    strb w9, [x8]
178; CHECK-NEXT:  .LBB4_2: // %if.end8
179; CHECK-NEXT:    ret
180entry:
181  %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2
182  %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2
183  %cmp = icmp sgt i8 %0, %1
184  br i1 %cmp, label %if.then, label %if.else
185
186if.then:                                          ; preds = %entry
187  store i8 %0, ptr @cost_s, align 2
188  br label %if.end8
189
190if.else:                                          ; preds = %entry
191  %cmp5 = icmp eq i8 %0, %1
192  br i1 %cmp5, label %if.then7, label %if.end8
193
194if.then7:                                         ; preds = %if.else
195  store i8 %0, ptr @cost_s, align 2
196  br label %if.end8
197
198if.end8:                                          ; preds = %if.else, %if.then7, %if.then
199  ret void
200}
201
202define void @test_i8_2cmp_signed_2() {
203; CHECK-LABEL: test_i8_2cmp_signed_2:
204; CHECK:       // %bb.0: // %entry
205; CHECK-NEXT:    adrp x8, :got:cost_s
206; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_s]
207; CHECK-NEXT:    ldrsb w9, [x8, #1]
208; CHECK-NEXT:    ldrsb w10, [x8, #2]
209; CHECK-NEXT:    cmp w9, w10
210; CHECK-NEXT:    b.gt .LBB5_2
211; CHECK-NEXT:  // %bb.1: // %if.else
212; CHECK-NEXT:    mov w9, w10
213; CHECK-NEXT:    b.ge .LBB5_3
214; CHECK-NEXT:  .LBB5_2: // %if.end8.sink.split
215; CHECK-NEXT:    strb w9, [x8]
216; CHECK-NEXT:  .LBB5_3: // %if.end8
217; CHECK-NEXT:    ret
218entry:
219  %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2
220  %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2
221  %cmp = icmp sgt i8 %0, %1
222  br i1 %cmp, label %if.then, label %if.else
223
224if.then:                                          ; preds = %entry
225  store i8 %0, ptr @cost_s, align 2
226  br label %if.end8
227
228if.else:                                          ; preds = %entry
229  %cmp5 = icmp slt i8 %0, %1
230  br i1 %cmp5, label %if.then7, label %if.end8
231
232if.then7:                                         ; preds = %if.else
233  store i8 %1, ptr @cost_s, align 2
234  br label %if.end8
235
236if.end8:                                          ; preds = %if.else, %if.then7, %if.then
237  ret void
238}
239
240define void @test_i8_2cmp_unsigned_1() {
241; CHECK-LABEL: test_i8_2cmp_unsigned_1:
242; CHECK:       // %bb.0: // %entry
243; CHECK-NEXT:    adrp x8, :got:cost_u_i8
244; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_u_i8]
245; CHECK-NEXT:    ldrb w9, [x8, #1]
246; CHECK-NEXT:    ldrb w10, [x8, #2]
247; CHECK-NEXT:    cmp w9, w10
248; CHECK-NEXT:    b.lo .LBB6_2
249; CHECK-NEXT:  // %bb.1: // %if.end8.sink.split
250; CHECK-NEXT:    strb w9, [x8]
251; CHECK-NEXT:  .LBB6_2: // %if.end8
252; CHECK-NEXT:    ret
253entry:
254  %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2
255  %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2
256  %cmp = icmp ugt i8 %0, %1
257  br i1 %cmp, label %if.then, label %if.else
258
259if.then:                                          ; preds = %entry
260  store i8 %0, ptr @cost_u_i8, align 2
261  br label %if.end8
262
263if.else:                                          ; preds = %entry
264  %cmp5 = icmp eq i8 %0, %1
265  br i1 %cmp5, label %if.then7, label %if.end8
266
267if.then7:                                         ; preds = %if.else
268  store i8 %0, ptr @cost_u_i8, align 2
269  br label %if.end8
270
271if.end8:                                          ; preds = %if.else, %if.then7, %if.then
272  ret void
273}
274
275define void @test_i8_2cmp_unsigned_2() {
276; CHECK-LABEL: test_i8_2cmp_unsigned_2:
277; CHECK:       // %bb.0: // %entry
278; CHECK-NEXT:    adrp x8, :got:cost_u_i8
279; CHECK-NEXT:    ldr x8, [x8, :got_lo12:cost_u_i8]
280; CHECK-NEXT:    ldrb w9, [x8, #1]
281; CHECK-NEXT:    ldrb w10, [x8, #2]
282; CHECK-NEXT:    cmp w9, w10
283; CHECK-NEXT:    b.hi .LBB7_2
284; CHECK-NEXT:  // %bb.1: // %if.else
285; CHECK-NEXT:    mov w9, w10
286; CHECK-NEXT:    b.hs .LBB7_3
287; CHECK-NEXT:  .LBB7_2: // %if.end8.sink.split
288; CHECK-NEXT:    strb w9, [x8]
289; CHECK-NEXT:  .LBB7_3: // %if.end8
290; CHECK-NEXT:    ret
291entry:
292  %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2
293  %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2
294  %cmp = icmp ugt i8 %0, %1
295  br i1 %cmp, label %if.then, label %if.else
296
297if.then:                                          ; preds = %entry
298  store i8 %0, ptr @cost_u_i8, align 2
299  br label %if.end8
300
301if.else:                                          ; preds = %entry
302  %cmp5 = icmp ult i8 %0, %1
303  br i1 %cmp5, label %if.then7, label %if.end8
304
305if.then7:                                         ; preds = %if.else
306  store i8 %1, ptr @cost_u_i8, align 2
307  br label %if.end8
308
309if.end8:                                          ; preds = %if.else, %if.then7, %if.then
310  ret void
311}
312
313; Make sure the case below won't crash.
314
315; The optimization of ZERO_EXTEND and SIGN_EXTEND in type legalization stage can't assert
316; the operand of a set_cc is always a TRUNCATE.
317
318define i1 @foo(float %inl, float %inr) {
319; CHECK-LABEL: foo:
320; CHECK:       // %bb.0:
321; CHECK-NEXT:    fcvtzs w8, s0
322; CHECK-NEXT:    fcvtzs w9, s1
323; CHECK-NEXT:    cmp w8, w9
324; CHECK-NEXT:    cset w0, eq
325; CHECK-NEXT:    ret
326  %lval = fptosi float %inl to i8
327  %rval = fptosi float %inr to i8
328  %sum = icmp eq i8 %lval, %rval
329  ret i1 %sum
330}
331