-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[RISCV][GISel] Add instruction selection for G_SEXT, G_ZEXT, and G_SEXT_INREG #67359
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
…XT_INREG G_SEXT and G_ZEXT are supported via patterns imported from SDISel; G_SEXT_INREG is selected using hand-written code as there is no (functional) rule at this moment to import G_SEXT_INREG from sext_inreg.
@llvm/pr-subscribers-llvm-globalisel @llvm/pr-subscribers-backend-risc-v ChangesG_SEXT and G_ZEXT are supported via patterns imported from SDISel; G_SEXT_INREG is selected using hand-written code as there is no (functional) rule at this moment to import G_SEXT_INREG from ISD::SEXT_INREG. Full diff: https://github.com/llvm/llvm-project/pull/67359.diff 5 Files Affected:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4a4be79528545f8..0149a8772f7d5e2 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -48,6 +48,7 @@ class RISCVInstructionSelector : public InstructionSelector {
bool selectCopy(MachineInstr &MI, MachineRegisterInfo &MRI) const;
bool selectConstant(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
+ bool selectSExtInreg(MachineInstr &MI, MachineIRBuilder &MIB) const;
bool earlySelectShift(unsigned Opc, MachineInstr &I, MachineIRBuilder &MIB,
const MachineRegisterInfo &MRI);
@@ -237,6 +238,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
}
+ case TargetOpcode::G_SEXT_INREG:
+ return selectSExtInreg(MI, MIB);
default:
return false;
}
@@ -363,6 +366,32 @@ bool RISCVInstructionSelector::selectConstant(MachineInstr &MI,
return true;
}
+bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
+ MachineIRBuilder &MIB) const {
+ if (!STI.isRV64())
+ return false;
+
+ const MachineOperand &Size = MI.getOperand(2);
+ // Only Size == 32 (i.e. shift by 32 bits) is acceptable at this point.
+ if (!Size.isImm() || Size.getImm() != 32)
+ return false;
+
+ const MachineOperand &Src = MI.getOperand(1);
+ const MachineOperand &Dst = MI.getOperand(0);
+ assert(Src.isReg() && Dst.isReg());
+ // addiw rd, rs, 0 (i.e. sext.w rd, rs)
+ MachineInstr *NewMI = MIB.buildInstr(RISCV::ADDIW)
+ .addDef(Dst.getReg())
+ .addReg(Src.getReg())
+ .addImm(0U);
+
+ if (!constrainSelectedInstRegOperands(*NewMI, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+}
+
namespace llvm {
InstructionSelector *
createRISCVInstructionSelector(const RISCVTargetMachine &TM,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index abbeff78b6e2864..12ec4e2c9b46b2c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1774,6 +1774,12 @@ let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,
def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;
} // Predicates = [IsRV64], ...
+let Predicates = [IsRV64] in
+def: Pat<(i64 (sext i32:$rs)), (ADDIW GPR:$rs, 0)>;
+
+let Predicates = [IsRV64, NotHasStdExtZba] in
+def: Pat<(i64 (zext i32:$rs)), (SRLI (SLLI GPR:$rs, 32), 32)>;
+
/// Loads
class LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT>
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index a21c3d132636bea..8467acdd8148411 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -727,6 +727,8 @@ def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 81)),
} // Predicates = [HasStdExtZba]
let Predicates = [HasStdExtZba, IsRV64] in {
+def : Pat<(i64 (zext i32:$rs)), (ADD_UW GPR:$rs, (XLenVT X0))>;
+
def : Pat<(i64 (shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt)),
(SLLI_UW GPR:$rs1, uimm5:$shamt)>;
// Match a shifted 0xffffffff mask. Use SRLI to clear the LSBs and SLLI_UW to
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir
new file mode 100644
index 000000000000000..50b1257c4ffec74
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir
@@ -0,0 +1,32 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+---
+name: sext_32_64
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sext_32_64
+ ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+ ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 0
+ ; CHECK-NEXT: $x8 = COPY [[ADDIW]]
+ %0:gprb(s32) = G_CONSTANT i32 -2147483648
+ %1:gprb(s64) = G_SEXT %0
+ $x8 = COPY %1(s64)
+...
+---
+name: sext_inreg_64_32
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sext_inreg_64_32
+ ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+ ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 0
+ ; CHECK-NEXT: $x8 = COPY [[ADDIW]]
+ %0:gprb(s64) = G_CONSTANT i64 -2147483648
+ %1:gprb(s64) = G_SEXT_INREG %0, 32
+ $x8 = COPY %1(s64)
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir
new file mode 100644
index 000000000000000..687be8a13932fe0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir
@@ -0,0 +1,24 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs -mattr='+zba' %s -o - | FileCheck %s --check-prefix=ZBA
+---
+name: zext_32_64
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: zext_32_64
+ ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+ ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[LUI]], 32
+ ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 32
+ ; CHECK-NEXT: $x8 = COPY [[SRLI]]
+ ;
+ ; ZBA-LABEL: name: zext_32_64
+ ; ZBA: [[LUI:%[0-9]+]]:gpr = LUI 524288
+ ; ZBA-NEXT: [[ADD_UW:%[0-9]+]]:gpr = ADD_UW [[LUI]], $x0
+ ; ZBA-NEXT: $x8 = COPY [[ADD_UW]]
+ %0:gprb(s32) = G_CONSTANT i32 -2147483648
+ %1:gprb(s64) = G_ZEXT %0
+ $x8 = COPY %1(s64)
+...
|
- Moved newly created isel patterns into RISCVGISel.td - Some minor fixes in `selectSExtInreg`
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
G_SEXT and G_ZEXT are supported via patterns imported from SDISel; G_SEXT_INREG is selected using hand-written code as there is no (functional) rule at this moment to import G_SEXT_INREG from ISD::SEXT_INREG.
Credit helps from @topperc on G_SEXT and G_ZEXT.