diff options
author | Craig Topper <craig.topper@sifive.com> | 2023-11-18 12:33:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-18 12:33:25 -0800 |
commit | 20f544d047e34283884d09e24db400de5077487f (patch) | |
tree | 2baed61d3404406bb4bc37f5464003bafe348390 | |
parent | 8ad4df8327e617c7ef1a727df61e4600ef13ed85 (diff) |
[RISCV][GISel] Instruction selection for G_JUMP_TABLE and G_BRJT. (#71987)
7 files changed, 1257 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 25f4a217c070..3c72269d1e00 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 @@ private: 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; @@ -483,6 +486,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: { Register LHS, RHS; RISCVCC::CondCode CC; @@ -493,6 +498,58 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) { MI.eraseFromParent(); return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI); } + case TargetOpcode::G_BRJT: { + // FIXME: Move to legalization? + const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + unsigned EntrySize = MJTI->getEntrySize(MF.getDataLayout()); + assert((EntrySize == 4 || (Subtarget->is64Bit() && EntrySize == 8)) && + "Unsupported jump-table entry size"); + assert( + (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + MJTI->getEntryKind() == MachineJumpTableInfo::EK_Custom32 || + MJTI->getEntryKind() == MachineJumpTableInfo::EK_BlockAddress) && + "Unexpected jump-table entry kind"); + + 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. Moving to legalization would fix this automatically. + 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(MJTI->getEntryAlignment(MF.getDataLayout())))); + if (!Dest.constrainAllUses(TII, TRI, RBI)) + return false; + + // If the Kind is EK_LabelDifference32, the table stores an offset from + // the location of the table. Add the table address to get an absolute + // address. + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) { + 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: { @@ -784,6 +841,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 000000000000..5d980e772145 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-medium-rv64.mir @@ -0,0 +1,160 @@ +# 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: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[COPY]], 0 + ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[ADDIW]], -1 + ; CHECK-NEXT: BLTU [[ADDI]], [[ADDI1]], %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 [[ADDI1]], 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: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: $x10 = COPY [[ADDI2]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.bb2: + ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: $x10 = COPY [[ADDI3]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.bb3: + ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: $x10 = COPY [[ADDI4]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.bb4: + ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: $x10 = COPY [[ADDI5]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.bb5: + ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 100 + ; CHECK-NEXT: $x10 = COPY [[ADDI6]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.bb6: + ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 200 + ; CHECK-NEXT: $x10 = COPY [[ADDI7]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.8.default: + ; CHECK-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; CHECK-NEXT: $x10 = COPY [[ADDI8]] + ; 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 000000000000..27fe465ccf69 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-rv32.mir @@ -0,0 +1,157 @@ +# 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, 5 + ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 200 + ; CHECK-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 100 + ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; CHECK-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI [[COPY]], -1 + ; CHECK-NEXT: BLTU [[ADDI]], [[ADDI8]], %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 [[ADDI8]], 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 [[ADDI6]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.bb2: + ; CHECK-NEXT: $x10 = COPY [[ADDI5]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.bb3: + ; CHECK-NEXT: $x10 = COPY [[ADDI4]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.bb4: + ; CHECK-NEXT: $x10 = COPY [[ADDI3]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.bb5: + ; CHECK-NEXT: $x10 = COPY [[ADDI2]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.bb6: + ; CHECK-NEXT: $x10 = COPY [[ADDI1]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.8.default: + ; CHECK-NEXT: $x10 = COPY [[ADDI7]] + ; 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 000000000000..77156b913c5e --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-pic-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: -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 +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, 5 + ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[COPY]], 0 + ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[ADDIW]], -1 + ; CHECK-NEXT: BLTU [[ADDI]], [[ADDI1]], %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 [[ADDI1]], 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: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: $x10 = COPY [[ADDI2]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.bb2: + ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: $x10 = COPY [[ADDI3]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.bb3: + ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: $x10 = COPY [[ADDI4]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.bb4: + ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: $x10 = COPY [[ADDI5]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.bb5: + ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 100 + ; CHECK-NEXT: $x10 = COPY [[ADDI6]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.bb6: + ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 200 + ; CHECK-NEXT: $x10 = COPY [[ADDI7]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.8.default: + ; CHECK-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; CHECK-NEXT: $x10 = COPY [[ADDI8]] + ; 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-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-rv32.mir new file mode 100644 index 000000000000..388c238b86eb --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-rv32.mir @@ -0,0 +1,213 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+m -run-pass=instruction-select %s -o - \ +# RUN: -code-model=small | FileCheck %s --check-prefix=RV32-SMALL +# RUN: llc -mtriple=riscv32 -mattr=+m -run-pass=instruction-select %s -o - \ +# RUN: -code-model=medium | FileCheck %s --check-prefix=RV32-MEDIUM + +--- | + 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: block-address + entries: + - id: 0 + blocks: [ '%bb.2', '%bb.3', '%bb.4', '%bb.5', '%bb.6', '%bb.7' ] +body: | + ; RV32-SMALL-LABEL: name: jt_test + ; RV32-SMALL: bb.0.entry: + ; RV32-SMALL-NEXT: successors: %bb.8(0x40000000), %bb.1(0x40000000) + ; RV32-SMALL-NEXT: liveins: $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 + ; RV32-SMALL-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; RV32-SMALL-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 200 + ; RV32-SMALL-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 100 + ; RV32-SMALL-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 1 + ; RV32-SMALL-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 2 + ; RV32-SMALL-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 3 + ; RV32-SMALL-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 4 + ; RV32-SMALL-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; RV32-SMALL-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI [[COPY]], -1 + ; RV32-SMALL-NEXT: BLTU [[ADDI]], [[ADDI8]], %bb.8 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.1.entry: + ; RV32-SMALL-NEXT: successors: %bb.2(0x15555555), %bb.3(0x15555555), %bb.4(0x15555555), %bb.5(0x15555555), %bb.6(0x15555555), %bb.7(0x15555555) + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: [[LUI:%[0-9]+]]:gpr = LUI target-flags(riscv-hi) %jump-table.0 + ; RV32-SMALL-NEXT: [[ADDI9:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) %jump-table.0 + ; RV32-SMALL-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI8]], 2 + ; RV32-SMALL-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[ADDI9]], [[SLLI]] + ; RV32-SMALL-NEXT: [[LW:%[0-9]+]]:gprjalr = LW [[ADD]], 0 :: (load (s32) from jump-table) + ; RV32-SMALL-NEXT: PseudoBRIND [[LW]], 0 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.2.bb1: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI6]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.3.bb2: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI5]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.4.bb3: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI4]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.5.bb4: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI3]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.6.bb5: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI2]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.7.bb6: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI1]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; RV32-SMALL-NEXT: {{ $}} + ; RV32-SMALL-NEXT: bb.8.default: + ; RV32-SMALL-NEXT: $x10 = COPY [[ADDI7]] + ; RV32-SMALL-NEXT: PseudoRET implicit $x10 + ; + ; RV32-MEDIUM-LABEL: name: jt_test + ; RV32-MEDIUM: bb.0.entry: + ; RV32-MEDIUM-NEXT: successors: %bb.8(0x40000000), %bb.1(0x40000000) + ; RV32-MEDIUM-NEXT: liveins: $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 + ; RV32-MEDIUM-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; RV32-MEDIUM-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 200 + ; RV32-MEDIUM-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI $x0, 100 + ; RV32-MEDIUM-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 1 + ; RV32-MEDIUM-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 2 + ; RV32-MEDIUM-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 3 + ; RV32-MEDIUM-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 4 + ; RV32-MEDIUM-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; RV32-MEDIUM-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI [[COPY]], -1 + ; RV32-MEDIUM-NEXT: BLTU [[ADDI]], [[ADDI8]], %bb.8 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.1.entry: + ; RV32-MEDIUM-NEXT: successors: %bb.2(0x15555555), %bb.3(0x15555555), %bb.4(0x15555555), %bb.5(0x15555555), %bb.6(0x15555555), %bb.7(0x15555555) + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA %jump-table.0 + ; RV32-MEDIUM-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI8]], 2 + ; RV32-MEDIUM-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLLA]], [[SLLI]] + ; RV32-MEDIUM-NEXT: [[LW:%[0-9]+]]:gprjalr = LW [[ADD]], 0 :: (load (s32) from jump-table) + ; RV32-MEDIUM-NEXT: PseudoBRIND [[LW]], 0 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.2.bb1: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI6]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.3.bb2: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI5]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.4.bb3: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI4]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.5.bb4: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI3]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.6.bb5: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI2]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.7.bb6: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI1]] + ; RV32-MEDIUM-NEXT: PseudoRET implicit $x10 + ; RV32-MEDIUM-NEXT: {{ $}} + ; RV32-MEDIUM-NEXT: bb.8.default: + ; RV32-MEDIUM-NEXT: $x10 = COPY [[ADDI7]] + ; RV32-MEDIUM-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-small-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-small-rv64.mir new file mode 100644 index 000000000000..09a855105c26 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/jump-table-brjt-small-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=small | 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: custom32 + 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, 5 + ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[COPY]], 0 + ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[ADDIW]], -1 + ; CHECK-NEXT: BLTU [[ADDI]], [[ADDI1]], %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: [[LUI:%[0-9]+]]:gpr = LUI target-flags(riscv-hi) %jump-table.0 + ; CHECK-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) %jump-table.0 + ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI1]], 2 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[ADDI2]], [[SLLI]] + ; CHECK-NEXT: [[LW:%[0-9]+]]:gprjalr = LW [[ADD]], 0 :: (load (s32) from jump-table) + ; CHECK-NEXT: PseudoBRIND [[LW]], 0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2.bb1: + ; CHECK-NEXT: [[ADDI3:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: $x10 = COPY [[ADDI3]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.bb2: + ; CHECK-NEXT: [[ADDI4:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: $x10 = COPY [[ADDI4]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.bb3: + ; CHECK-NEXT: [[ADDI5:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: $x10 = COPY [[ADDI5]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.bb4: + ; CHECK-NEXT: [[ADDI6:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: $x10 = COPY [[ADDI6]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.bb5: + ; CHECK-NEXT: [[ADDI7:%[0-9]+]]:gpr = ADDI $x0, 100 + ; CHECK-NEXT: $x10 = COPY [[ADDI7]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.bb6: + ; CHECK-NEXT: [[ADDI8:%[0-9]+]]:gpr = ADDI $x0, 200 + ; CHECK-NEXT: $x10 = COPY [[ADDI8]] + ; CHECK-NEXT: PseudoRET implicit $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.8.default: + ; CHECK-NEXT: [[ADDI9:%[0-9]+]]:gpr = ADDI $x0, 1000 + ; CHECK-NEXT: $x10 = COPY [[ADDI9]] + ; 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/jumptable.ll b/llvm/test/CodeGen/RISCV/GlobalISel/jumptable.ll new file mode 100644 index 000000000000..601290812bb2 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/jumptable.ll @@ -0,0 +1,257 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -code-model=small -verify-machineinstrs < %s \ +; RUN: -global-isel | FileCheck %s -check-prefixes=RV32I-SMALL +; RUN: llc -mtriple=riscv32 -code-model=medium -verify-machineinstrs < %s \ +; RUN: -global-isel | FileCheck %s -check-prefixes=RV32I-MEDIUM +; RUN: llc -mtriple=riscv32 -relocation-model=pic -verify-machineinstrs < %s \ +; RUN: -global-isel | FileCheck %s -check-prefixes=RV32I-PIC +; RUN: llc -mtriple=riscv64 -code-model=small -verify-machineinstrs < %s \ +; RUN: -global-isel | FileCheck %s -check-prefixes=RV64I-SMALL +; RUN: llc -mtriple=riscv64 -code-model=medium -verify-machineinstrs < %s \ +; RUN: -global-isel | FileCheck %s -check-prefixes=RV64I-MEDIUM +; 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 { +; RV32I-SMALL-LABEL: above_threshold: +; RV32I-SMALL: # %bb.0: # %entry +; RV32I-SMALL-NEXT: li a2, 5 +; RV32I-SMALL-NEXT: addi a0, a0, -1 +; RV32I-SMALL-NEXT: bltu a2, a0, .LBB0_9 +; RV32I-SMALL-NEXT: # %bb.1: # %entry +; RV32I-SMALL-NEXT: lui a2, %hi(.LJTI0_0) +; RV32I-SMALL-NEXT: addi a2, a2, %lo(.LJTI0_0) +; RV32I-SMALL-NEXT: slli a0, a0, 2 +; RV32I-SMALL-NEXT: add a0, a2, a0 +; RV32I-SMALL-NEXT: lw a0, 0(a0) +; RV32I-SMALL-NEXT: jr a0 +; RV32I-SMALL-NEXT: .LBB0_2: # %bb1 +; RV32I-SMALL-NEXT: li a0, 4 +; RV32I-SMALL-NEXT: j .LBB0_8 +; RV32I-SMALL-NEXT: .LBB0_3: # %bb5 +; RV32I-SMALL-NEXT: li a0, 100 +; RV32I-SMALL-NEXT: j .LBB0_8 +; RV32I-SMALL-NEXT: .LBB0_4: # %bb3 +; RV32I-SMALL-NEXT: li a0, 2 +; RV32I-SMALL-NEXT: j .LBB0_8 +; RV32I-SMALL-NEXT: .LBB0_5: # %bb4 +; RV32I-SMALL-NEXT: li a0, 1 +; RV32I-SMALL-NEXT: j .LBB0_8 +; RV32I-SMALL-NEXT: .LBB0_6: # %bb2 +; RV32I-SMALL-NEXT: li a0, 3 +; RV32I-SMALL-NEXT: j .LBB0_8 +; RV32I-SMALL-NEXT: .LBB0_7: # %bb6 +; RV32I-SMALL-NEXT: li a0, 200 +; RV32I-SMALL-NEXT: .LBB0_8: # %exit +; RV32I-SMALL-NEXT: sw a0, 0(a1) +; RV32I-SMALL-NEXT: .LBB0_9: # %exit +; RV32I-SMALL-NEXT: ret +; +; RV32I-MEDIUM-LABEL: above_threshold: +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: li a2, 5 +; RV32I-MEDIUM-NEXT: addi a0, a0, -1 +; RV32I-MEDIUM-NEXT: bltu a2, a0, .LBB0_9 +; RV32I-MEDIUM-NEXT: # %bb.1: # %entry +; RV32I-MEDIUM-NEXT: .Lpcrel_hi0: +; RV32I-MEDIUM-NEXT: auipc a2, %pcrel_hi(.LJTI0_0) +; RV32I-MEDIUM-NEXT: addi a2, a2, %pcrel_lo(.Lpcrel_hi0) +; RV32I-MEDIUM-NEXT: slli a0, a0, 2 +; RV32I-MEDIUM-NEXT: add a0, a2, a0 +; RV32I-MEDIUM-NEXT: lw a0, 0(a0) +; RV32I-MEDIUM-NEXT: jr a0 +; RV32I-MEDIUM-NEXT: .LBB0_2: # %bb1 +; RV32I-MEDIUM-NEXT: li a0, 4 +; RV32I-MEDIUM-NEXT: j .LBB0_8 +; RV32I-MEDIUM-NEXT: .LBB0_3: # %bb5 +; RV32I-MEDIUM-NEXT: li a0, 100 +; RV32I-MEDIUM-NEXT: j .LBB0_8 +; RV32I-MEDIUM-NEXT: .LBB0_4: # %bb3 +; RV32I-MEDIUM-NEXT: li a0, 2 +; RV32I-MEDIUM-NEXT: j .LBB0_8 +; RV32I-MEDIUM-NEXT: .LBB0_5: # %bb4 +; RV32I-MEDIUM-NEXT: li a0, 1 +; RV32I-MEDIUM-NEXT: j .LBB0_8 +; RV32I-MEDIUM-NEXT: .LBB0_6: # %bb2 +; RV32I-MEDIUM-NEXT: li a0, 3 +; RV32I-MEDIUM-NEXT: j .LBB0_8 +; RV32I-MEDIUM-NEXT: .LBB0_7: # %bb6 +; RV32I-MEDIUM-NEXT: li a0, 200 +; RV32I-MEDIUM-NEXT: .LBB0_8: # %exit +; RV32I-MEDIUM-NEXT: sw a0, 0(a1) +; RV32I-MEDIUM-NEXT: .LBB0_9: # %exit +; RV32I-MEDIUM-NEXT: ret +; +; RV32I-PIC-LABEL: above_threshold: +; RV32I-PIC: # %bb.0: # %entry +; RV32I-PIC-NEXT: li a2, 5 +; RV32I-PIC-NEXT: addi a0, a0, -1 +; RV32I-PIC-NEXT: bltu a2, a0, .LBB0_9 +; RV32I-PIC-NEXT: # %bb.1: # %entry +; RV32I-PIC-NEXT: .Lpcrel_hi0: +; RV32I-PIC-NEXT: auipc a2, %pcrel_hi(.LJTI0_0) +; RV32I-PIC-NEXT: addi a2, a2, %pcrel_lo(.Lpcrel_hi0) +; RV32I-PIC-NEXT: slli a0, a0, 2 +; RV32I-PIC-NEXT: add a0, a2, a0 +; RV32I-PIC-NEXT: lw a0, 0(a0) +; RV32I-PIC-NEXT: add a0, a0, a2 +; RV32I-PIC-NEXT: jr a0 +; RV32I-PIC-NEXT: .LBB0_2: # %bb1 +; RV32I-PIC-NEXT: li a0, 4 +; RV32I-PIC-NEXT: j .LBB0_8 +; RV32I-PIC-NEXT: .LBB0_3: # %bb5 +; RV32I-PIC-NEXT: li a0, 100 +; RV32I-PIC-NEXT: j .LBB0_8 +; RV32I-PIC-NEXT: .LBB0_4: # %bb3 +; RV32I-PIC-NEXT: li a0, 2 +; RV32I-PIC-NEXT: j .LBB0_8 +; RV32I-PIC-NEXT: .LBB0_5: # %bb4 +; RV32I-PIC-NEXT: li a0, 1 +; RV32I-PIC-NEXT: j .LBB0_8 +; RV32I-PIC-NEXT: .LBB0_6: # %bb2 +; RV32I-PIC-NEXT: li a0, 3 +; RV32I-PIC-NEXT: j .LBB0_8 +; RV32I-PIC-NEXT: .LBB0_7: # %bb6 +; RV32I-PIC-NEXT: li a0, 200 +; RV32I-PIC-NEXT: .LBB0_8: # %exit +; RV32I-PIC-NEXT: sw a0, 0(a1) +; RV32I-PIC-NEXT: .LBB0_9: # %exit +; RV32I-PIC-NEXT: ret +; +; RV64I-SMALL-LABEL: above_threshold: +; RV64I-SMALL: # %bb.0: # %entry +; RV64I-SMALL-NEXT: li a2, 5 +; RV64I-SMALL-NEXT: sext.w a0, a0 +; RV64I-SMALL-NEXT: addi a0, a0, -1 +; RV64I-SMALL-NEXT: bltu a2, a0, .LBB0_9 +; RV64I-SMALL-NEXT: # %bb.1: # %entry +; RV64I-SMALL-NEXT: lui a2, %hi(.LJTI0_0) +; RV64I-SMALL-NEXT: addi a2, a2, %lo(.LJTI0_0) +; RV64I-SMALL-NEXT: slli a0, a0, 2 +; RV64I-SMALL-NEXT: add a0, a2, a0 +; RV64I-SMALL-NEXT: lw a0, 0(a0) +; RV64I-SMALL-NEXT: jr a0 +; RV64I-SMALL-NEXT: .LBB0_2: # %bb1 +; RV64I-SMALL-NEXT: li a0, 4 +; RV64I-SMALL-NEXT: j .LBB0_8 +; RV64I-SMALL-NEXT: .LBB0_3: # %bb5 +; RV64I-SMALL-NEXT: li a0, 100 +; RV64I-SMALL-NEXT: j .LBB0_8 +; RV64I-SMALL-NEXT: .LBB0_4: # %bb3 +; RV64I-SMALL-NEXT: li a0, 2 +; RV64I-SMALL-NEXT: j .LBB0_8 +; RV64I-SMALL-NEXT: .LBB0_5: # %bb4 +; RV64I-SMALL-NEXT: li a0, 1 +; RV64I-SMALL-NEXT: j .LBB0_8 +; RV64I-SMALL-NEXT: .LBB0_6: # %bb2 +; RV64I-SMALL-NEXT: li a0, 3 +; RV64I-SMALL-NEXT: j .LBB0_8 +; RV64I-SMALL-NEXT: .LBB0_7: # %bb6 +; RV64I-SMALL-NEXT: li a0, 200 +; RV64I-SMALL-NEXT: .LBB0_8: # %exit +; RV64I-SMALL-NEXT: sw a0, 0(a1) +; RV64I-SMALL-NEXT: .LBB0_9: # %exit +; RV64I-SMALL-NEXT: ret +; +; RV64I-MEDIUM-LABEL: above_threshold: +; RV64I-MEDIUM: # %bb.0: # %entry +; RV64I-MEDIUM-NEXT: li a2, 5 +; RV64I-MEDIUM-NEXT: sext.w a0, a0 +; RV64I-MEDIUM-NEXT: addi a0, a0, -1 +; RV64I-MEDIUM-NEXT: bltu a2, a0, .LBB0_9 +; RV64I-MEDIUM-NEXT: # %bb.1: # %entry +; RV64I-MEDIUM-NEXT: .Lpcrel_hi0: +; RV64I-MEDIUM-NEXT: auipc a2, %pcrel_hi(.LJTI0_0) +; RV64I-MEDIUM-NEXT: addi a2, a2, %pcrel_lo(.Lpcrel_hi0) +; RV64I-MEDIUM-NEXT: slli a0, a0, 3 +; RV64I-MEDIUM-NEXT: add a0, a2, a0 +; RV64I-MEDIUM-NEXT: ld a0, 0(a0) +; RV64I-MEDIUM-NEXT: jr a0 +; RV64I-MEDIUM-NEXT: .LBB0_2: # %bb1 +; RV64I-MEDIUM-NEXT: li a0, 4 +; RV64I-MEDIUM-NEXT: j .LBB0_8 +; RV64I-MEDIUM-NEXT: .LBB0_3: # %bb5 +; RV64I-MEDIUM-NEXT: li a0, 100 +; RV64I-MEDIUM-NEXT: j .LBB0_8 +; RV64I-MEDIUM-NEXT: .LBB0_4: # %bb3 +; RV64I-MEDIUM-NEXT: li a0, 2 +; RV64I-MEDIUM-NEXT: j .LBB0_8 +; RV64I-MEDIUM-NEXT: .LBB0_5: # %bb4 +; RV64I-MEDIUM-NEXT: li a0, 1 +; RV64I-MEDIUM-NEXT: j .LBB0_8 +; RV64I-MEDIUM-NEXT: .LBB0_6: # %bb2 +; RV64I-MEDIUM-NEXT: li a0, 3 +; RV64I-MEDIUM-NEXT: j .LBB0_8 +; RV64I-MEDIUM-NEXT: .LBB0_7: # %bb6 +; RV64I-MEDIUM-NEXT: li a0, 200 +; RV64I-MEDIUM-NEXT: .LBB0_8: # %exit +; RV64I-MEDIUM-NEXT: sw a0, 0(a1) +; RV64I-MEDIUM-NEXT: .LBB0_9: # %exit +; RV64I-MEDIUM-NEXT: ret +; +; RV64I-PIC-LABEL: above_threshold: +; RV64I-PIC: # %bb.0: # %entry +; RV64I-PIC-NEXT: li a2, 5 +; RV64I-PIC-NEXT: sext.w a0, a0 +; RV64I-PIC-NEXT: addi a0, a0, -1 +; RV64I-PIC-NEXT: bltu a2, a0, .LBB0_9 +; RV64I-PIC-NEXT: # %bb.1: # %entry +; RV64I-PIC-NEXT: .Lpcrel_hi0: +; RV64I-PIC-NEXT: auipc a2, %pcrel_hi(.LJTI0_0) +; RV64I-PIC-NEXT: addi a2, a2, %pcrel_lo(.Lpcrel_hi0) +; RV64I-PIC-NEXT: slli a0, a0, 2 +; RV64I-PIC-NEXT: add a0, a2, a0 +; RV64I-PIC-NEXT: lw a0, 0(a0) +; RV64I-PIC-NEXT: add a0, a0, a2 +; RV64I-PIC-NEXT: jr a0 +; RV64I-PIC-NEXT: .LBB0_2: # %bb1 +; RV64I-PIC-NEXT: li a0, 4 +; RV64I-PIC-NEXT: j .LBB0_8 +; RV64I-PIC-NEXT: .LBB0_3: # %bb5 +; RV64I-PIC-NEXT: li a0, 100 +; RV64I-PIC-NEXT: j .LBB0_8 +; RV64I-PIC-NEXT: .LBB0_4: # %bb3 +; RV64I-PIC-NEXT: li a0, 2 +; RV64I-PIC-NEXT: j .LBB0_8 +; RV64I-PIC-NEXT: .LBB0_5: # %bb4 +; RV64I-PIC-NEXT: li a0, 1 +; RV64I-PIC-NEXT: j .LBB0_8 +; RV64I-PIC-NEXT: .LBB0_6: # %bb2 +; RV64I-PIC-NEXT: li a0, 3 +; RV64I-PIC-NEXT: j .LBB0_8 +; RV64I-PIC-NEXT: .LBB0_7: # %bb6 +; RV64I-PIC-NEXT: li a0, 200 +; RV64I-PIC-NEXT: .LBB0_8: # %exit +; RV64I-PIC-NEXT: sw a0, 0(a1) +; RV64I-PIC-NEXT: .LBB0_9: # %exit +; RV64I-PIC-NEXT: ret +entry: + switch i32 %in, label %exit [ + 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: + store i32 4, ptr %out + br label %exit +bb2: + store i32 3, ptr %out + br label %exit +bb3: + store i32 2, ptr %out + br label %exit +bb4: + store i32 1, ptr %out + br label %exit +bb5: + store i32 100, ptr %out + br label %exit +bb6: + store i32 200, ptr %out + br label %exit +exit: + ret void +} |