Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -43,6 +43,13 @@ std::unique_ptr createObjectWriter(raw_pwrite_stream &OS) const override; + // Preserve relocation types if the linker relaxation enabled. So then + // linker could has information to fixup offsets while relaxation. + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override { + return STI.getFeatureBits()[RISCV::FeatureRelax]; + } + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override; Index: lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -78,6 +78,8 @@ 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 @@ -50,6 +50,9 @@ // fixup_riscv_call - A fixup representing a call attached to the auipc // instruction in a pair composed of adjacent auipc+jalr instructions. fixup_riscv_call, + // fixup_riscv_relax - Used to generate an R_RISCV_RELAX relocation type, + // which indicates the linker may relax the instruction pair. + 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 @@ -185,7 +185,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()); @@ -253,6 +253,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/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/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/MC/RISCV/linker-relaxation.s =================================================================== --- /dev/null +++ test/MC/RISCV/linker-relaxation.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+relax < %s \ +# RUN: | llvm-readobj -r | FileCheck -check-prefix=RELAX-RELOC %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=-relax < %s \ +# RUN: | llvm-readobj -r | FileCheck -check-prefix=RELOC %s + +.long foo + +.L1: +call foo +# RELOC: R_RISCV_CALL foo 0x0 +# RELAX-RELOC: R_RISCV_CALL foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX foo 0x0 +beq s1, s1, .L1 +# RELAX-RELOC: R_RISCV_BRANCH .L1 0x0