-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV][GISel] Instruction selection for G_JUMP_TABLE and G_BRJT. #71987
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-llvm-globalisel @llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesPatch is 46.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71987.diff 7 Files Affected:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index b8acd98939b9fc7..a07c6dedbeb7570 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/IR/IntrinsicsRISCV.h"
#include "llvm/Support/Debug.h"
@@ -64,6 +65,8 @@ class RISCVInstructionSelector : public InstructionSelector {
bool materializeImm(Register Reg, int64_t Imm, MachineIRBuilder &MIB) const;
bool selectGlobalValue(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
+ bool selectJumpTable(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const;
bool selectSExtInreg(MachineInstr &MI, MachineIRBuilder &MIB) const;
bool selectSelect(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
@@ -397,6 +400,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
}
case TargetOpcode::G_GLOBAL_VALUE:
return selectGlobalValue(MI, MIB, MRI);
+ case TargetOpcode::G_JUMP_TABLE:
+ return selectJumpTable(MI, MIB, MRI);
case TargetOpcode::G_BRCOND: {
// TODO: Fold with G_ICMP.
auto Bcc =
@@ -405,6 +410,49 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
}
+ case TargetOpcode::G_BRJT: {
+ unsigned EntrySize =
+ MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
+ assert((EntrySize == 4 || (Subtarget->is64Bit() && EntrySize == 8)) &&
+ "Unsupported jump-table entry size");
+
+ auto SLL =
+ MIB.buildInstr(RISCV::SLLI, {&RISCV::GPRRegClass}, {MI.getOperand(2)})
+ .addImm(Log2_32(EntrySize));
+ if (!SLL.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ // TODO: Use SHXADD.
+ auto ADD = MIB.buildInstr(RISCV::ADD, {&RISCV::GPRRegClass},
+ {MI.getOperand(0), SLL.getReg(0)});
+ if (!ADD.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ unsigned LdOpc = EntrySize == 8 ? RISCV::LD : RISCV::LW;
+ auto Dest =
+ MIB.buildInstr(LdOpc, {&RISCV::GPRRegClass}, {ADD.getReg(0)})
+ .addImm(0)
+ .addMemOperand(MF.getMachineMemOperand(
+ MachinePointerInfo::getJumpTable(MF), MachineMemOperand::MOLoad,
+ EntrySize, Align(EntrySize)));
+ if (!Dest.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ if (MF.getTarget().isPositionIndependent()) {
+ Dest = MIB.buildInstr(RISCV::ADD, {&RISCV::GPRRegClass},
+ {Dest.getReg(0), MI.getOperand(0)});
+ if (!Dest.constrainAllUses(TII, TRI, RBI))
+ return false;
+ }
+
+ auto Branch =
+ MIB.buildInstr(RISCV::PseudoBRIND, {}, {Dest.getReg(0)}).addImm(0);
+ if (!Branch.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
case TargetOpcode::G_SEXT_INREG:
return selectSExtInreg(MI, MIB);
case TargetOpcode::G_FRAME_INDEX: {
@@ -696,6 +744,97 @@ bool RISCVInstructionSelector::selectGlobalValue(
return false;
}
+// FIXME: This is very similar to selectGlobalValue. Merge somehow?
+bool RISCVInstructionSelector::selectJumpTable(MachineInstr &MI,
+ MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const {
+ assert(MI.getOpcode() == TargetOpcode::G_JUMP_TABLE &&
+ "Expected G_JUMP_TABLE");
+
+ int Idx = MI.getOperand(1).getIndex();
+
+ Register DefReg = MI.getOperand(0).getReg();
+ const LLT DefTy = MRI.getType(DefReg);
+ MachineInstr *Result = nullptr;
+
+ // When HWASAN is used and tagging of global variables is enabled
+ // they should be accessed via the GOT, since the tagged address of a global
+ // is incompatible with existing code models. This also applies to non-pic
+ // mode.
+ if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
+ if (!Subtarget->allowTaggedGlobals()) {
+ // Use PC-relative addressing to access the symbol. This generates the
+ // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
+ // %pcrel_lo(auipc)).
+ Result =
+ MIB.buildInstr(RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex(Idx);
+ } else {
+ // Use PC-relative addressing to access the GOT for this symbol, then
+ // load the address from the GOT. This generates the pattern (PseudoLGA
+ // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
+ // %pcrel_lo(auipc))).
+ MachineFunction &MF = *MI.getParent()->getParent();
+ MachineMemOperand *MemOp = MF.getMachineMemOperand(
+ MachinePointerInfo::getGOT(MF),
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
+ MachineMemOperand::MOInvariant,
+ DefTy, Align(DefTy.getSizeInBits() / 8));
+
+ Result = MIB.buildInstr(RISCV::PseudoLGA, {DefReg}, {})
+ .addJumpTableIndex(Idx)
+ .addMemOperand(MemOp);
+ }
+
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+
+ switch (TM.getCodeModel()) {
+ default: {
+ reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
+ getName(), "Unsupported code model for lowering", MI);
+ return false;
+ }
+ case CodeModel::Small: {
+ // Must lie within a single 2 GiB address range and must lie between
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
+ // (lui %hi(sym)) %lo(sym)).
+ Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI, {AddrHiDest}, {})
+ .addJumpTableIndex(Idx, RISCVII::MO_HI);
+
+ if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
+ return false;
+
+ Result = MIB.buildInstr(RISCV::ADDI, {DefReg}, {AddrHiDest})
+ .addJumpTableIndex(Idx, RISCVII::MO_LO);
+
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+ case CodeModel::Medium: {
+ // Generate a sequence for accessing addresses within any 2GiB range
+ // within the address space. This generates the pattern (PseudoLLA sym),
+ // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
+ Result =
+ MIB.buildInstr(RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex(Idx);
+
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+ }
+ return false;
+}
+
bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
MachineIRBuilder &MIB) const {
if (!STI.isRV64())
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-medium-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-medium-rv64.mir
new file mode 100644
index 000000000000000..edd071cb96a8912
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-medium-rv64.mir
@@ -0,0 +1,161 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select %s -o - \
+# RUN: -code-model=medium | FileCheck %s
+
+--- |
+ define i32 @jt_test(i32 signext %in) {
+ entry:
+ %0 = sext i32 %in to i64
+ switch i64 %0, label %default [
+ i64 1, label %bb1
+ i64 2, label %bb2
+ i64 3, label %bb3
+ i64 4, label %bb4
+ i64 5, label %bb5
+ i64 6, label %bb6
+ ]
+
+ bb1: ; preds = %entry
+ ret i32 4
+
+ bb2: ; preds = %entry
+ ret i32 3
+
+ bb3: ; preds = %entry
+ ret i32 2
+
+ bb4: ; preds = %entry
+ ret i32 1
+
+ bb5: ; preds = %entry
+ ret i32 100
+
+ bb6: ; preds = %entry
+ ret i32 200
+
+ default: ; preds = %entry
+ ret i32 1000
+ }
+
+...
+---
+name: jt_test
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+jumpTable:
+ kind: block-address
+ entries:
+ - id: 0
+ blocks: [ '%bb.2', '%bb.3', '%bb.4', '%bb.5', '%bb.6', '%bb.7' ]
+body: |
+ ; CHECK-LABEL: name: jt_test
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.8(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[COPY]], 0
+ ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[ADDIW]], -1
+ ; CHECK-NEXT: [[SLTIU:%[0-9]+]]:gpr = SLTIU [[ADDI]], 6
+ ; CHECK-NEXT: [[XORI:%[0-9]+]]:gpr = XORI [[SLTIU]], 1
+ ; CHECK-NEXT: BNE [[XORI]], $x0, %bb.8
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1.entry:
+ ; CHECK-NEXT: successors: %bb.2(0x15555555), %bb.3(0x15555555), %bb.4(0x15555555), %bb.5(0x15555555), %bb.6(0x15555555), %bb.7(0x15555555)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA %jump-table.0
+ ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI]], 3
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLLA]], [[SLLI]]
+ ; CHECK-NEXT: [[LD:%[0-9]+]]:gprjalr = LD [[ADD]], 0 :: (load (s64) from jump-table)
+ ; CHECK-NEXT: PseudoBRIND [[LD]], 0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.bb1:
+ ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 4
+ ; CHECK-NEXT: $x10 = COPY [[ADDI1]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3.bb2:
+ ; CHECK-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 3
+ ; CHECK-NEXT: $x10 = COPY [[ADDI2]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4.bb3:
+ ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 2
+ ; CHECK-NEXT: $x10 = COPY [[ADDI3]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5.bb4:
+ ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 1
+ ; CHECK-NEXT: $x10 = COPY [[ADDI4]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.6.bb5:
+ ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 100
+ ; CHECK-NEXT: $x10 = COPY [[ADDI5]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.7.bb6:
+ ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 200
+ ; CHECK-NEXT: $x10 = COPY [[ADDI6]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.8.default:
+ ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 1000
+ ; CHECK-NEXT: $x10 = COPY [[ADDI7]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ bb.1.entry:
+ successors: %bb.8, %bb.9
+ liveins: $x10
+
+ %1:gprb(s64) = COPY $x10
+ %2:gprb(s64) = G_ASSERT_SEXT %1, 32
+ %7:gprb(s64) = G_CONSTANT i64 5
+ %3:gprb(s64) = G_SEXT_INREG %2, 32
+ %4:gprb(s64) = G_CONSTANT i64 1
+ %5:gprb(s64) = G_SUB %3, %4
+ %26:gprb(s64) = G_ICMP intpred(ugt), %5(s64), %7
+ G_BRCOND %26(s64), %bb.8
+
+ bb.9.entry:
+ successors: %bb.2, %bb.3, %bb.4, %bb.5, %bb.6, %bb.7
+
+ %10:gprb(p0) = G_JUMP_TABLE %jump-table.0
+ G_BRJT %10(p0), %jump-table.0, %5(s64)
+
+ bb.2.bb1:
+ %22:gprb(s64) = G_CONSTANT i64 4
+ $x10 = COPY %22(s64)
+ PseudoRET implicit $x10
+
+ bb.3.bb2:
+ %20:gprb(s64) = G_CONSTANT i64 3
+ $x10 = COPY %20(s64)
+ PseudoRET implicit $x10
+
+ bb.4.bb3:
+ %18:gprb(s64) = G_CONSTANT i64 2
+ $x10 = COPY %18(s64)
+ PseudoRET implicit $x10
+
+ bb.5.bb4:
+ %16:gprb(s64) = G_CONSTANT i64 1
+ $x10 = COPY %16(s64)
+ PseudoRET implicit $x10
+
+ bb.6.bb5:
+ %14:gprb(s64) = G_CONSTANT i64 100
+ $x10 = COPY %14(s64)
+ PseudoRET implicit $x10
+
+ bb.7.bb6:
+ %12:gprb(s64) = G_CONSTANT i64 200
+ $x10 = COPY %12(s64)
+ PseudoRET implicit $x10
+
+ bb.8.default:
+ %24:gprb(s64) = G_CONSTANT i64 1000
+ $x10 = COPY %24(s64)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv32.mir
new file mode 100644
index 000000000000000..44073e2b4997704
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv32.mir
@@ -0,0 +1,158 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -run-pass=instruction-select %s -o - \
+# RUN: -relocation-model=pic | FileCheck %s
+
+--- |
+ define i32 @jt_test(i32 signext %in) {
+ entry:
+ switch i32 %in, label %default [
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ i32 5, label %bb5
+ i32 6, label %bb6
+ ]
+
+ bb1: ; preds = %entry
+ ret i32 4
+
+ bb2: ; preds = %entry
+ ret i32 3
+
+ bb3: ; preds = %entry
+ ret i32 2
+
+ bb4: ; preds = %entry
+ ret i32 1
+
+ bb5: ; preds = %entry
+ ret i32 100
+
+ bb6: ; preds = %entry
+ ret i32 200
+
+ default: ; preds = %entry
+ ret i32 1000
+ }
+
+...
+---
+name: jt_test
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+jumpTable:
+ kind: label-difference32
+ entries:
+ - id: 0
+ blocks: [ '%bb.2', '%bb.3', '%bb.4', '%bb.5', '%bb.6', '%bb.7' ]
+body: |
+ ; CHECK-LABEL: name: jt_test
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.8(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 200
+ ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 100
+ ; CHECK-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 1
+ ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 2
+ ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 3
+ ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 4
+ ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 1000
+ ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI [[COPY]], -1
+ ; CHECK-NEXT: [[SLTIU:%[0-9]+]]:gpr = SLTIU [[ADDI7]], 6
+ ; CHECK-NEXT: [[XORI:%[0-9]+]]:gpr = XORI [[SLTIU]], 1
+ ; CHECK-NEXT: BNE [[XORI]], $x0, %bb.8
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1.entry:
+ ; CHECK-NEXT: successors: %bb.2(0x15555555), %bb.3(0x15555555), %bb.4(0x15555555), %bb.5(0x15555555), %bb.6(0x15555555), %bb.7(0x15555555)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA %jump-table.0
+ ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI7]], 2
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLLA]], [[SLLI]]
+ ; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[ADD]], 0 :: (load (s32) from jump-table)
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:gprjalr = ADD [[LW]], [[PseudoLLA]]
+ ; CHECK-NEXT: PseudoBRIND [[ADD1]], 0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.bb1:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI5]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3.bb2:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI4]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4.bb3:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI3]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5.bb4:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI2]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.6.bb5:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI1]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.7.bb6:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.8.default:
+ ; CHECK-NEXT: $x10 = COPY [[ADDI6]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ bb.1.entry:
+ successors: %bb.8, %bb.9
+ liveins: $x10
+
+ %0:gprb(s32) = COPY $x10
+ %4:gprb(s32) = G_CONSTANT i32 5
+ %8:gprb(s32) = G_CONSTANT i32 200
+ %9:gprb(s32) = G_CONSTANT i32 100
+ %10:gprb(s32) = G_CONSTANT i32 1
+ %11:gprb(s32) = G_CONSTANT i32 2
+ %12:gprb(s32) = G_CONSTANT i32 3
+ %13:gprb(s32) = G_CONSTANT i32 4
+ %14:gprb(s32) = G_CONSTANT i32 1000
+ %1:gprb(s32) = G_CONSTANT i32 1
+ %2:gprb(s32) = G_SUB %0, %1
+ %16:gprb(s32) = G_ICMP intpred(ugt), %2(s32), %4
+ G_BRCOND %16(s32), %bb.8
+
+ bb.9.entry:
+ successors: %bb.2, %bb.3, %bb.4, %bb.5, %bb.6, %bb.7
+
+ %7:gprb(p0) = G_JUMP_TABLE %jump-table.0
+ G_BRJT %7(p0), %jump-table.0, %2(s32)
+
+ bb.2.bb1:
+ $x10 = COPY %13(s32)
+ PseudoRET implicit $x10
+
+ bb.3.bb2:
+ $x10 = COPY %12(s32)
+ PseudoRET implicit $x10
+
+ bb.4.bb3:
+ $x10 = COPY %11(s32)
+ PseudoRET implicit $x10
+
+ bb.5.bb4:
+ $x10 = COPY %10(s32)
+ PseudoRET implicit $x10
+
+ bb.6.bb5:
+ $x10 = COPY %9(s32)
+ PseudoRET implicit $x10
+
+ bb.7.bb6:
+ $x10 = COPY %8(s32)
+ PseudoRET implicit $x10
+
+ bb.8.default:
+ $x10 = COPY %14(s32)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv64.mir
new file mode 100644
index 000000000000000..24492028a97da10
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv64.mir
@@ -0,0 +1,163 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select %s -o - \
+# RUN: -relocation-model=pic | FileCheck %s
+
+--- |
+ define i32 @jt_test(i32 signext %in) {
+ entry:
+ %0 = sext i32 %in to i64
+ switch i64 %0, label %default [
+ i64 1, label %bb1
+ i64 2, label %bb2
+ i64 3, label %bb3
+ i64 4, label %bb4
+ i64 5, label %bb5
+ i64 6, label %bb6
+ ]
+
+ bb1: ; preds = %entry
+ ret i32 4
+
+ bb2: ; preds = %entry
+ ret i32 3
+
+ bb3: ; preds = %entry
+ ret i32 2
+
+ bb4: ; preds = %entry
+ ret i32 1
+
+ bb5: ; preds = %entry
+ ret i32 100
+
+ bb6: ; preds = %entry
+ ret i32 200
+
+ default: ; preds = %entry
+ ret i32 1000
+ }
+
+...
+---
+name: jt_test
+alignment: 4
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+jumpTable:
+ kind: label-difference32
+ entries:
+ - id: 0
+ blocks: [ '%bb.2', '%bb.3', '%bb.4', '%bb.5', '%bb.6', '%bb.7' ]
+body: |
+ ; CHECK-LABEL: name: jt_test
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.8(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[COPY]], 0
+ ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[ADDIW]], -1
+ ; CHECK-NEXT: [[SLTIU:%[0-9]+]]:gpr = SLTIU [[ADDI]], 6
+ ; CHECK-NEXT: [[XORI:%[0-9]+]]:gpr = XORI [[SLTIU]], 1
+ ; CHECK-NE...
[truncated]
|
@@ -405,6 +410,49 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) { | |||
MI.eraseFromParent(); | |||
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI); | |||
} | |||
case TargetOpcode::G_BRJT: { | |||
unsigned EntrySize = |
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.
In the long term, it probably makes sense to move this to a lowering action on the legalizer.
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.
X86 uses Has variables:
bool HasAVX = STI.hasAVX(); |
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.
@tschuett I'm not sure what you're suggesting I do in this patch? There's only 1 subtarget check and its in an assert.
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.
If I read your comments correctly, you have different options for the code sequence depending on which extensions are available. X86 has the same loads of 256-bit are legal, but depending on pure AVX or with VLX they haven selection strategies.
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.
The load size is determined by codemodel and pic/no-pic. This is reflected in EntrySize and the isPositionIndependent. This also affects the jump-table kind you see in the tests custom32
, block-address
, or label-difference32
The SLLI+ADD can be fused to SH2ADD or SH3ADD with the Zbb extension.
I think we can expand this whole thing to generic opcodes G_SEXTLOAD, G_SHL, G_ADD, G_BRINDIRECT, etc. during legalization and let all the pieces go through regbankselect and instruction-select individually. But G_BRINDIRECT hasn't been implemented yet. I have more fallbacks pointing at missing G_BRJT/G_JUMP_TABLE support so I wrote this to make progress.
; RUN: llc -mtriple=riscv64 -relocation-model=pic -verify-machineinstrs < %s \ | ||
; RUN: -global-isel | FileCheck %s -check-prefixes=RV64I-PIC | ||
|
||
define void @above_threshold(i32 signext %in, ptr %out) nounwind { |
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 test is a copy of a llvm/test/CodeGen/RISCV/jumptable.ll I diffed the output of both and didn't spot any differences other than instruction order.
75db97f
to
4a575f5
Compare
return false; | ||
|
||
if (MF.getTarget().isPositionIndependent()) { | ||
Dest = MIB.buildInstr(RISCV::ADD, {&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.
What does this code do? Why do we only do it for position independent?
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.
For position independent, the jump table is EK_LabelDifference32.Each entry is the address of the block minus the address of the jump table.
. So we have to add the base of the jump table to convert to an absolute address.
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.
Mind adding this in a comment so it is obvious. Thanks for checking entry kind instead of position independent, that helps to make it clear as well.
Ping |
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 with minor comment.
return false; | ||
|
||
if (MF.getTarget().isPositionIndependent()) { | ||
Dest = MIB.buildInstr(RISCV::ADD, {&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.
Mind adding this in a comment so it is obvious. Thanks for checking entry kind instead of position independent, that helps to make it clear as well.
5ce4190
to
abff076
Compare
No description provided.