1 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2 # RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="bitfield_extract_from_and" -verify-machineinstrs %s -o - | FileCheck %s
5 # Check that we can combine
7 # and (lshr x, cst), mask -> ubfx x, cst, width
12 tracksRegLiveness: true
19 ; Width = LSB + trailing_ones(255) - 1 =
22 ; CHECK-LABEL: name: ubfx_s32
24 ; CHECK: %x:_(s32) = COPY $w0
25 ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
26 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
27 ; CHECK: %and:_(s32) = G_UBFX %x, %lsb(s32), [[C]]
28 ; CHECK: $w0 = COPY %and(s32)
29 ; CHECK: RET_ReallyLR implicit $w0
31 %lsb:_(s32) = G_CONSTANT i32 5
32 %mask:_(s32) = G_CONSTANT i32 255
33 %shift:_(s32) = G_LSHR %x, %lsb
34 %and:_(s32) = G_AND %shift, %mask
36 RET_ReallyLR implicit $w0
41 tracksRegLiveness: true
48 ; Width = LSB + trailing_ones(1) - 1 =
51 ; CHECK-LABEL: name: ubfx_s64
53 ; CHECK: %x:_(s64) = COPY $x0
54 ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
55 ; CHECK: %mask:_(s64) = G_CONSTANT i64 1
56 ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), %mask
57 ; CHECK: $x0 = COPY %and(s64)
58 ; CHECK: RET_ReallyLR implicit $x0
60 %lsb:_(s64) = G_CONSTANT i64 5
61 %mask:_(s64) = G_CONSTANT i64 1
62 %shift:_(s64) = G_LSHR %x, %lsb
63 %and:_(s64) = G_AND %shift, %mask
65 RET_ReallyLR implicit $x0
69 name: dont_combine_no_and_cst
70 tracksRegLiveness: true
76 ; UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants.
78 ; CHECK-LABEL: name: dont_combine_no_and_cst
79 ; CHECK: liveins: $w0, $w1
80 ; CHECK: %x:_(s32) = COPY $w0
81 ; CHECK: %y:_(s32) = COPY $w1
82 ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
83 ; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32)
84 ; CHECK: %and:_(s32) = G_AND %shift, %y
85 ; CHECK: $w0 = COPY %and(s32)
86 ; CHECK: RET_ReallyLR implicit $w0
89 %lsb:_(s32) = G_CONSTANT i32 5
90 %shift:_(s32) = G_LSHR %x, %lsb
91 %and:_(s32) = G_AND %shift, %y
93 RET_ReallyLR implicit $w0
97 name: dont_combine_and_cst_not_mask
98 tracksRegLiveness: true
103 ; CHECK-LABEL: name: dont_combine_and_cst_not_mask
104 ; CHECK: liveins: $w0
105 ; CHECK: %x:_(s32) = COPY $w0
106 ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
107 ; CHECK: %not_a_mask:_(s32) = G_CONSTANT i32 2
108 ; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32)
109 ; CHECK: %and:_(s32) = G_AND %shift, %not_a_mask
110 ; CHECK: $w0 = COPY %and(s32)
111 ; CHECK: RET_ReallyLR implicit $w0
113 %lsb:_(s32) = G_CONSTANT i32 5
114 %not_a_mask:_(s32) = G_CONSTANT i32 2
115 %shift:_(s32) = G_LSHR %x, %lsb
116 %and:_(s32) = G_AND %shift, %not_a_mask
118 RET_ReallyLR implicit $w0
122 name: dont_combine_shift_more_than_one_use
123 tracksRegLiveness: true
128 ; CHECK-LABEL: name: dont_combine_shift_more_than_one_use
129 ; CHECK: liveins: $x0
130 ; CHECK: %x:_(s64) = COPY $x0
131 ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
132 ; CHECK: %mask:_(s64) = G_CONSTANT i64 1
133 ; CHECK: %shift:_(s64) = G_LSHR %x, %lsb(s64)
134 ; CHECK: %and:_(s64) = G_AND %shift, %mask
135 ; CHECK: %sub:_(s64) = G_SUB %and, %shift
136 ; CHECK: $x0 = COPY %sub(s64)
137 ; CHECK: RET_ReallyLR implicit $x0
139 %lsb:_(s64) = G_CONSTANT i64 5
140 %mask:_(s64) = G_CONSTANT i64 1
141 %shift:_(s64) = G_LSHR %x, %lsb
142 %and:_(s64) = G_AND %shift, %mask
143 %sub:_(s64) = G_SUB %and, %shift
145 RET_ReallyLR implicit $x0
149 name: dont_combine_negative_lsb
150 tracksRegLiveness: true
156 ; LSB must be in [0, reg_size)
158 ; CHECK-LABEL: name: dont_combine_negative_lsb
159 ; CHECK: liveins: $w0
160 ; CHECK: %x:_(s32) = COPY $w0
161 ; CHECK: %negative:_(s32) = G_CONSTANT i32 -1
162 ; CHECK: %mask:_(s32) = G_CONSTANT i32 255
163 ; CHECK: %shift:_(s32) = G_LSHR %x, %negative(s32)
164 ; CHECK: %and:_(s32) = G_AND %shift, %mask
165 ; CHECK: $w0 = COPY %and(s32)
166 ; CHECK: RET_ReallyLR implicit $w0
168 %negative:_(s32) = G_CONSTANT i32 -1
169 %mask:_(s32) = G_CONSTANT i32 255
170 %shift:_(s32) = G_LSHR %x, %negative
171 %and:_(s32) = G_AND %shift, %mask
173 RET_ReallyLR implicit $w0
177 name: dont_combine_lsb_too_large
178 tracksRegLiveness: true
184 ; LSB must be in [0, reg_size)
186 ; CHECK-LABEL: name: dont_combine_lsb_too_large
187 ; CHECK: liveins: $w0
188 ; CHECK: %x:_(s32) = COPY $w0
189 ; CHECK: %too_large:_(s32) = G_CONSTANT i32 32
190 ; CHECK: %mask:_(s32) = G_CONSTANT i32 255
191 ; CHECK: %shift:_(s32) = G_LSHR %x, %too_large(s32)
192 ; CHECK: %and:_(s32) = G_AND %shift, %mask
193 ; CHECK: $w0 = COPY %and(s32)
194 ; CHECK: RET_ReallyLR implicit $w0
196 %too_large:_(s32) = G_CONSTANT i32 32
197 %mask:_(s32) = G_CONSTANT i32 255
198 %shift:_(s32) = G_LSHR %x, %too_large
199 %and:_(s32) = G_AND %shift, %mask
201 RET_ReallyLR implicit $w0
205 name: dont_combine_vector
206 tracksRegLiveness: true
211 ; CHECK-LABEL: name: dont_combine_vector
212 ; CHECK: liveins: $d0
213 ; CHECK: %x:_(<2 x s32>) = COPY $d0
214 ; CHECK: %lsb_cst:_(s32) = G_CONSTANT i32 5
215 ; CHECK: %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst(s32), %lsb_cst(s32)
216 ; CHECK: %mask_cst:_(s32) = G_CONSTANT i32 255
217 ; CHECK: %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst(s32), %mask_cst(s32)
218 ; CHECK: %shift:_(<2 x s32>) = G_LSHR %x, %lsb(<2 x s32>)
219 ; CHECK: %and:_(<2 x s32>) = G_AND %shift, %mask
220 ; CHECK: $d0 = COPY %and(<2 x s32>)
221 ; CHECK: RET_ReallyLR implicit $d0
222 %x:_(<2 x s32>) = COPY $d0
223 %lsb_cst:_(s32) = G_CONSTANT i32 5
224 %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst, %lsb_cst
225 %mask_cst:_(s32) = G_CONSTANT i32 255
226 %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst, %mask_cst
227 %shift:_(<2 x s32>) = G_LSHR %x, %lsb
228 %and:_(<2 x s32>) = G_AND %shift, %mask
230 RET_ReallyLR implicit $d0
234 name: max_signed_int_mask
235 tracksRegLiveness: true
240 ; mask = 0111 1111 1111 ... 1111
241 ; mask + 1 = 1000 0000 0000 ... 0000
242 ; CHECK-LABEL: name: max_signed_int_mask
243 ; CHECK: liveins: $x0
244 ; CHECK: %x:_(s64) = COPY $x0
245 ; CHECK: %lsb:_(s64) = G_CONSTANT i64 0
246 ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
247 ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
248 ; CHECK: $x0 = COPY %and(s64)
249 ; CHECK: RET_ReallyLR implicit $x0
251 %lsb:_(s64) = G_CONSTANT i64 0
252 %mask:_(s64) = G_CONSTANT i64 9223372036854775807
253 %shift:_(s64) = G_LSHR %x, %lsb
254 %and:_(s64) = G_AND %shift, %mask
256 RET_ReallyLR implicit $x0
260 name: max_unsigned_int_mask
261 tracksRegLiveness: true
266 ; mask = 1111 1111 1111 ... 1111
267 ; mask + 1 = 0000 0000 0000 ... 000
268 ; CHECK-LABEL: name: max_unsigned_int_mask
269 ; CHECK: liveins: $x0
270 ; CHECK: %x:_(s64) = COPY $x0
271 ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
272 ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
273 ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
274 ; CHECK: $x0 = COPY %and(s64)
275 ; CHECK: RET_ReallyLR implicit $x0
277 %lsb:_(s64) = G_CONSTANT i64 5
278 %mask:_(s64) = G_CONSTANT i64 18446744073709551615
279 %shift:_(s64) = G_LSHR %x, %lsb
280 %and:_(s64) = G_AND %shift, %mask
282 RET_ReallyLR implicit $x0