[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / GlobalISel / prelegalizercombiner-extending-loads-cornercases.mir
blob9128cb88c6b6ee58a5cd9c33c87f8f9edc32879f
1 # RUN: llc -O0 -run-pass=aarch64-prelegalizer-combiner -global-isel %s -o - | FileCheck %s
2 # RUN: llc -O0 -run-pass=aarch64-prelegalizer-combiner -global-isel %s -o - \
3 # RUN:   -debug-only=aarch64-prelegalizer-combiner,gi-combiner 2>&1 >/dev/null \
4 # RUN:   | FileCheck %s --check-prefix=CHECK-WORKLIST
6 # REQUIRES: asserts
8 --- |
9   target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
10   target triple = "aarch64--"
12   define void @multiple_copies(i8* %addr) {
13   entry:
14     br i1 0, label %if, label %else
15   if:
16     br label %exit
17   else:
18     br label %exit
19   exit:
20     ret void
21   }
23   define void @sink_to_phi_trivially_dominating(i8* %addr) {
24   entry:
25     br i1 0, label %if, label %exit
26   if:
27     br label %exit
28   exit:
29     ret void
30   }
32   define void @sink_to_phi_nondominating(i8* %addr) {
33   entry:
34     br i1 0, label %if, label %else
35   if:
36     br label %exit
37   else:
38     br label %exit
39   exit:
40     ret void
41   }
43   define void @sink_to_phi_emptyblock(i8* %addr) {
44   entry:
45     br i1 0, label %if, label %else
46   if:
47     br label %exit
48   else:
49     br label %else2
50   else2:
51     br label %exit
52   exit:
53     ret void
54   }
56   define void @use_doesnt_def_anything(i8* %addr) {
57   entry:
58     ret void
59   }
61   define void @op0_isnt_a_reg(i8* %addr) {
62   entry:
63     ret void
64   }
65 ...
67 ---
68 name:            multiple_copies
69 # CHECK-LABEL: name: multiple_copies
70 tracksRegLiveness: true
71 body: |
72   bb.0.entry:
73     liveins: $x0, $w1
74     successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)
75     ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD
76     %0:_(p0) = COPY $x0
77     %1:_(s32) = COPY $w1
78     %2:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
79     %3:_(s32) = G_SEXT %2
80     %4:_(s32) = G_CONSTANT i32 1
81     %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_
82     G_BRCOND %5:_(s1), %bb.1
83     G_BR %bb.2.else
84   bb.1.if:
85   ; CHECK: bb.1.if:
86     successors: %bb.3(0x80000000)
87     %10:_(s8) = G_CONSTANT i8 1
88     ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
89     %6:_(s8) = G_ADD %2, %10
90     ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}
91     G_BR %bb.3.exit
92   bb.2.else:
93   ; CHECK: bb.2.else:
94     successors: %bb.3(0x80000000)
95     %11:_(s8) = G_CONSTANT i8 1
96     ; CHECK: [[T3:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
97     %7:_(s8) = G_SUB %2, %11
98     ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_SUB [[T3]], {{.*}}
99     G_BR %bb.3.exit
100   bb.3.exit:
101   ; CHECK: bb.3.exit:
102     %8:_(s8) = G_PHI %6:_(s8), %bb.1, %7:_(s8), %bb.2
103     ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)
104     %9:_(s32) = G_ZEXT %8
105     ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)
106     ; CHECK: $w0 = COPY [[T0]](s32)
107     ; CHECK: $w1 = COPY [[T6]](s32)
108     $w0 = COPY %3
109     $w1 = COPY %9
111 # Check that we report the correct modifications to the observer. This acts as
112 # a test of the debug output and a test.
114 # CHECK-WORKLIST-LABEL: Generic MI Combiner for: multiple_copies
115 # CHECK-WORKLIST:       Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0) :: (load 1 from %ir.addr)
116 # CHECK-WORKLIST:       Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)
117 # CHECK-WORKLIST-DAG:   Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
118 # CHECK-WORKLIST-DAG:   Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_
119 # CHECK-WORKLIST-DAG:   Changed: [[IN3]]:_(s8) = G_ADD [[NEW1:%[0-9]+]]:_, [[IN4]]:_
120 # CHECK-WORKLIST-DAG:   Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_
121 # CHECK-WORKLIST-DAG:   Changed: [[IN5]]:_(s8) = G_SUB [[NEW2:%[0-9]+]]:_, [[IN6]]:_
122 # CHECK-WORKLIST-DAG:   Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)
123 # CHECK-WORKLIST-DAG:   Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
124 # CHECK-WORKLIST-DAG:   Created: [[NEW1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
125 # CHECK-WORKLIST-DAG:   Created: [[NEW2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
126 # CHECK-WORKLIST:       Try combining
130 name:            sink_to_phi_trivially_dominating
131 # CHECK-LABEL: name: sink_to_phi_trivially_dominating
132 # This test currently tests that we don't sink if we would sink to a phi. This
133 # is needed to avoid inserting into the middle of the leading G_PHI instructions
134 # of a BB
135 tracksRegLiveness: true
136 body: |
137   bb.0.entry:
138     liveins: $x0, $w1
139     successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)
140     ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD
141     %0:_(p0) = COPY $x0
142     %1:_(s32) = COPY $w1
143     %2:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
144     ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
145     %3:_(s32) = G_SEXT %2
146     %4:_(s32) = G_CONSTANT i32 1
147     %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_
148     G_BRCOND %5:_(s1), %bb.1
149     G_BR %bb.2.exit
150   bb.1.if:
151   ; CHECK: bb.1.if:
152     successors: %bb.2(0x80000000)
153     %10:_(s8) = G_CONSTANT i8 1
154     ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
155     %6:_(s8) = G_ADD %2, %10
156     ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}
157     G_BR %bb.2.exit
158   bb.2.exit:
159   ; CHECK: bb.2.exit:
160     %8:_(s8) = G_PHI %6:_(s8), %bb.1, %2:_(s8), %bb.0
161     ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)
162     %9:_(s32) = G_ZEXT %8
163     ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)
164     ; CHECK: $w0 = COPY [[T0]](s32)
165     ; CHECK: $w1 = COPY [[T6]](s32)
166     $w0 = COPY %3
167     $w1 = COPY %9
171 name:            sink_to_phi_nondominating
172 # CHECK-LABEL: name: sink_to_phi_nondominating
173 tracksRegLiveness: true
174 body: |
175   bb.0.entry:
176     liveins: $x0, $w1
177     successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)
178     ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD
179     %0:_(p0) = COPY $x0
180     %1:_(s32) = COPY $w1
181     %2:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
182     %3:_(s32) = G_CONSTANT i32 1
183     %4:_(s1) = G_ICMP intpred(ne), %1:_(s32), %3:_
184     G_BRCOND %4:_(s1), %bb.1
185     G_BR %bb.2.else
186   bb.1.if:
187   ; CHECK: bb.1.if:
188     successors: %bb.3(0x80000000)
189     %5:_(s8) = G_CONSTANT i8 1
190     ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
191     %6:_(s8) = G_ADD %2, %5
192     ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}
193     G_BR %bb.3.exit
194   bb.2.else:
195   ; CHECK: bb.2.else:
196     successors: %bb.3(0x80000000)
197     %7:_(s8) = G_CONSTANT i8 1
198     ; CHECK: [[T3:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
199     %8:_(s8) = G_SUB %2, %7
200     ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_SUB [[T3]], {{.*}}
201     G_BR %bb.3.exit
202   bb.3.exit:
203   ; CHECK: bb.3.exit:
204     %9:_(s8) = G_PHI %6:_(s8), %bb.1, %8:_(s8), %bb.2
205     ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)
206     %10:_(s32) = G_SEXT %2
207     %11:_(s32) = G_ZEXT %9
208     ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)
209     ; CHECK: $w0 = COPY [[T0]](s32)
210     ; CHECK: $w1 = COPY [[T6]](s32)
211     $w0 = COPY %10
212     $w1 = COPY %11
213 # CHECK-WORKLIST-LABEL: Generic MI Combiner for: sink_to_phi_nondominating
214 # CHECK-WORKLIST:       Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0) :: (load 1 from %ir.addr)
215 # CHECK-WORKLIST:       Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)
216 # CHECK-WORKLIST-DAG:   Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
217 # CHECK-WORKLIST-DAG:   Creating: G_TRUNC
218 # CHECK-WORKLIST-DAG:   Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_
219 # CHECK-WORKLIST-DAG:   Changed: [[IN3]]:_(s8) = G_ADD [[OUT1:%[0-9]+]]:_, [[IN4]]:_
220 # CHECK-WORKLIST-DAG:   Creating: G_TRUNC
221 # CHECK-WORKLIST-DAG:   Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_
222 # CHECK-WORKLIST-DAG:   Changed: [[IN5]]:_(s8) = G_SUB [[OUT2:%[0-9]+]]:_, [[IN6]]:_
223 # CHECK-WORKLIST-DAG:   Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)
224 # CHECK-WORKLIST-DAG:   Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
225 # CHECK-WORKLIST-DAG:   Created: [[OUT1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
226 # CHECK-WORKLIST-DAG:   Created: [[OUT2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
227 # CHECK-WORKLIST:       Try combining
231 name:            sink_to_phi_emptyblock
232 # CHECK-LABEL: name: sink_to_phi_emptyblock
233 tracksRegLiveness: true
234 body: |
235   bb.0.entry:
236     liveins: $x0, $w1
237     successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)
238     ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD
239     %0:_(p0) = COPY $x0
240     %1:_(s32) = COPY $w1
241     %2:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
242     %3:_(s32) = G_SEXT %2
243     %4:_(s32) = G_CONSTANT i32 1
244     %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_
245     G_BRCOND %5:_(s1), %bb.1
246     G_BR %bb.2.else
247   bb.1.if:
248   ; CHECK: bb.1.if:
249     successors: %bb.4(0x80000000)
250     %10:_(s8) = G_CONSTANT i8 1
251     ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
252     %6:_(s8) = G_ADD %2, %10
253     ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}
254     G_BR %bb.4.exit
255   bb.2.else:
256   ; CHECK: bb.2.else:
257     successors: %bb.3(0x80000000)
258     G_BR %bb.3.else2
259   bb.3.else2:
260   ; CHECK: bb.3.else2:
261     successors: %bb.4(0x80000000)
262     ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)
263     ; Fallthrough
264   bb.4.exit:
265   ; CHECK: bb.4.exit:
266     %8:_(s8) = G_PHI %6:_(s8), %bb.1, %2:_(s8), %bb.3
267     ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)
268     %9:_(s32) = G_ZEXT %8
269     ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)
270     ; CHECK: $w0 = COPY [[T0]](s32)
271     ; CHECK: $w1 = COPY [[T6]](s32)
272     $w0 = COPY %3
273     $w1 = COPY %9
277 name:            use_doesnt_def_anything
278 # CHECK-LABEL: name: use_doesnt_def_anything
279 # Check that we don't crash when inspecting a use that doesn't define anything.
280 # The real issue which was that the combine rule was looking through
281 # non-truncates as if they were truncates and attempting to obtain the result
282 # register. It would usually go on to make the right overall decision anyway but
283 # would sometimes crash on things like (SOME_INTRINSIC imm). This test covers
284 # the case that it would recover from.
285 tracksRegLiveness: true
286 body: |
287   bb.0.entry:
288     liveins: $x0, $w1
289     %0:_(p0) = COPY $x0
290     %1:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
291     ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr)
292     G_STORE %1(s8), %0(p0) :: (store 1 into %ir.addr)
293     ; CHECK: G_STORE %1(s8), %0(p0) :: (store 1 into %ir.addr)
297 name:            op0_isnt_a_reg
298 # CHECK-LABEL: name: op0_isnt_a_reg
299 # This test covers the variant of use_doesnt_def_anything that would crash.
300 tracksRegLiveness: true
301 body: |
302   bb.0.entry:
303     liveins: $x0, $w1
304     %0:_(p0) = COPY $x0
305     %1:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
306     ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr)
307     G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)
308     ; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)