Skip to content

[GlobalIsel][NFC] Modernize UBFX combine #97513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,10 @@ def and_or_disjoint_mask : GICombineRule<

def bitfield_extract_from_and : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_AND):$root,
(match (G_CONSTANT $mask, $imm2),
(G_CONSTANT $lsb, $imm1),
(G_LSHR $shift, $x, $lsb),
(G_AND $root, $shift, $mask):$root,
[{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;

Expand Down
12 changes: 7 additions & 5 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4521,19 +4521,21 @@ bool CombinerHelper::matchBitfieldExtractFromSExtInReg(
}

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

int64_t AndImm, LSBImm;
Register ShiftSrc;
const unsigned Size = Ty.getScalarSizeInBits();
if (!mi_match(MI.getOperand(0).getReg(), MRI,
if (!mi_match(And->getReg(0), MRI,
m_GAnd(m_OneNonDBGUse(m_GLShr(m_Reg(ShiftSrc), m_ICst(LSBImm))),
m_ICst(AndImm))))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this condition not be removed now that you're matching it in the TableGen?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It is collecting registers and int64_t s.
  2. mi_match returns a boolean. I don't want to and cannot ignore it.
  3. I could add a comment: "Cannot fail due to pattern."

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"m_OneNonDBGUse" could cause failure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It is collecting registers and int64_t s.
  2. mi_match returns a boolean. I don't want to and cannot ignore it.
  3. I could add a comment: "Cannot fail due to pattern."
  1. You can add those as function parameters and pass them from the TableGen.
  2. The only part of this match that differs from the TableGen is the m_OneNonDBGUse bit, which you can add as a separate condition. You can also use the HasOneUse predicate ([TableGen] HasOneUse builtin predicate on PatFrags #91578).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only pass MachineOperands as parameters. The constants would still need a separate mechanism. The HasOneUse predicate is still limited to the instruction emitter and cannot be used in the combiner.

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#
# and (lshr x, cst), mask -> ubfx x, cst, width

# LSB = 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please precommit all the formatting changes in this files. I can't tell if there are any changes related to the patch.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update script deleted the comments and I had to move them up to #.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that, but please commit all those formatting changes as a separate NFC patch.

# Width = LSB + trailing_ones(255) - 1 =
# 5 + 8 - 1 = 12

...
---
name: ubfx_s32
Expand All @@ -15,18 +19,16 @@ body: |
bb.0:
liveins: $w0

; LSB = 5
; Width = LSB + trailing_ones(255) - 1 =
; 5 + 8 - 1 = 12

; CHECK-LABEL: name: ubfx_s32
; CHECK: liveins: $w0
; CHECK: %x:_(s32) = COPY $w0
; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
; CHECK: %and:_(s32) = G_UBFX %x, %lsb(s32), [[C]]
; CHECK: $w0 = COPY %and(s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
; CHECK-NEXT: %and:_(s32) = G_UBFX %x, %lsb(s32), [[C]]
; CHECK-NEXT: $w0 = COPY %and(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
%lsb:_(s32) = G_CONSTANT i32 5
%mask:_(s32) = G_CONSTANT i32 255
Expand All @@ -35,6 +37,10 @@ body: |
$w0 = COPY %and
RET_ReallyLR implicit $w0

# LSB = 5
# Width = LSB + trailing_ones(1) - 1 =
# 5 + 1 - 1 = 5

...
---
name: ubfx_s64
Expand All @@ -44,18 +50,15 @@ body: |
bb.0:
liveins: $x0

; LSB = 5
; Width = LSB + trailing_ones(1) - 1 =
; 5 + 1 - 1 = 5

; CHECK-LABEL: name: ubfx_s64
; CHECK: liveins: $x0
; CHECK: %x:_(s64) = COPY $x0
; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK: %mask:_(s64) = G_CONSTANT i64 1
; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), %mask
; CHECK: $x0 = COPY %and(s64)
; CHECK: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s64) = COPY $x0
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK-NEXT: %mask:_(s64) = G_CONSTANT i64 1
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), %mask
; CHECK-NEXT: $x0 = COPY %and(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%x:_(s64) = COPY $x0
%lsb:_(s64) = G_CONSTANT i64 5
%mask:_(s64) = G_CONSTANT i64 1
Expand All @@ -64,6 +67,8 @@ body: |
$x0 = COPY %and
RET_ReallyLR implicit $x0

# UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants.

...
---
name: dont_combine_no_and_cst
Expand All @@ -73,17 +78,17 @@ body: |
bb.0:
liveins: $w0, $w1

; UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants.

; CHECK-LABEL: name: dont_combine_no_and_cst
; CHECK: liveins: $w0, $w1
; CHECK: %x:_(s32) = COPY $w0
; CHECK: %y:_(s32) = COPY $w1
; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32)
; CHECK: %and:_(s32) = G_AND %shift, %y
; CHECK: $w0 = COPY %and(s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %y:_(s32) = COPY $w1
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %lsb(s32)
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %y
; CHECK-NEXT: $w0 = COPY %and(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
%y:_(s32) = COPY $w1
%lsb:_(s32) = G_CONSTANT i32 5
Expand All @@ -102,13 +107,14 @@ body: |
liveins: $w0
; CHECK-LABEL: name: dont_combine_and_cst_not_mask
; CHECK: liveins: $w0
; CHECK: %x:_(s32) = COPY $w0
; CHECK: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK: %not_a_mask:_(s32) = G_CONSTANT i32 2
; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32)
; CHECK: %and:_(s32) = G_AND %shift, %not_a_mask
; CHECK: $w0 = COPY %and(s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %lsb:_(s32) = G_CONSTANT i32 5
; CHECK-NEXT: %not_a_mask:_(s32) = G_CONSTANT i32 2
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %lsb(s32)
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %not_a_mask
; CHECK-NEXT: $w0 = COPY %and(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
%lsb:_(s32) = G_CONSTANT i32 5
%not_a_mask:_(s32) = G_CONSTANT i32 2
Expand All @@ -127,14 +133,15 @@ body: |
liveins: $x0
; CHECK-LABEL: name: dont_combine_shift_more_than_one_use
; CHECK: liveins: $x0
; CHECK: %x:_(s64) = COPY $x0
; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK: %mask:_(s64) = G_CONSTANT i64 1
; CHECK: %shift:_(s64) = G_LSHR %x, %lsb(s64)
; CHECK: %and:_(s64) = G_AND %shift, %mask
; CHECK: %sub:_(s64) = G_SUB %and, %shift
; CHECK: $x0 = COPY %sub(s64)
; CHECK: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s64) = COPY $x0
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK-NEXT: %mask:_(s64) = G_CONSTANT i64 1
; CHECK-NEXT: %shift:_(s64) = G_LSHR %x, %lsb(s64)
; CHECK-NEXT: %and:_(s64) = G_AND %shift, %mask
; CHECK-NEXT: %sub:_(s64) = G_SUB %and, %shift
; CHECK-NEXT: $x0 = COPY %sub(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%x:_(s64) = COPY $x0
%lsb:_(s64) = G_CONSTANT i64 5
%mask:_(s64) = G_CONSTANT i64 1
Expand All @@ -144,6 +151,8 @@ body: |
$x0 = COPY %sub
RET_ReallyLR implicit $x0

# LSB must be in [0, reg_size)

...
---
name: dont_combine_negative_lsb
Expand All @@ -153,17 +162,17 @@ body: |
bb.0:
liveins: $w0

; LSB must be in [0, reg_size)

; CHECK-LABEL: name: dont_combine_negative_lsb
; CHECK: liveins: $w0
; CHECK: %x:_(s32) = COPY $w0
; CHECK: %negative:_(s32) = G_CONSTANT i32 -1
; CHECK: %mask:_(s32) = G_CONSTANT i32 255
; CHECK: %shift:_(s32) = G_LSHR %x, %negative(s32)
; CHECK: %and:_(s32) = G_AND %shift, %mask
; CHECK: $w0 = COPY %and(s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %negative:_(s32) = G_CONSTANT i32 -1
; CHECK-NEXT: %mask:_(s32) = G_CONSTANT i32 255
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %negative(s32)
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %mask
; CHECK-NEXT: $w0 = COPY %and(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
%negative:_(s32) = G_CONSTANT i32 -1
%mask:_(s32) = G_CONSTANT i32 255
Expand All @@ -172,6 +181,8 @@ body: |
$w0 = COPY %and
RET_ReallyLR implicit $w0

# LSB must be in [0, reg_size)

...
---
name: dont_combine_lsb_too_large
Expand All @@ -181,17 +192,17 @@ body: |
bb.0:
liveins: $w0

; LSB must be in [0, reg_size)

; CHECK-LABEL: name: dont_combine_lsb_too_large
; CHECK: liveins: $w0
; CHECK: %x:_(s32) = COPY $w0
; CHECK: %too_large:_(s32) = G_CONSTANT i32 32
; CHECK: %mask:_(s32) = G_CONSTANT i32 255
; CHECK: %shift:_(s32) = G_LSHR %x, %too_large(s32)
; CHECK: %and:_(s32) = G_AND %shift, %mask
; CHECK: $w0 = COPY %and(s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %too_large:_(s32) = G_CONSTANT i32 32
; CHECK-NEXT: %mask:_(s32) = G_CONSTANT i32 255
; CHECK-NEXT: %shift:_(s32) = G_LSHR %x, %too_large(s32)
; CHECK-NEXT: %and:_(s32) = G_AND %shift, %mask
; CHECK-NEXT: $w0 = COPY %and(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
%too_large:_(s32) = G_CONSTANT i32 32
%mask:_(s32) = G_CONSTANT i32 255
Expand All @@ -210,15 +221,16 @@ body: |
liveins: $d0
; CHECK-LABEL: name: dont_combine_vector
; CHECK: liveins: $d0
; CHECK: %x:_(<2 x s32>) = COPY $d0
; CHECK: %lsb_cst:_(s32) = G_CONSTANT i32 5
; CHECK: %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst(s32), %lsb_cst(s32)
; CHECK: %mask_cst:_(s32) = G_CONSTANT i32 255
; CHECK: %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst(s32), %mask_cst(s32)
; CHECK: %shift:_(<2 x s32>) = G_LSHR %x, %lsb(<2 x s32>)
; CHECK: %and:_(<2 x s32>) = G_AND %shift, %mask
; CHECK: $d0 = COPY %and(<2 x s32>)
; CHECK: RET_ReallyLR implicit $d0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(<2 x s32>) = COPY $d0
; CHECK-NEXT: %lsb_cst:_(s32) = G_CONSTANT i32 5
; CHECK-NEXT: %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst(s32), %lsb_cst(s32)
; CHECK-NEXT: %mask_cst:_(s32) = G_CONSTANT i32 255
; CHECK-NEXT: %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst(s32), %mask_cst(s32)
; CHECK-NEXT: %shift:_(<2 x s32>) = G_LSHR %x, %lsb(<2 x s32>)
; CHECK-NEXT: %and:_(<2 x s32>) = G_AND %shift, %mask
; CHECK-NEXT: $d0 = COPY %and(<2 x s32>)
; CHECK-NEXT: RET_ReallyLR implicit $d0
%x:_(<2 x s32>) = COPY $d0
%lsb_cst:_(s32) = G_CONSTANT i32 5
%lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst, %lsb_cst
Expand All @@ -229,6 +241,9 @@ body: |
$d0 = COPY %and
RET_ReallyLR implicit $d0

# mask = 0111 1111 1111 ... 1111
# mask + 1 = 1000 0000 0000 ... 0000

...
---
name: max_signed_int_mask
Expand All @@ -237,16 +252,15 @@ legalized: true
body: |
bb.0:
liveins: $x0
; mask = 0111 1111 1111 ... 1111
; mask + 1 = 1000 0000 0000 ... 0000
; CHECK-LABEL: name: max_signed_int_mask
; CHECK: liveins: $x0
; CHECK: %x:_(s64) = COPY $x0
; CHECK: %lsb:_(s64) = G_CONSTANT i64 0
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
; CHECK: $x0 = COPY %and(s64)
; CHECK: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s64) = COPY $x0
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 0
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
; CHECK-NEXT: $x0 = COPY %and(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%x:_(s64) = COPY $x0
%lsb:_(s64) = G_CONSTANT i64 0
%mask:_(s64) = G_CONSTANT i64 9223372036854775807
Expand All @@ -255,6 +269,9 @@ body: |
$x0 = COPY %and
RET_ReallyLR implicit $x0

# mask = 1111 1111 1111 ... 1111
# mask + 1 = 0000 0000 0000 ... 000

...
---
name: max_unsigned_int_mask
Expand All @@ -263,16 +280,15 @@ legalized: true
body: |
bb.0:
liveins: $x0
; mask = 1111 1111 1111 ... 1111
; mask + 1 = 0000 0000 0000 ... 000
; CHECK-LABEL: name: max_unsigned_int_mask
; CHECK: liveins: $x0
; CHECK: %x:_(s64) = COPY $x0
; CHECK: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
; CHECK: $x0 = COPY %and(s64)
; CHECK: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s64) = COPY $x0
; CHECK-NEXT: %lsb:_(s64) = G_CONSTANT i64 5
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
; CHECK-NEXT: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]]
; CHECK-NEXT: $x0 = COPY %and(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%x:_(s64) = COPY $x0
%lsb:_(s64) = G_CONSTANT i64 5
%mask:_(s64) = G_CONSTANT i64 18446744073709551615
Expand Down
Loading