-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[GISel][RISCV] Implement selectShiftMask. #77572
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
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Mikhail Gudim (mgudim) ChangesThis is WIP, just posting it to let others know that I'm working on it. Full diff: https://github.com/llvm/llvm-project/pull/77572.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 61bdbfc47d947f..82860eb4b9e134 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -159,9 +159,55 @@ RISCVInstructionSelector::RISCVInstructionSelector(
InstructionSelector::ComplexRendererFns
RISCVInstructionSelector::selectShiftMask(MachineOperand &Root) const {
- // TODO: Also check if we are seeing the result of an AND operation which
- // could be bypassed since we only check the lower log2(xlen) bits.
- return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
+ // TODO: ShiftWidth can be 64.
+ unsigned ShiftWidth = 32;
+
+ using namespace llvm::MIPatternMatch;
+ MachineFunction &MF = *Root.getParent()->getParent()->getParent();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+
+ if (!Root.isReg())
+ return std::nullopt;
+ Register RootReg = Root.getReg();
+ Register ShAmtReg = RootReg;
+ // Peek through zext.
+ Register ZExtSrcReg;
+ if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg)))) {
+ ShAmtReg = ZExtSrcReg;
+ }
+
+ APInt AndMask;
+ Register AndSrcReg;
+ if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
+ APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
+ if (ShMask.isSubsetOf(AndMask)) {
+ ShAmtReg = AndSrcReg;
+ } else {
+ // TODO:
+ // SimplifyDemandedBits may have optimized the mask so try restoring any
+ // bits that are known zero.
+ }
+ }
+
+ APInt Imm;
+ Register Reg;
+ if (mi_match(ShAmtReg, MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
+ if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
+ // If we are shifting by X+N where N == 0 mod Size, then just shift by X
+ // to avoid the ADD.
+ ShAmtReg = Reg;
+ } else if (mi_match(ShAmtReg, MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
+ if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
+ // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
+ // to generate a NEG instead of a SUB of a constant.
+ ShAmtReg = Reg;
+ }
+ }
+
+ if (ShAmtReg == RootReg)
+ return std::nullopt;
+
+ return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
}
InstructionSelector::ComplexRendererFns
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir
new file mode 100644
index 00000000000000..4e07819cb4b4c0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir
@@ -0,0 +1,54 @@
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select \
+# RUN: -simplify-mir -verify-machineinstrs %s -o -
+
+#---
+#name: shl_zext
+#legalized: true
+#regBankSelected: true
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# liveins: $x10
+#
+# %0:gprb(s64) = COPY $x10
+# %1:gprb(s32) = G_CONSTANT i32 1
+# %2:gprb(s64) = G_ZEXT %1
+# %3:gprb(s64) = G_SHL %0, %2(s64)
+# $x10 = COPY %3(s64)
+# PseudoRET implicit $x10
+
+#---
+#name: shl_and
+#legalized: true
+#regBankSelected: true
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# liveins: $x10, $x11
+#
+# %0:gprb(s64) = COPY $x10
+# %1:gprb(s64) = COPY $x11
+# %2:gprb(s64) = G_CONSTANT i64 31
+# %3:gprb(s64) = G_AND %1, %2
+# %4:gprb(s64) = G_SHL %0, %3(s64)
+# $x10 = COPY %4(s64)
+# PseudoRET implicit $x10
+
+---
+name: shl_and_zext
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ %0:gprb(s64) = COPY $x10
+ %addr:gprb(p0) = COPY $x11
+ %1:gprb(s32) = G_LOAD %addr(p0) :: (load (s8))
+ %2:gprb(s32) = G_CONSTANT i32 31
+ %3:gprb(s32) = G_AND %1, %2
+ %4:gprb(s64) = G_ZEXT %3
+ %5:gprb(s64) = G_SHL %0, %4(s64)
+ $x10 = COPY %5(s64)
+ PseudoRET implicit $x10
|
@llvm/pr-subscribers-llvm-globalisel Author: Mikhail Gudim (mgudim) ChangesThis is WIP, just posting it to let others know that I'm working on it. Full diff: https://github.com/llvm/llvm-project/pull/77572.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 61bdbfc47d947f..82860eb4b9e134 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -159,9 +159,55 @@ RISCVInstructionSelector::RISCVInstructionSelector(
InstructionSelector::ComplexRendererFns
RISCVInstructionSelector::selectShiftMask(MachineOperand &Root) const {
- // TODO: Also check if we are seeing the result of an AND operation which
- // could be bypassed since we only check the lower log2(xlen) bits.
- return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
+ // TODO: ShiftWidth can be 64.
+ unsigned ShiftWidth = 32;
+
+ using namespace llvm::MIPatternMatch;
+ MachineFunction &MF = *Root.getParent()->getParent()->getParent();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+
+ if (!Root.isReg())
+ return std::nullopt;
+ Register RootReg = Root.getReg();
+ Register ShAmtReg = RootReg;
+ // Peek through zext.
+ Register ZExtSrcReg;
+ if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg)))) {
+ ShAmtReg = ZExtSrcReg;
+ }
+
+ APInt AndMask;
+ Register AndSrcReg;
+ if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
+ APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
+ if (ShMask.isSubsetOf(AndMask)) {
+ ShAmtReg = AndSrcReg;
+ } else {
+ // TODO:
+ // SimplifyDemandedBits may have optimized the mask so try restoring any
+ // bits that are known zero.
+ }
+ }
+
+ APInt Imm;
+ Register Reg;
+ if (mi_match(ShAmtReg, MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
+ if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
+ // If we are shifting by X+N where N == 0 mod Size, then just shift by X
+ // to avoid the ADD.
+ ShAmtReg = Reg;
+ } else if (mi_match(ShAmtReg, MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
+ if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
+ // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
+ // to generate a NEG instead of a SUB of a constant.
+ ShAmtReg = Reg;
+ }
+ }
+
+ if (ShAmtReg == RootReg)
+ return std::nullopt;
+
+ return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
}
InstructionSelector::ComplexRendererFns
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir
new file mode 100644
index 00000000000000..4e07819cb4b4c0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/shift-rv64.mir
@@ -0,0 +1,54 @@
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select \
+# RUN: -simplify-mir -verify-machineinstrs %s -o -
+
+#---
+#name: shl_zext
+#legalized: true
+#regBankSelected: true
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# liveins: $x10
+#
+# %0:gprb(s64) = COPY $x10
+# %1:gprb(s32) = G_CONSTANT i32 1
+# %2:gprb(s64) = G_ZEXT %1
+# %3:gprb(s64) = G_SHL %0, %2(s64)
+# $x10 = COPY %3(s64)
+# PseudoRET implicit $x10
+
+#---
+#name: shl_and
+#legalized: true
+#regBankSelected: true
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# liveins: $x10, $x11
+#
+# %0:gprb(s64) = COPY $x10
+# %1:gprb(s64) = COPY $x11
+# %2:gprb(s64) = G_CONSTANT i64 31
+# %3:gprb(s64) = G_AND %1, %2
+# %4:gprb(s64) = G_SHL %0, %3(s64)
+# $x10 = COPY %4(s64)
+# PseudoRET implicit $x10
+
+---
+name: shl_and_zext
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ %0:gprb(s64) = COPY $x10
+ %addr:gprb(p0) = COPY $x11
+ %1:gprb(s32) = G_LOAD %addr(p0) :: (load (s8))
+ %2:gprb(s32) = G_CONSTANT i32 31
+ %3:gprb(s32) = G_AND %1, %2
+ %4:gprb(s64) = G_ZEXT %3
+ %5:gprb(s64) = G_SHL %0, %4(s64)
+ $x10 = COPY %5(s64)
+ PseudoRET implicit $x10
|
8f84ce6
to
2b5a25d
Compare
unsigned ShiftWidth = 32; | ||
|
||
using namespace llvm::MIPatternMatch; | ||
MachineFunction &MF = *Root.getParent()->getParent()->getParent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should already be available in the base class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed this, thanks.
2b5a25d
to
b22fe66
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
b22fe66
to
6c90357
Compare
Implement the selectShiftMask for GlobalISel.
6c90357
to
5f51ab1
Compare
MIB.addReg(ShAmtReg); | ||
}}}; | ||
} | ||
if ((Imm.urem(ShiftWidth) & (ShiftWidth - 1)) == ShiftWidth - 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generalized this slightly from the non-global ISel version so that it works with negative numbers. This simplification works as long as lower 4 or 5 bits of the remainer are all 1
. I think this is right, please correct me if I am wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doesn't the isel version work with negative numbers?
The & (ShiftWidth - 1)
seems unnecessary. Imm.urem(ShiftWidth) should return a number in the range [0, ShiftWidth -1] so the & should have no effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right. I forgot that Imm
is treated as unsigned.
This is ready for review @topperc |
if (ShMask.isSubsetOf(AndMask)) { | ||
ShAmtReg = AndSrcReg; | ||
} else { | ||
// TODO: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the TODO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done. Forgot to delete this line, thanks
if (Imm != 0 && Imm.urem(ShiftWidth) == 0) { | ||
// If we are shifting by N-X where N == 0 mod Size, then just shift by -X | ||
// to generate a NEG instead of a SUB of a constant. | ||
ShAmtReg = MRI.createGenericVirtualRegister(ShiftLLT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this should be MRI.createVirtualRegister(&RISCV::GPRRegClass)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... Not sure, I just followed similar code (like selectSHXADDOp
). The docs say about target's InstructionSelector
that " It is also responsible for doing the necessary constraining of gvregs into the appropriate register classes as well as passing through COPY instructions to the register allocator." So, to me it also seems more appropriate to use createVirtualRegister
. We still see gpr
in the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should avoid creating new generic register during selection. You can get away with it if later steps end up constraining the register, but it's just adding extra steps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for clarifying @arsenm I changed it here, I can change it in other places in separate MR
6791b0f
to
aec7179
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Implement `selectShiftMask` in `GlobalISel`.
Implement
selectShiftMask
inGlobalISel
.