[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / GlobalISel / postlegalizer-combiner-and-trivial-mask.mir
blob93e5b4c4ba06457e970b8315b7266edf5a16ba78
1 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
3 # Check that we can fold (x & mask) -> x when (x & mask) is known to equal x.
5 # RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
7 ---
8 name:            remove_and_with_one_bit
9 legalized:       true
10 tracksRegLiveness: true
11 body:             |
12   bb.0:
13     liveins: $w0, $w1
14     ; G_ICMP produces a single bit. The mask is 1.
15     ;
16     ; cmp = 000...0?
17     ; mask = 000...01
18     ; cmp & mask = 000...0?
19     ;
20     ; Remove the G_AND.
21     ;
22     ; CHECK-LABEL: name: remove_and_with_one_bit
23     ; CHECK: liveins: $w0, $w1
24     ; CHECK: %x:_(s32) = COPY $w0
25     ; CHECK: %y:_(s32) = COPY $w1
26     ; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
27     ; CHECK: $w0 = COPY %cmp(s32)
28     ; CHECK: RET_ReallyLR implicit $w0
29     %x:_(s32) = COPY $w0
30     %y:_(s32) = COPY $w1
31     %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
32     %mask:_(s32) = G_CONSTANT i32 1
33     %and:_(s32) = G_AND %cmp(s32), %mask
34     $w0 = COPY %and(s32)
35     RET_ReallyLR implicit $w0
37 ...
38 ---
39 name:            remove_and_all_ones_mask
40 legalized:       true
41 tracksRegLiveness: true
42 body:             |
43   bb.0:
44     liveins: $w0, $w1, $w2
45     ; -1 is all ones. Therefore z & -1 = z. Remove the G_AND.
46     ;
47     ; CHECK-LABEL: name: remove_and_all_ones_mask
48     ; CHECK: liveins: $w0, $w1, $w2
49     ; CHECK: %z:_(s32) = COPY $w2
50     ; CHECK: $w0 = COPY %z(s32)
51     ; CHECK: RET_ReallyLR implicit $w0
52     %x:_(s32) = COPY $w0
53     %y:_(s32) = COPY $w1
54     %z:_(s32) = COPY $w2
55     %mask:_(s32) = G_CONSTANT i32 -1
56     %and:_(s32) = G_AND %z(s32), %mask
57     $w0 = COPY %and(s32)
58     RET_ReallyLR implicit $w0
60 ...
61 ---
62 name:            remove_and_all_ones_zext
63 legalized:       true
64 tracksRegLiveness: true
65 body:             |
66   bb.0:
67     liveins: $w0, $w1, $w2
68     ; %z is a s32, so it can be at most the all-ones value on 32 bits.
69     ; In decimal this is 4294967295. Any zero-extension of %z is at most this
70     ; value.
71     ;
72     ; Therefore, zext(z) & 4294967295 == z. Remove the G_AND.
73     ;
74     ; CHECK-LABEL: name: remove_and_all_ones_zext
75     ; CHECK: liveins: $w0, $w1, $w2
76     ; CHECK: %z:_(s32) = COPY $w2
77     ; CHECK: %ext:_(s64) = G_ZEXT %z(s32)
78     ; CHECK: $x0 = COPY %ext(s64)
79     ; CHECK: RET_ReallyLR implicit $x0
80     %x:_(s32) = COPY $w0
81     %y:_(s32) = COPY $w1
82     %z:_(s32) = COPY $w2
83     %ext:_(s64) = G_ZEXT %z
84     %mask:_(s64) = G_CONSTANT i64 4294967295
85     %and:_(s64) = G_AND %ext(s64), %mask
86     $x0 = COPY %and(s64)
87     RET_ReallyLR implicit $x0
89 ...
90 ---
91 name:            remove_and_all_ones_anyext
92 legalized:       true
93 tracksRegLiveness: true
94 body:             |
95   bb.0:
96     liveins: $w0, $w1, $w2
97     ; This is the same as the zext case.
98     ;
99     ; CHECK-LABEL: name: remove_and_all_ones_anyext
100     ; CHECK: liveins: $w0, $w1, $w2
101     ; CHECK: %z:_(s32) = COPY $w2
102     ; CHECK: %ext:_(s64) = G_ZEXT %z(s32)
103     ; CHECK: $x0 = COPY %ext(s64)
104     ; CHECK: RET_ReallyLR implicit $x0
105     %x:_(s32) = COPY $w0
106     %y:_(s32) = COPY $w1
107     %z:_(s32) = COPY $w2
108     %ext:_(s64) = G_ZEXT %z
109     %mask:_(s64) = G_CONSTANT i64 4294967295
110     %and:_(s64) = G_AND %ext(s64), %mask
111     $x0 = COPY %and(s64)
112     RET_ReallyLR implicit $x0
116 name:            dont_remove_all_ones_sext
117 legalized:       true
118 tracksRegLiveness: true
119 body:             |
120   bb.0:
121     liveins: $w0, $w1, $w2
122     ; We don't know if the sign bit is set on %z. So, the value in %ext may have
123     ; higher bits set than 4294967295.
124     ;
125     ; CHECK-LABEL: name: dont_remove_all_ones_sext
126     ; CHECK: liveins: $w0, $w1, $w2
127     ; CHECK: %z:_(s32) = COPY $w2
128     ; CHECK: %ext:_(s64) = G_SEXT %z(s32)
129     ; CHECK: %mask:_(s64) = G_CONSTANT i64 4294967295
130     ; CHECK: %and:_(s64) = G_AND %ext, %mask
131     ; CHECK: $x0 = COPY %and(s64)
132     ; CHECK: RET_ReallyLR implicit $x0
133     %x:_(s32) = COPY $w0
134     %y:_(s32) = COPY $w1
135     %z:_(s32) = COPY $w2
136     %ext:_(s64) = G_SEXT %z
137     %mask:_(s64) = G_CONSTANT i64 4294967295
138     %and:_(s64) = G_AND %ext(s64), %mask
139     $x0 = COPY %and(s64)
140     RET_ReallyLR implicit $x0
144 name:            remove_and_positive_constant_sext
145 legalized:       true
146 tracksRegLiveness: true
147 body:             |
148   bb.0:
149     liveins: $w0, $w1, $w2
150     ; We know the sign bit is not set on %z. Therefore,
151     ;
152     ; z = ext = 42 = 000...0101010
153     ; mask = 0000...0111111
154     ;
155     ; So z & mask == z
156     ; CHECK-LABEL: name: remove_and_positive_constant_sext
157     ; CHECK: liveins: $w0, $w1, $w2
158     ; CHECK: %z:_(s32) = G_CONSTANT i32 42
159     ; CHECK: %ext:_(s64) = G_SEXT %z(s32)
160     ; CHECK: $x0 = COPY %ext(s64)
161     ; CHECK: RET_ReallyLR implicit $x0
162     %x:_(s32) = COPY $w0
163     %y:_(s32) = COPY $w1
164     %z:_(s32) = G_CONSTANT i32 42
165     %ext:_(s64) = G_SEXT %z
166     %mask:_(s64) = G_CONSTANT i64 63
167     %and:_(s64) = G_AND %ext(s64), %mask
168     $x0 = COPY %and(s64)
169     RET_ReallyLR implicit $x0
173 name:            not_a_mask
174 legalized:       true
175 tracksRegLiveness: true
176 body:             |
177   bb.0:
178     liveins: $w0, $w1
179     ; 6 is not a mask, so we should still have the G_AND.
180     ;
181     ; CHECK-LABEL: name: not_a_mask
182     ; CHECK: liveins: $w0, $w1
183     ; CHECK: %x:_(s32) = COPY $w0
184     ; CHECK: %y:_(s32) = COPY $w1
185     ; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
186     ; CHECK: %mask:_(s32) = G_CONSTANT i32 6
187     ; CHECK: %and:_(s32) = G_AND %cmp, %mask
188     ; CHECK: $w0 = COPY %and(s32)
189     ; CHECK: RET_ReallyLR implicit $w0
190     %x:_(s32) = COPY $w0
191     %y:_(s32) = COPY $w1
192     %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
193     %mask:_(s32) = G_CONSTANT i32 6
194     %and:_(s32) = G_AND %cmp(s32), %mask
195     $w0 = COPY %and(s32)
196     RET_ReallyLR implicit $w0
200 name:            unknown_val
201 legalized:       true
202 tracksRegLiveness: true
203 body:             |
204   bb.0:
205     liveins: $w0, $w1, $w2
206     ; We don't know what's in $w2, so we can't remove the G_AND without a mask
207     ; that fills every bit in the type.
208     ;
209     ; CHECK-LABEL: name: unknown_val
210     ; CHECK: liveins: $w0, $w1, $w2
211     ; CHECK: %z:_(s32) = COPY $w2
212     ; CHECK: %one:_(s32) = G_CONSTANT i32 32
213     ; CHECK: %and:_(s32) = G_AND %z, %one
214     ; CHECK: $w0 = COPY %and(s32)
215     ; CHECK: RET_ReallyLR implicit $w0
216     %x:_(s32) = COPY $w0
217     %y:_(s32) = COPY $w1
218     %z:_(s32) = COPY $w2
219     %one:_(s32) = G_CONSTANT i32 32
220     %and:_(s32) = G_AND %z(s32), %one
221     $w0 = COPY %and(s32)
222     RET_ReallyLR implicit $w0
225 name:            remove_and_assert_zext
226 legalized:       true
227 tracksRegLiveness: true
228 body:             |
229   bb.0:
230     liveins: $w0
231     ; G_ASSERT_ZEXT communicates that only the bottom 8 bits of %x can be set.
232     ; So, the G_AND can be removed.
234     ; CHECK-LABEL: name: remove_and_assert_zext
235     ; CHECK: liveins: $w0
236     ; CHECK: %x:_(s32) = COPY $w0
237     ; CHECK: %assert_zext:_(s32) = G_ASSERT_ZEXT %x, 8
238     ; CHECK: $w0 = COPY %assert_zext(s32)
239     ; CHECK: RET_ReallyLR implicit $w0
240     %x:_(s32) = COPY $w0
241     %assert_zext:_(s32) = G_ASSERT_ZEXT %x(s32), 8
242     %mask:_(s32) = G_CONSTANT i32 255
243     %and:_(s32) = G_AND %assert_zext(s32), %mask
244     $w0 = COPY %and(s32)
245     RET_ReallyLR implicit $w0
248 name:            dont_remove_and_assert_zext_wrong_mask
249 legalized:       true
250 tracksRegLiveness: true
251 body:             |
252   bb.0:
253     liveins: $w0
254     ; The mask here is for 8 bits, not 16.
256     ; CHECK-LABEL: name: dont_remove_and_assert_zext
257     ; CHECK: liveins: $w0
258     ; CHECK: %x:_(s32) = COPY $w0
259     ; CHECK: %assert_zext:_(s32) = G_ASSERT_ZEXT %x, 16
260     ; CHECK: %mask:_(s32) = G_CONSTANT i32 255
261     ; CHECK: %and:_(s32) = G_AND %assert_zext, %mask
262     ; CHECK: $w0 = COPY %and(s32)
263     ; CHECK: RET_ReallyLR implicit $w0
264     %x:_(s32) = COPY $w0
265     %assert_zext:_(s32) = G_ASSERT_ZEXT %x(s32), 16
266     %mask:_(s32) = G_CONSTANT i32 255
267     %and:_(s32) = G_AND %assert_zext(s32), %mask
268     $w0 = COPY %and(s32)
269     RET_ReallyLR implicit $w0