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
8 name: remove_and_with_one_bit
10 tracksRegLiveness: true
14 ; G_ICMP produces a single bit. The mask is 1.
18 ; cmp & mask = 000...0?
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
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
35 RET_ReallyLR implicit $w0
39 name: remove_and_all_ones_mask
41 tracksRegLiveness: true
44 liveins: $w0, $w1, $w2
45 ; -1 is all ones. Therefore z & -1 = z. Remove the G_AND.
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
55 %mask:_(s32) = G_CONSTANT i32 -1
56 %and:_(s32) = G_AND %z(s32), %mask
58 RET_ReallyLR implicit $w0
62 name: remove_and_all_ones_zext
64 tracksRegLiveness: true
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
72 ; Therefore, zext(z) & 4294967295 == z. Remove the G_AND.
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
83 %ext:_(s64) = G_ZEXT %z
84 %mask:_(s64) = G_CONSTANT i64 4294967295
85 %and:_(s64) = G_AND %ext(s64), %mask
87 RET_ReallyLR implicit $x0
91 name: remove_and_all_ones_anyext
93 tracksRegLiveness: true
96 liveins: $w0, $w1, $w2
97 ; This is the same as the zext case.
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
108 %ext:_(s64) = G_ZEXT %z
109 %mask:_(s64) = G_CONSTANT i64 4294967295
110 %and:_(s64) = G_AND %ext(s64), %mask
112 RET_ReallyLR implicit $x0
116 name: dont_remove_all_ones_sext
118 tracksRegLiveness: true
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.
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
136 %ext:_(s64) = G_SEXT %z
137 %mask:_(s64) = G_CONSTANT i64 4294967295
138 %and:_(s64) = G_AND %ext(s64), %mask
140 RET_ReallyLR implicit $x0
144 name: remove_and_positive_constant_sext
146 tracksRegLiveness: true
149 liveins: $w0, $w1, $w2
150 ; We know the sign bit is not set on %z. Therefore,
152 ; z = ext = 42 = 000...0101010
153 ; mask = 0000...0111111
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
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
169 RET_ReallyLR implicit $x0
175 tracksRegLiveness: true
179 ; 6 is not a mask, so we should still have the G_AND.
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
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
196 RET_ReallyLR implicit $w0
202 tracksRegLiveness: true
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.
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
219 %one:_(s32) = G_CONSTANT i32 32
220 %and:_(s32) = G_AND %z(s32), %one
222 RET_ReallyLR implicit $w0
225 name: remove_and_assert_zext
227 tracksRegLiveness: true
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
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
245 RET_ReallyLR implicit $w0
248 name: dont_remove_and_assert_zext_wrong_mask
250 tracksRegLiveness: true
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
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
269 RET_ReallyLR implicit $w0