Index: lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- lib/Target/RISCV/RISCVISelLowering.h +++ lib/Target/RISCV/RISCVISelLowering.h @@ -104,6 +104,7 @@ SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue lowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -136,6 +136,7 @@ setOperationAction(ISD::GlobalAddress, XLenVT, Custom); setOperationAction(ISD::BlockAddress, XLenVT, Custom); setOperationAction(ISD::ConstantPool, XLenVT, Custom); + setOperationAction(ISD::JumpTable, XLenVT, Custom); if (Subtarget.hasStdExtA()) setMaxAtomicSizeInBitsSupported(Subtarget.getXLen()); @@ -148,9 +149,6 @@ unsigned FunctionAlignment = Subtarget.hasStdExtC() ? 1 : 2; setMinFunctionAlignment(FunctionAlignment); setPrefFunctionAlignment(FunctionAlignment); - - // Effectively disable jump table generation. - setMinimumJumpTableEntries(INT_MAX); } EVT RISCVTargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &, @@ -278,6 +276,8 @@ return lowerBlockAddress(Op, DAG); case ISD::ConstantPool: return lowerConstantPool(Op, DAG); + case ISD::JumpTable: + return lowerJumpTable(Op, DAG); case ISD::SELECT: return lowerSELECT(Op, DAG); case ISD::VASTART: @@ -357,6 +357,25 @@ } } +SDValue RISCVTargetLowering::lowerJumpTable(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + EVT Ty = Op.getValueType(); + JumpTableSDNode *N = cast(Op); + int JTI = N->getIndex(); + + if (!isPositionIndependent()) { + SDValue JTHi = DAG.getTargetJumpTable(JTI, Ty, RISCVII::MO_HI); + SDValue JTLo = DAG.getTargetJumpTable(JTI, Ty, RISCVII::MO_LO); + SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, JTHi), 0); + SDValue MNLo = + SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, JTLo), 0); + return MNLo; + } else { + report_fatal_error("Unable to lowerConstantPool"); + } +} + SDValue RISCVTargetLowering::lowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); Index: lib/Target/RISCV/RISCVMCInstLower.cpp =================================================================== --- lib/Target/RISCV/RISCVMCInstLower.cpp +++ lib/Target/RISCV/RISCVMCInstLower.cpp @@ -92,6 +92,9 @@ case MachineOperand::MO_ConstantPoolIndex: MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); break; + case MachineOperand::MO_JumpTableIndex: + MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP); + break; } return true; } Index: test/CodeGen/RISCV/jumptable.ll =================================================================== --- test/CodeGen/RISCV/jumptable.ll +++ test/CodeGen/RISCV/jumptable.ll @@ -5,34 +5,31 @@ define void @jt(i32 %in, i32* %out) { ; RV32I-LABEL: jt: ; RV32I: # %bb.0: # %entry -; RV32I-NEXT: addi a2, zero, 2 -; RV32I-NEXT: blt a2, a0, .LBB0_4 -; RV32I-NEXT: # %bb.1: # %entry -; RV32I-NEXT: addi a3, zero, 1 -; RV32I-NEXT: beq a0, a3, .LBB0_7 -; RV32I-NEXT: # %bb.2: # %entry -; RV32I-NEXT: bne a0, a2, .LBB0_9 -; RV32I-NEXT: # %bb.3: # %bb2 +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: addi a2, a0, -1 ; RV32I-NEXT: addi a0, zero, 3 -; RV32I-NEXT: sw a0, 0(a1) -; RV32I-NEXT: ret -; RV32I-NEXT: .LBB0_4: # %entry -; RV32I-NEXT: addi a3, zero, 3 -; RV32I-NEXT: beq a0, a3, .LBB0_8 -; RV32I-NEXT: # %bb.5: # %entry -; RV32I-NEXT: addi a2, zero, 4 -; RV32I-NEXT: bne a0, a2, .LBB0_9 -; RV32I-NEXT: # %bb.6: # %bb4 -; RV32I-NEXT: addi a0, zero, 1 -; RV32I-NEXT: sw a0, 0(a1) -; RV32I-NEXT: ret -; RV32I-NEXT: .LBB0_7: # %bb1 +; RV32I-NEXT: bltu a0, a2, .LBB0_6 +; RV32I-NEXT: # %bb.1: # %entry +; RV32I-NEXT: lui a3, %hi(.LJTI0_0) +; RV32I-NEXT: addi a3, a3, %lo(.LJTI0_0) +; RV32I-NEXT: slli a2, a2, 2 +; RV32I-NEXT: add a2, a2, a3 +; RV32I-NEXT: lw a2, 0(a2) +; RV32I-NEXT: jr a2 +; RV32I-NEXT: .LBB0_2: # %bb1 ; RV32I-NEXT: addi a0, zero, 4 +; RV32I-NEXT: j .LBB0_5 +; RV32I-NEXT: .LBB0_3: # %bb3 +; RV32I-NEXT: addi a0, zero, 2 +; RV32I-NEXT: j .LBB0_5 +; RV32I-NEXT: .LBB0_4: # %bb4 +; RV32I-NEXT: addi a0, zero, 1 +; RV32I-NEXT: .LBB0_5: # %exit ; RV32I-NEXT: sw a0, 0(a1) -; RV32I-NEXT: ret -; RV32I-NEXT: .LBB0_8: # %bb3 -; RV32I-NEXT: sw a2, 0(a1) -; RV32I-NEXT: .LBB0_9: # %exit +; RV32I-NEXT: .LBB0_6: # %exit +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret entry: switch i32 %in, label %exit [