Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -60,7 +60,7 @@ if (FixupKind == RISCV::fixup_riscv_pcrel_lo12_i || FixupKind == RISCV::fixup_riscv_pcrel_hi20) return true; - return false; + return STI.getFeatureBits()[RISCV::FeatureRelax]; } bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, Index: lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -73,6 +73,10 @@ return ELF::R_RISCV_RVC_JUMP; case RISCV::fixup_riscv_rvc_branch: return ELF::R_RISCV_RVC_BRANCH; + case RISCV::fixup_riscv_call: + return ELF::R_RISCV_CALL; + case RISCV::fixup_riscv_relax: + return ELF::R_RISCV_RELAX; } } Index: lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h +++ lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h @@ -47,6 +47,10 @@ // fixup_riscv_rvc_branch - 8-bit fixup for symbol references in the // compressed branch instruction fixup_riscv_rvc_branch, + // fixup_riscv_call - For generate R_RISCV_CALL to relax function call. + fixup_riscv_call, + // fixup_riscv_relax - For generate R_RISCV_RELAX relax relocation type. + fixup_riscv_relax, // fixup_riscv_invalid - used as a sentinel and a marker, must be last fixup fixup_riscv_invalid, Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -138,7 +138,7 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { - + bool EnableRelax = STI.getFeatureBits()[RISCV::FeatureRelax]; const MCOperand &MO = MI.getOperand(OpNo); MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); @@ -183,6 +183,18 @@ case RISCVMCExpr::VK_RISCV_PCREL_HI: FixupKind = RISCV::fixup_riscv_pcrel_hi20; break; + case RISCVMCExpr::VK_RISCV_CALL_LO: + if (EnableRelax) + return 0; + else + FixupKind = RISCV::fixup_riscv_pcrel_lo12_i; + break; + case RISCVMCExpr::VK_RISCV_CALL_HI: + if (EnableRelax) + FixupKind = RISCV::fixup_riscv_call; + else + FixupKind = RISCV::fixup_riscv_pcrel_hi20; + break; } } else if (Kind == MCExpr::SymbolRef && cast(Expr)->getKind() == MCSymbolRefExpr::VK_None) { @@ -203,6 +215,15 @@ MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); ++MCNumFixups; + if (EnableRelax) { + if (FixupKind == RISCV::fixup_riscv_call) { + Fixups.push_back( + MCFixup::create(0, Expr, MCFixupKind(RISCV::fixup_riscv_relax), + MI.getLoc())); + ++MCNumFixups; + } + } + return 0; } Index: lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h +++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h @@ -28,6 +28,8 @@ VK_RISCV_HI, VK_RISCV_PCREL_LO, VK_RISCV_PCREL_HI, + VK_RISCV_CALL_LO, + VK_RISCV_CALL_HI, VK_RISCV_Invalid }; Index: lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -67,8 +67,10 @@ case VK_RISCV_HI: return "hi"; case VK_RISCV_PCREL_LO: + case VK_RISCV_CALL_LO: return "pcrel_lo"; case VK_RISCV_PCREL_HI: + case VK_RISCV_CALL_HI: return "pcrel_hi"; } } @@ -76,7 +78,8 @@ bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const { MCValue Value; - if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO) + if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO || + Kind == VK_RISCV_CALL_HI || Kind == VK_RISCV_CALL_LO) return false; if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) Index: lib/Target/RISCV/RISCV.td =================================================================== --- lib/Target/RISCV/RISCV.td +++ lib/Target/RISCV/RISCV.td @@ -55,6 +55,10 @@ def RV64 : HwMode<"+64bit">; def RV32 : HwMode<"-64bit">; +def FeatureRelax + : SubtargetFeature<"relax", "EnableLinkerRelax", "true", + "Enable Linker relaxation.">; + //===----------------------------------------------------------------------===// // Registers, calling conventions, instruction descriptions. //===----------------------------------------------------------------------===// Index: lib/Target/RISCV/RISCVAsmPrinter.cpp =================================================================== --- lib/Target/RISCV/RISCVAsmPrinter.cpp +++ lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -84,13 +84,13 @@ // Create high part expression HiExpr for AUIPC. Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext); const MCExpr *HiExpr = - RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_PCREL_HI, OutContext); + RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_CALL_HI, OutContext); // Create low part expression LoExpr for JALR. auto HiLabel = OutContext.createTempSymbol(); Expr = MCSymbolRefExpr::create(HiLabel, MCSymbolRefExpr::VK_None, OutContext); const MCExpr *LoExpr = - RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_PCREL_LO, OutContext); + RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_CALL_LO, OutContext); // Emit .LtmpX: OutStreamer->EmitLabel(HiLabel); Index: lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- lib/Target/RISCV/RISCVSubtarget.h +++ lib/Target/RISCV/RISCVSubtarget.h @@ -36,6 +36,7 @@ bool HasStdExtD = false; bool HasStdExtC = false; bool HasRV64 = false; + bool EnableLinkerRelax = false; unsigned XLen = 32; MVT XLenVT = MVT::i32; RISCVFrameLowering FrameLowering; @@ -77,6 +78,7 @@ bool hasStdExtD() const { return HasStdExtD; } bool hasStdExtC() const { return HasStdExtC; } bool is64Bit() const { return HasRV64; } + bool enableLinkerRelax() const { return EnableLinkerRelax; } MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } }; Index: test/CodeGen/RISCV/linker-relaxation.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/linker-relaxation.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple=riscv32 -filetype=obj -mattr=+relax < %s \ +; RUN: | llvm-readobj -r | FileCheck -check-prefix=RELOC %s + +declare i32 @external_function(i32) + +define i32 @test_call_external(i32 %a) nounwind { +; RELOC: R_RISCV_CALL external_function 0x0 +; RELOC: R_RISCV_RELAX external_function 0x0 + %1 = call i32 @external_function(i32 %a) + ret i32 %1 +}