Index: lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- lib/Target/PowerPC/PPCISelLowering.h +++ lib/Target/PowerPC/PPCISelLowering.h @@ -840,7 +840,15 @@ SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + + unsigned getJumpTableEncoding() const override; + const MCExpr * + LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, unsigned uid, + MCContext &Ctx) const override; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerBR_JT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -260,7 +261,10 @@ if (!Subtarget.useCRBits()) setOperationAction(ISD::BRCOND, MVT::Other, Expand); - setOperationAction(ISD::BR_JT, MVT::Other, Expand); + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) + setOperationAction(ISD::BR_JT, MVT::Other, Custom); + else + setOperationAction(ISD::BR_JT, MVT::Other, Expand); // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); @@ -2179,12 +2183,65 @@ return LowerLabelRef(CPIHi, CPILo, IsPIC, DAG); } +/// Return the entry encoding for a jump table in the +/// current function. The returned value is a member of the +/// MachineJumpTableInfo::JTEntryKind enum. +unsigned PPCTargetLowering::getJumpTableEncoding() const { + // 64-bit SVR4 ABI code is always position-independent. + // The actual address of the GlobalValue is stored in the TOC. + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) + return MachineJumpTableInfo::EK_Custom32; + + // Otherwise, use the normal jump table encoding heuristics. + return TargetLowering::getJumpTableEncoding(); +} + +const MCExpr * +PPCTargetLowering::LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid,MCContext &Ctx) const{ + assert(Subtarget.isSVR4ABI() && Subtarget.isPPC64()); + + const MCExpr *Value = MCSymbolRefExpr::create(MBB->getSymbol(), Ctx); + MCSymbol *PB = MBB->getParent()->getPICBaseSymbol(); + + const MCExpr *Base = MCSymbolRefExpr::create(PB, Ctx); + return MCBinaryExpr::createSub(Value, Base, Ctx); +} + +/// Custom lowering of BR_JT for the 64bit SYSV ABI. +SDValue +PPCTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Table = Op.getOperand(1); + SDValue Index = Op.getOperand(2); + SDLoc DL(Op); + auto &TD = DAG.getDataLayout(); + EVT PTy = getPointerTy(TD); + unsigned EntrySize = + DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD); + + Index = DAG.getNode(ISD::MUL, DL, Index.getValueType(), Index, + DAG.getConstant(EntrySize, DL, Index.getValueType())); + SDValue Addr = DAG.getNode(ISD::ADD, DL, Index.getValueType(), Index, Table); + + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); + SDValue LD = DAG.getExtLoad( + ISD::SEXTLOAD, DL, PTy, Chain, Addr, + MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), MemVT); + + // 64-bit SVR4 ABI code is always position-independent. + Addr = DAG.getNode(ISD::ADD, DL, PTy, LD, + DAG.getNode(PPCISD::GlobalBaseReg, DL, PTy)); + + return DAG.getNode(ISD::BRIND, DL, MVT::Other, LD.getValue(1), Addr); +} + SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast(Op); // 64-bit SVR4 ABI code is always position-independent. - // The actual address of the GlobalValue is stored in the TOC. if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); @@ -8322,6 +8379,7 @@ case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::BR_JT: return lowerBR_JT(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); Index: test/CodeGen/PowerPC/mcm-5.ll =================================================================== --- test/CodeGen/PowerPC/mcm-5.ll +++ test/CodeGen/PowerPC/mcm-5.ll @@ -50,11 +50,17 @@ %5 = load i32, i32* %i.addr, align 4 ret i32 %5 } +; CHECK-LABEL: test_jump_table: +; CHECK: bl .L0$pb +; CHECK-NEXT: .L0$pb: +; CHECK: mflr [[REGBASE:[0-9]+]] -; CHECK-LABEL: test_jump_table: -; CHECK: addis [[REG1:[0-9]+]], 2, .LC[[TOCNUM:[0-9]+]]@toc@ha -; CHECK: ld [[REG2:[0-9]+]], .LC[[TOCNUM]]@toc@l([[REG1]]) -; CHECK: ldx {{[0-9]+}}, {{[0-9]+}}, [[REG2]] -; CHECK: .section .toc -; CHECK: .LC[[TOCNUM]]: -; CHECK: .tc {{[a-z0-9A-Z_.]+}}[TC],{{[a-z0-9A-Z_.]+}} +; CHECK: addis [[REG1:[0-9]+]], 2, .LC[[TOCNUM:[0-9]+]]@toc@ha +; CHECK: ld [[REG2:[0-9]+]], .LC[[TOCNUM]]@toc@l([[REG1]]) +; CHECK: lwax [[REG3:[0-9]+]], {{[0-9]+}}, [[REG2]] +; CHECK-NEXT: add [[REG4:[0-9]+]], [[REG3]], [[REGBASE]] +; CHECK-NEXT: mtctr [[REG4]] +; CHECK-NEXT: bctr + +; CHECK-LABEL: .LJTI0_0: +; CHECK-NEXT: .long .LBB0_{{[0-9]+}}-.L0$pb