diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -844,6 +844,10 @@ Arch == llvm::Triple::ppc64le) return false; + // RISC-V non-small code models prefer avoiding copy relocations. + if (TT.isRISCV() && CGOpts.CodeModel != "small") + return false; + // If we can use copy relocations we can assume it is local. if (auto *Var = dyn_cast(GV)) if (!Var->isThreadLocal() && diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -676,7 +676,8 @@ unsigned SecondOpcode; unsigned FlagsHi; - if (MF->getTarget().isPositionIndependent()) { + if (MF->getTarget().isPositionIndependent() || + MF->getTarget().getCodeModel() != CodeModel::Small) { const auto &STI = MF->getSubtarget(); SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; FlagsHi = RISCVII::MO_GOT_HI; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -429,25 +429,11 @@ 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(auipc)). - 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(auipc))). - return SDValue(DAG.getMachineNode(RISCV::PseudoLA, DL, Ty, Addr), 0); - } - - switch (getTargetMachine().getCodeModel()) { - default: + CodeModel::Model M = getTargetMachine().getCodeModel(); + if (M != CodeModel::Small && M != CodeModel::Medium) report_fatal_error("Unsupported code model for lowering"); - case CodeModel::Small: { + + if (!isPositionIndependent() && M == CodeModel::Small) { // Generate a sequence for accessing addresses within the first 2 GiB of // address space. This generates the pattern (addi (lui %hi(sym)) %lo(sym)). SDValue AddrHi = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_HI); @@ -455,14 +441,18 @@ SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, AddrHi), 0); return SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, AddrLo), 0); } - 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)). - SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0); + + 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(auipc)). 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(auipc))). + return SDValue(DAG.getMachineNode(RISCV::PseudoLA, DL, Ty, Addr), 0); } SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op, diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -189,6 +189,9 @@ // PowerPC prefers avoiding copy relocations. if (Arch == Triple::ppc || TT.isPPC64()) return false; + // RISC-V non-small code models prefer avoiding copy relocations. + if (TT.isRISCV() && getCodeModel() != CodeModel::Small) + return false; // Check if we can use copy relocations. if (!(GV && GV->isThreadLocal()) && RM == Reloc::Static) diff --git a/llvm/test/CodeGen/RISCV/pic-models.ll b/llvm/test/CodeGen/RISCV/pic-models.ll --- a/llvm/test/CodeGen/RISCV/pic-models.ll +++ b/llvm/test/CodeGen/RISCV/pic-models.ll @@ -8,6 +8,10 @@ ; RUN: llc -mtriple=riscv64 -relocation-model=pic < %s \ ; RUN: | FileCheck -check-prefix=RV64-PIC %s +;; Use PIC address sequence for medium code model, even if position dependent. +; RUN: llc -mtriple=riscv64 -relocation-model=static -code-model=medium < %s \ +; RUN: | FileCheck -check-prefix=RV64-PIC %s + ; Check basic lowering of PIC addressing. ; TODO: Check other relocation models?