Skip to content

Commit c5b67dd

Browse files
author
Thorsten Schütt
authored
[GlobalIsel][NFC] Modernize UBFX combine (#97513)
Credits: https://reviews.llvm.org/D99283
1 parent 690ecee commit c5b67dd

File tree

3 files changed

+110
-89
lines changed

3 files changed

+110
-89
lines changed

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,10 @@ def and_or_disjoint_mask : GICombineRule<
10261026

10271027
def bitfield_extract_from_and : GICombineRule<
10281028
(defs root:$root, build_fn_matchinfo:$info),
1029-
(match (wip_match_opcode G_AND):$root,
1029+
(match (G_CONSTANT $mask, $imm2),
1030+
(G_CONSTANT $lsb, $imm1),
1031+
(G_LSHR $shift, $x, $lsb),
1032+
(G_AND $root, $shift, $mask):$root,
10301033
[{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]),
10311034
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
10321035

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4521,19 +4521,21 @@ bool CombinerHelper::matchBitfieldExtractFromSExtInReg(
45214521
}
45224522

45234523
/// Form a G_UBFX from "(a srl b) & mask", where b and mask are constants.
4524-
bool CombinerHelper::matchBitfieldExtractFromAnd(
4525-
MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) {
4526-
assert(MI.getOpcode() == TargetOpcode::G_AND);
4527-
Register Dst = MI.getOperand(0).getReg();
4524+
bool CombinerHelper::matchBitfieldExtractFromAnd(MachineInstr &MI,
4525+
BuildFnTy &MatchInfo) {
4526+
GAnd *And = cast<GAnd>(&MI);
4527+
Register Dst = And->getReg(0);
45284528
LLT Ty = MRI.getType(Dst);
45294529
LLT ExtractTy = getTargetLowering().getPreferredShiftAmountTy(Ty);
4530+
// Note that isLegalOrBeforeLegalizer is stricter and does not take custom
4531+
// into account.
45304532
if (LI && !LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
45314533
return false;
45324534

45334535
int64_t AndImm, LSBImm;
45344536
Register ShiftSrc;
45354537
const unsigned Size = Ty.getScalarSizeInBits();
4536-
if (!mi_match(MI.getOperand(0).getReg(), MRI,
4538+
if (!mi_match(And->getReg(0), MRI,
45374539
m_GAnd(m_OneNonDBGUse(m_GLShr(m_Reg(ShiftSrc), m_ICst(LSBImm))),
45384540
m_ICst(AndImm))))
45394541
return false;

llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-and.mir

Lines changed: 99 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
#
77
# and (lshr x, cst), mask -> ubfx x, cst, width
88

9+
# LSB = 5
10+
# Width = LSB + trailing_ones(255) - 1 =
11+
# 5 + 8 - 1 = 12
12+
913
...
1014
---
1115
name: ubfx_s32
@@ -15,18 +19,16 @@ body: |
1519
bb.0:
1620
liveins: $w0
1721
18-
; LSB = 5
19-
; Width = LSB + trailing_ones(255) - 1 =
20-
; 5 + 8 - 1 = 12
2122
2223
; CHECK-LABEL: name: ubfx_s32
2324
; CHECK: liveins: $w0
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
25+
; CHECK-NEXT: {{ $}}
26+
; CHECK-NEXT: %x:_(s32) = COPY $w0
27+
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
28+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
29+
; CHECK-NEXT: %and:_(s32) = G_UBFX %x, %lsb(s32), [[C]]
30+
; CHECK-NEXT: $w0 = COPY %and(s32)
31+
; CHECK-NEXT: RET_ReallyLR implicit $w0
3032
%x:_(s32) = COPY $w0
3133
%lsb:_(s32) = G_CONSTANT i32 5
3234
%mask:_(s32) = G_CONSTANT i32 255
@@ -35,6 +37,10 @@ body: |
3537
$w0 = COPY %and
3638
RET_ReallyLR implicit $w0
3739
40+
# LSB = 5
41+
# Width = LSB + trailing_ones(1) - 1 =
42+
# 5 + 1 - 1 = 5
43+
3844
...
3945
---
4046
name: ubfx_s64
@@ -44,18 +50,15 @@ body: |
4450
bb.0:
4551
liveins: $x0
4652
47-
; LSB = 5
48-
; Width = LSB + trailing_ones(1) - 1 =
49-
; 5 + 1 - 1 = 5
50-
5153
; CHECK-LABEL: name: ubfx_s64
5254
; CHECK: liveins: $x0
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
55+
; CHECK-NEXT: {{ $}}
56+
; CHECK-NEXT: %x:_(s64) = COPY $x0
57+
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
58+
; CHECK-NEXT: %mask:_(s64) = G_CONSTANT i64 1
59+
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), %mask
60+
; CHECK-NEXT: $x0 = COPY %and(s64)
61+
; CHECK-NEXT: RET_ReallyLR implicit $x0
5962
%x:_(s64) = COPY $x0
6063
%lsb:_(s64) = G_CONSTANT i64 5
6164
%mask:_(s64) = G_CONSTANT i64 1
@@ -64,6 +67,8 @@ body: |
6467
$x0 = COPY %and
6568
RET_ReallyLR implicit $x0
6669
70+
# UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants.
71+
6772
...
6873
---
6974
name: dont_combine_no_and_cst
@@ -73,17 +78,17 @@ body: |
7378
bb.0:
7479
liveins: $w0, $w1
7580
76-
; UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants.
7781
7882
; CHECK-LABEL: name: dont_combine_no_and_cst
7983
; 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
84+
; CHECK-NEXT: {{ $}}
85+
; CHECK-NEXT: %x:_(s32) = COPY $w0
86+
; CHECK-NEXT: %y:_(s32) = COPY $w1
87+
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
88+
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %lsb(s32)
89+
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %y
90+
; CHECK-NEXT: $w0 = COPY %and(s32)
91+
; CHECK-NEXT: RET_ReallyLR implicit $w0
8792
%x:_(s32) = COPY $w0
8893
%y:_(s32) = COPY $w1
8994
%lsb:_(s32) = G_CONSTANT i32 5
@@ -102,13 +107,14 @@ body: |
102107
liveins: $w0
103108
; CHECK-LABEL: name: dont_combine_and_cst_not_mask
104109
; 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
110+
; CHECK-NEXT: {{ $}}
111+
; CHECK-NEXT: %x:_(s32) = COPY $w0
112+
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
113+
; CHECK-NEXT: %not_a_mask:_(s32) = G_CONSTANT i32 2
114+
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %lsb(s32)
115+
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %not_a_mask
116+
; CHECK-NEXT: $w0 = COPY %and(s32)
117+
; CHECK-NEXT: RET_ReallyLR implicit $w0
112118
%x:_(s32) = COPY $w0
113119
%lsb:_(s32) = G_CONSTANT i32 5
114120
%not_a_mask:_(s32) = G_CONSTANT i32 2
@@ -127,14 +133,15 @@ body: |
127133
liveins: $x0
128134
; CHECK-LABEL: name: dont_combine_shift_more_than_one_use
129135
; 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
136+
; CHECK-NEXT: {{ $}}
137+
; CHECK-NEXT: %x:_(s64) = COPY $x0
138+
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
139+
; CHECK-NEXT: %mask:_(s64) = G_CONSTANT i64 1
140+
; CHECK-NEXT: %shift:_(s64) = G_LSHR %x, %lsb(s64)
141+
; CHECK-NEXT: %and:_(s64) = G_AND %shift, %mask
142+
; CHECK-NEXT: %sub:_(s64) = G_SUB %and, %shift
143+
; CHECK-NEXT: $x0 = COPY %sub(s64)
144+
; CHECK-NEXT: RET_ReallyLR implicit $x0
138145
%x:_(s64) = COPY $x0
139146
%lsb:_(s64) = G_CONSTANT i64 5
140147
%mask:_(s64) = G_CONSTANT i64 1
@@ -144,6 +151,8 @@ body: |
144151
$x0 = COPY %sub
145152
RET_ReallyLR implicit $x0
146153
154+
# LSB must be in [0, reg_size)
155+
147156
...
148157
---
149158
name: dont_combine_negative_lsb
@@ -153,17 +162,17 @@ body: |
153162
bb.0:
154163
liveins: $w0
155164
156-
; LSB must be in [0, reg_size)
157165
158166
; CHECK-LABEL: name: dont_combine_negative_lsb
159167
; 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+
; CHECK-NEXT: {{ $}}
169+
; CHECK-NEXT: %x:_(s32) = COPY $w0
170+
; CHECK-NEXT: %negative:_(s32) = G_CONSTANT i32 -1
171+
; CHECK-NEXT: %mask:_(s32) = G_CONSTANT i32 255
172+
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %negative(s32)
173+
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %mask
174+
; CHECK-NEXT: $w0 = COPY %and(s32)
175+
; CHECK-NEXT: RET_ReallyLR implicit $w0
167176
%x:_(s32) = COPY $w0
168177
%negative:_(s32) = G_CONSTANT i32 -1
169178
%mask:_(s32) = G_CONSTANT i32 255
@@ -172,6 +181,8 @@ body: |
172181
$w0 = COPY %and
173182
RET_ReallyLR implicit $w0
174183
184+
# LSB must be in [0, reg_size)
185+
175186
...
176187
---
177188
name: dont_combine_lsb_too_large
@@ -181,17 +192,17 @@ body: |
181192
bb.0:
182193
liveins: $w0
183194
184-
; LSB must be in [0, reg_size)
185195
186196
; CHECK-LABEL: name: dont_combine_lsb_too_large
187197
; 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
198+
; CHECK-NEXT: {{ $}}
199+
; CHECK-NEXT: %x:_(s32) = COPY $w0
200+
; CHECK-NEXT: %too_large:_(s32) = G_CONSTANT i32 32
201+
; CHECK-NEXT: %mask:_(s32) = G_CONSTANT i32 255
202+
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %too_large(s32)
203+
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %mask
204+
; CHECK-NEXT: $w0 = COPY %and(s32)
205+
; CHECK-NEXT: RET_ReallyLR implicit $w0
195206
%x:_(s32) = COPY $w0
196207
%too_large:_(s32) = G_CONSTANT i32 32
197208
%mask:_(s32) = G_CONSTANT i32 255
@@ -210,15 +221,16 @@ body: |
210221
liveins: $d0
211222
; CHECK-LABEL: name: dont_combine_vector
212223
; 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
224+
; CHECK-NEXT: {{ $}}
225+
; CHECK-NEXT: %x:_(<2 x s32>) = COPY $d0
226+
; CHECK-NEXT: %lsb_cst:_(s32) = G_CONSTANT i32 5
227+
; CHECK-NEXT: %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst(s32), %lsb_cst(s32)
228+
; CHECK-NEXT: %mask_cst:_(s32) = G_CONSTANT i32 255
229+
; CHECK-NEXT: %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst(s32), %mask_cst(s32)
230+
; CHECK-NEXT: %shift:_(<2 x s32>) = G_LSHR %x, %lsb(<2 x s32>)
231+
; CHECK-NEXT: %and:_(<2 x s32>) = G_AND %shift, %mask
232+
; CHECK-NEXT: $d0 = COPY %and(<2 x s32>)
233+
; CHECK-NEXT: RET_ReallyLR implicit $d0
222234
%x:_(<2 x s32>) = COPY $d0
223235
%lsb_cst:_(s32) = G_CONSTANT i32 5
224236
%lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst, %lsb_cst
@@ -229,6 +241,9 @@ body: |
229241
$d0 = COPY %and
230242
RET_ReallyLR implicit $d0
231243
244+
# mask = 0111 1111 1111 ... 1111
245+
# mask + 1 = 1000 0000 0000 ... 0000
246+
232247
...
233248
---
234249
name: max_signed_int_mask
@@ -237,16 +252,15 @@ legalized: true
237252
body: |
238253
bb.0:
239254
liveins: $x0
240-
; mask = 0111 1111 1111 ... 1111
241-
; mask + 1 = 1000 0000 0000 ... 0000
242255
; CHECK-LABEL: name: max_signed_int_mask
243256
; 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
257+
; CHECK-NEXT: {{ $}}
258+
; CHECK-NEXT: %x:_(s64) = COPY $x0
259+
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 0
260+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
261+
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
262+
; CHECK-NEXT: $x0 = COPY %and(s64)
263+
; CHECK-NEXT: RET_ReallyLR implicit $x0
250264
%x:_(s64) = COPY $x0
251265
%lsb:_(s64) = G_CONSTANT i64 0
252266
%mask:_(s64) = G_CONSTANT i64 9223372036854775807
@@ -255,6 +269,9 @@ body: |
255269
$x0 = COPY %and
256270
RET_ReallyLR implicit $x0
257271
272+
# mask = 1111 1111 1111 ... 1111
273+
# mask + 1 = 0000 0000 0000 ... 000
274+
258275
...
259276
---
260277
name: max_unsigned_int_mask
@@ -263,16 +280,15 @@ legalized: true
263280
body: |
264281
bb.0:
265282
liveins: $x0
266-
; mask = 1111 1111 1111 ... 1111
267-
; mask + 1 = 0000 0000 0000 ... 000
268283
; CHECK-LABEL: name: max_unsigned_int_mask
269284
; 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
285+
; CHECK-NEXT: {{ $}}
286+
; CHECK-NEXT: %x:_(s64) = COPY $x0
287+
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
288+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
289+
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
290+
; CHECK-NEXT: $x0 = COPY %and(s64)
291+
; CHECK-NEXT: RET_ReallyLR implicit $x0
276292
%x:_(s64) = COPY $x0
277293
%lsb:_(s64) = G_CONSTANT i64 5
278294
%mask:_(s64) = G_CONSTANT i64 18446744073709551615

0 commit comments

Comments
 (0)