-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[GISel] Fold shifts to constant result. #123510
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
Changes from all commits
63c7775
56dfed9
ce31b1f
d004399
ec1618f
12fb70e
0ab36e7
bb12265
43f01ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6590,12 +6590,57 @@ bool CombinerHelper::matchRedundantBinOpInEquality(MachineInstr &MI, | |
return CmpInst::isEquality(Pred) && Y.isValid(); | ||
} | ||
|
||
bool CombinerHelper::matchShiftsTooBig(MachineInstr &MI) const { | ||
/// Return the minimum useless shift amount that results in complete loss of the | ||
/// source value. Return std::nullopt when it cannot determine a value. | ||
static std::optional<unsigned> | ||
getMinUselessShift(KnownBits ValueKB, unsigned Opcode, | ||
std::optional<int64_t> &Result) { | ||
assert(Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR || | ||
Opcode == TargetOpcode::G_ASHR && "Expect G_SHL, G_LSHR or G_ASHR."); | ||
auto SignificantBits = 0; | ||
switch (Opcode) { | ||
case TargetOpcode::G_SHL: | ||
SignificantBits = ValueKB.countMinTrailingZeros(); | ||
Result = 0; | ||
break; | ||
case TargetOpcode::G_LSHR: | ||
Result = 0; | ||
SignificantBits = ValueKB.countMinLeadingZeros(); | ||
break; | ||
case TargetOpcode::G_ASHR: | ||
if (ValueKB.isNonNegative()) { | ||
SignificantBits = ValueKB.countMinLeadingZeros(); | ||
Result = 0; | ||
} else if (ValueKB.isNegative()) { | ||
SignificantBits = ValueKB.countMinLeadingOnes(); | ||
Result = -1; | ||
} else { | ||
// Cannot determine shift result. | ||
Result = std::nullopt; | ||
} | ||
break; | ||
Comment on lines
+6610
to
+6621
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be using computeKnownSignBits instead of computeKnownBits, it can be slightly smarter |
||
default: | ||
break; | ||
} | ||
return ValueKB.getBitWidth() - SignificantBits; | ||
} | ||
|
||
bool CombinerHelper::matchShiftsTooBig( | ||
MachineInstr &MI, std::optional<int64_t> &MatchInfo) const { | ||
Register ShiftVal = MI.getOperand(1).getReg(); | ||
Register ShiftReg = MI.getOperand(2).getReg(); | ||
LLT ResTy = MRI.getType(MI.getOperand(0).getReg()); | ||
auto IsShiftTooBig = [&](const Constant *C) { | ||
auto *CI = dyn_cast<ConstantInt>(C); | ||
return CI && CI->uge(ResTy.getScalarSizeInBits()); | ||
if (!CI) | ||
return false; | ||
if (CI->uge(ResTy.getScalarSizeInBits())) { | ||
MatchInfo = std::nullopt; | ||
return true; | ||
} | ||
auto OptMaxUsefulShift = getMinUselessShift(KB->getKnownBits(ShiftVal), | ||
MI.getOpcode(), MatchInfo); | ||
return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift); | ||
}; | ||
return matchUnaryPredicate(MRI, ShiftReg, IsShiftTooBig); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py | ||
# RUN: llc -mtriple=amdgcn -run-pass=amdgpu-prelegalizer-combiner %s -o - | FileCheck %s | ||
|
||
--- | ||
name: combine_ashr | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_ashr | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 | ||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 | ||
; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 | ||
; CHECK-NEXT: G_STORE [[C]](s32), [[MV]](p0) :: (store (s32)) | ||
; CHECK-NEXT: SI_RETURN | ||
%0:_(s32) = COPY $vgpr0 | ||
%1:_(s32) = COPY $vgpr1 | ||
%2:_(p0) = G_MERGE_VALUES %0(s32), %1(s32) | ||
%3:_(s32) = G_CONSTANT i32 10 | ||
%4:_(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.workitem.id.x) | ||
%5:_(s32) = G_ASHR %4, %3(s32) | ||
G_STORE %5(s32), %2(p0) :: (store (s32)) | ||
SI_RETURN | ||
|
||
... | ||
--- | ||
name: combine_lshr | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_lshr | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 | ||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 | ||
; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 | ||
; CHECK-NEXT: G_STORE [[C]](s32), [[MV]](p0) :: (store (s32)) | ||
; CHECK-NEXT: SI_RETURN | ||
%0:_(s32) = COPY $vgpr0 | ||
%1:_(s32) = COPY $vgpr1 | ||
%2:_(p0) = G_MERGE_VALUES %0(s32), %1(s32) | ||
%3:_(s32) = G_CONSTANT i32 10 | ||
%4:_(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.workitem.id.x) | ||
%5:_(s32) = G_LSHR %4, %3(s32) | ||
G_STORE %5(s32), %2(p0) :: (store (s32)) | ||
SI_RETURN | ||
|
||
... | ||
--- | ||
name: combine_shl | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_shl | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 | ||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 | ||
; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 | ||
; CHECK-NEXT: G_STORE [[C]](s32), [[MV]](p0) :: (store (s32)) | ||
; CHECK-NEXT: SI_RETURN | ||
%0:_(s32) = COPY $vgpr0 | ||
%1:_(s32) = COPY $vgpr1 | ||
%2:_(p0) = G_MERGE_VALUES %0(s32), %1(s32) | ||
%3:_(s32) = G_CONSTANT i32 16 | ||
%4:_(s32) = G_CONSTANT i32 4294901760 | ||
%5:_(s32) = G_SHL %4, %3(s32) | ||
G_STORE %5(s32), %2(p0) :: (store (s32)) | ||
SI_RETURN | ||
|
||
... | ||
--- | ||
name: combine_ashr2 | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_ashr2 | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 | ||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 | ||
; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 -1 | ||
; CHECK-NEXT: G_STORE [[C]](s8), [[MV]](p0) :: (store (s8)) | ||
; CHECK-NEXT: SI_RETURN | ||
%0:_(s32) = COPY $vgpr0 | ||
%1:_(s32) = COPY $vgpr1 | ||
%2:_(p0) = G_MERGE_VALUES %0(s32), %1(s32) | ||
%3:_(s32) = G_CONSTANT i32 1 | ||
%4:_(s8) = G_CONSTANT i8 -2 | ||
%5:_(s8) = G_ASHR %4, %3(s32) | ||
G_STORE %5(s8), %2(p0) :: (store (s8)) | ||
SI_RETURN | ||
|
||
... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test vector cases There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test cases added |
||
--- | ||
name: combine_vector_lshr | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_vector_lshr | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 | ||
; CHECK-NEXT: $vgpr0 = COPY [[C]](s32) | ||
; CHECK-NEXT: $vgpr1 = COPY [[C]](s32) | ||
; CHECK-NEXT: SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
%0:_(<2 x s32>) = G_IMPLICIT_DEF | ||
%1:_(s32) = G_CONSTANT i32 511 | ||
%2:_(s32) = G_CONSTANT i32 0 | ||
%3:_(s32) = G_CONSTANT i32 1 | ||
%4:_(s32) = G_CONSTANT i32 9 | ||
%5:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32) | ||
%6:_(<2 x s32>) = G_INSERT_VECTOR_ELT %0, %1(s32), %2(s32) | ||
%7:_(<2 x s32>) = G_INSERT_VECTOR_ELT %6, %1(s32), %3(s32) | ||
%8:_(<2 x s32>) = G_LSHR %7, %5(<2 x s32>) | ||
%9:_(s32), %10:_(s32) = G_UNMERGE_VALUES %8(<2 x s32>) | ||
$vgpr0 = COPY %9(s32) | ||
$vgpr1 = COPY %10(s32) | ||
SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
|
||
... | ||
--- | ||
name: combine_vector_shl | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_vector_shl | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 | ||
; CHECK-NEXT: $vgpr0 = COPY [[C]](s32) | ||
; CHECK-NEXT: $vgpr1 = COPY [[C]](s32) | ||
; CHECK-NEXT: SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
%0:_(<2 x s32>) = G_IMPLICIT_DEF | ||
%1:_(s32) = G_CONSTANT i32 4294901760 | ||
%2:_(s32) = G_CONSTANT i32 0 | ||
%3:_(s32) = G_CONSTANT i32 1 | ||
%4:_(s32) = G_CONSTANT i32 16 | ||
%5:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32) | ||
%6:_(<2 x s32>) = G_INSERT_VECTOR_ELT %0, %1(s32), %2(s32) | ||
%7:_(<2 x s32>) = G_INSERT_VECTOR_ELT %6, %1(s32), %3(s32) | ||
%8:_(<2 x s32>) = G_SHL %7, %5(<2 x s32>) | ||
%9:_(s32), %10:_(s32) = G_UNMERGE_VALUES %8(<2 x s32>) | ||
$vgpr0 = COPY %9(s32) | ||
$vgpr1 = COPY %10(s32) | ||
SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
|
||
... | ||
--- | ||
name: combine_vector_ashr | ||
tracksRegLiveness: true | ||
body: | | ||
bb.0: | ||
liveins: $vgpr0, $vgpr1, $vgpr31 | ||
|
||
liveins: $vgpr0, $vgpr1 | ||
|
||
; CHECK-LABEL: name: combine_vector_ashr | ||
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr31, $vgpr0, $vgpr1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 | ||
; CHECK-NEXT: $vgpr0 = COPY [[C]](s32) | ||
; CHECK-NEXT: $vgpr1 = COPY [[C]](s32) | ||
; CHECK-NEXT: SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
%0:_(<2 x s32>) = G_IMPLICIT_DEF | ||
%1:_(s32) = G_CONSTANT i32 -1 | ||
%2:_(s32) = G_CONSTANT i32 0 | ||
%3:_(s32) = G_CONSTANT i32 1 | ||
%4:_(s32) = G_CONSTANT i32 1 | ||
%5:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32) | ||
%6:_(<2 x s32>) = G_INSERT_VECTOR_ELT %0, %1(s32), %2(s32) | ||
%7:_(<2 x s32>) = G_INSERT_VECTOR_ELT %6, %1(s32), %3(s32) | ||
%8:_(<2 x s32>) = G_ASHR %7, %5(<2 x s32>) | ||
%9:_(s32), %10:_(s32) = G_UNMERGE_VALUES %8(<2 x s32>) | ||
$vgpr0 = COPY %9(s32) | ||
$vgpr1 = COPY %10(s32) | ||
SI_RETURN implicit $vgpr0, implicit $vgpr1 | ||
|
||
... |
Uh oh!
There was an error while loading. Please reload this page.