Index: lib/Target/RISCV/RISCVExpandPseudoInsts.cpp =================================================================== --- lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -55,9 +55,16 @@ bool expandAtomicCmpXchg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked, int Width, MachineBasicBlock::iterator &NextMBBI); + bool expandAuipcInstPair(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI, + unsigned FlagsHi, unsigned SecondOpcode); bool expandLoadLocalAddress(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI); + bool expandLoadAddress(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI); }; char RISCVExpandPseudo::ID = 0; @@ -118,6 +125,8 @@ return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI); case RISCV::PseudoLLA: return expandLoadLocalAddress(MBB, MBBI, NextMBBI); + case RISCV::PseudoLA: + return expandLoadAddress(MBB, MBBI, NextMBBI); } return false; @@ -550,9 +559,10 @@ return true; } -bool RISCVExpandPseudo::expandLoadLocalAddress( +bool RISCVExpandPseudo::expandAuipcInstPair( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - MachineBasicBlock::iterator &NextMBBI) { + MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, + unsigned SecondOpcode) { MachineFunction *MF = MBB.getParent(); MachineInstr &MI = *MBBI; DebugLoc DL = MI.getDebugLoc(); @@ -569,8 +579,8 @@ MF->insert(++MBB.getIterator(), NewMBB); BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg) - .addDisp(Symbol, 0, RISCVII::MO_PCREL_HI); - BuildMI(NewMBB, DL, TII->get(RISCV::ADDI), DestReg) + .addDisp(Symbol, 0, FlagsHi); + BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg) .addReg(DestReg) .addMBB(NewMBB, RISCVII::MO_PCREL_LO); @@ -590,6 +600,28 @@ return true; } +bool RISCVExpandPseudo::expandLoadLocalAddress( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI) { + return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, + RISCV::ADDI); +} + +bool RISCVExpandPseudo::expandLoadAddress( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI) { + MachineFunction *MF = MBB.getParent(); + + if (!MF->getTarget().isPositionIndependent()) + return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, + RISCV::ADDI); + + const auto &STI = MF->getSubtarget(); + unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; + return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI, + SecondOpcode); +} + } // end of anonymous namespace INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", Index: lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- lib/Target/RISCV/RISCVISelLowering.h +++ lib/Target/RISCV/RISCVISelLowering.h @@ -112,7 +112,7 @@ } template - SDValue getAddr(NodeTy *N, SelectionDAG &DAG) const; + SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -350,10 +350,25 @@ } template -SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG) const { +SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG, + bool IsLocal) const { SDLoc DL(N); EVT Ty = getPointerTy(DAG.getDataLayout()); + if (isPositionIndependent()) { + SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0); + if (IsLocal) + // Use PC-relative addressing to access the symbol. This generates the pattern + // (PseudoLLA sym), which expands to + // (addi (auipc %pcrel_hi(sym)) %pcrel_lo(sym)). + return SDValue(DAG.getMachineNode(RISCV::PseudoLLA, DL, Ty, Addr), 0); + + // Use PC-relative addressing to access the GOT for this symbol, then load + // the address from the GOT. This generates the pattern (PseudoLA sym), + // which expands to (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(sym))). + return SDValue(DAG.getMachineNode(RISCV::PseudoLA, DL, Ty, Addr), 0); + } + switch (getTargetMachine().getCodeModel()) { default: report_fatal_error("Unsupported code model for lowering"); @@ -383,10 +398,9 @@ int64_t Offset = N->getOffset(); MVT XLenVT = Subtarget.getXLenVT(); - if (isPositionIndependent()) - report_fatal_error("Unable to lowerGlobalAddress"); - - SDValue Addr = getAddr(N, DAG); + const GlobalValue *GV = N->getGlobal(); + bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + SDValue Addr = getAddr(N, DAG, IsLocal); // In order to maximise the opportunity for common subexpression elimination, // emit a separate ADD node for the global address offset instead of folding @@ -402,9 +416,6 @@ SelectionDAG &DAG) const { BlockAddressSDNode *N = cast(Op); - if (isPositionIndependent()) - report_fatal_error("Unable to lowerBlockAddress"); - return getAddr(N, DAG); } @@ -412,9 +423,6 @@ SelectionDAG &DAG) const { ConstantPoolSDNode *N = cast(Op); - if (isPositionIndependent()) - report_fatal_error("Unable to lowerConstantPool"); - return getAddr(N, DAG); } Index: lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.cpp +++ lib/Target/RISCV/RISCVInstrInfo.cpp @@ -440,6 +440,7 @@ case RISCV::PseudoCALL: case RISCV::PseudoTAIL: case RISCV::PseudoLLA: + case RISCV::PseudoLA: return 8; case TargetOpcode::INLINEASM: { const MachineFunction &MF = *MI.getParent()->getParent(); Index: lib/Target/RISCV/RISCVMCInstLower.cpp =================================================================== --- lib/Target/RISCV/RISCVMCInstLower.cpp +++ lib/Target/RISCV/RISCVMCInstLower.cpp @@ -49,6 +49,9 @@ case RISCVII::MO_PCREL_HI: Kind = RISCVMCExpr::VK_RISCV_PCREL_HI; break; + case RISCVII::MO_GOT_HI: + Kind = RISCVMCExpr::VK_RISCV_GOT_HI; + break; } const MCExpr *ME = Index: lib/Target/RISCV/Utils/RISCVBaseInfo.h =================================================================== --- lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -53,6 +53,7 @@ MO_HI, MO_PCREL_LO, MO_PCREL_HI, + MO_GOT_HI, }; } // namespace RISCVII Index: test/CodeGen/RISCV/pic-models.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/pic-models.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -relocation-model=static < %s \ +; RUN: | FileCheck -check-prefix=RV32-STATIC %s +; RUN: llc -mtriple=riscv32 -relocation-model=pic < %s \ +; RUN: | FileCheck -check-prefix=RV32-PIC %s + +; Check basic lowering of PIC addressing. +; TODO: Check other relocation models? + +@external_var = external global i32 +@internal_var = internal global i32 42 + + +; external address + +define i32* @f1() { +; RV32-STATIC-LABEL: f1: +; RV32-STATIC: # %bb.0: # %entry +; RV32-STATIC-NEXT: lui a0, %hi(external_var) +; RV32-STATIC-NEXT: addi a0, a0, %lo(external_var) +; RV32-STATIC-NEXT: ret +; +; RV32-PIC-LABEL: f1: +; RV32-PIC: # %bb.0: # %entry +; RV32-PIC-NEXT: .LBB0_1: # %entry +; RV32-PIC-NEXT: # Label of block must be emitted +; RV32-PIC-NEXT: auipc a0, %got_pcrel_hi(external_var) +; RV32-PIC-NEXT: lw a0, %pcrel_lo(.LBB0_1)(a0) +; RV32-PIC-NEXT: ret +entry: + ret i32* @external_var +} + + +; internal address + +define i32* @f2() { +; RV32-STATIC-LABEL: f2: +; RV32-STATIC: # %bb.0: # %entry +; RV32-STATIC-NEXT: lui a0, %hi(internal_var) +; RV32-STATIC-NEXT: addi a0, a0, %lo(internal_var) +; RV32-STATIC-NEXT: ret +; +; RV32-PIC-LABEL: f2: +; RV32-PIC: # %bb.0: # %entry +; RV32-PIC-NEXT: .LBB1_1: # %entry +; RV32-PIC-NEXT: # Label of block must be emitted +; RV32-PIC-NEXT: auipc a0, %pcrel_hi(internal_var) +; RV32-PIC-NEXT: addi a0, a0, %pcrel_lo(.LBB1_1) +; RV32-PIC-NEXT: ret +entry: + ret i32* @internal_var +}