Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -205,6 +205,7 @@ const MCExpr *Expr = MO.getExpr(); MCExpr::ExprKind Kind = Expr->getKind(); RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; + bool RelaxCandidate = false; if (Kind == MCExpr::Target) { const RISCVMCExpr *RVExpr = cast(Expr); @@ -219,9 +220,11 @@ FixupKind = RISCV::fixup_riscv_lo12_s; else llvm_unreachable("VK_RISCV_LO used with unexpected instruction format"); + RelaxCandidate = true; break; case RISCVMCExpr::VK_RISCV_HI: FixupKind = RISCV::fixup_riscv_hi20; + RelaxCandidate = true; break; case RISCVMCExpr::VK_RISCV_PCREL_LO: if (MIFrm == RISCVII::InstFormatI) @@ -231,12 +234,15 @@ else llvm_unreachable( "VK_RISCV_PCREL_LO used with unexpected instruction format"); + RelaxCandidate = true; break; case RISCVMCExpr::VK_RISCV_PCREL_HI: FixupKind = RISCV::fixup_riscv_pcrel_hi20; + RelaxCandidate = true; break; case RISCVMCExpr::VK_RISCV_CALL: FixupKind = RISCV::fixup_riscv_call; + RelaxCandidate = true; break; } } else if (Kind == MCExpr::SymbolRef && @@ -258,13 +264,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; - } + // Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is + // enabled and the current fixup will result in a relocation that may be + // relaxed. + if (EnableRelax && RelaxCandidate) { + const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); + Fixups.push_back( + MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), + MI.getLoc())); + ++MCNumFixups; } return 0; Index: test/MC/RISCV/linker-relaxation.s =================================================================== --- test/MC/RISCV/linker-relaxation.s +++ test/MC/RISCV/linker-relaxation.s @@ -18,9 +18,58 @@ # NORELAX-RELOC: R_RISCV_CALL foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX # RELAX-RELOC: R_RISCV_CALL foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 # RELAX-FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call -# RELAX-FIXUP: fixup B - offset: 0, value: foo, kind: fixup_riscv_relax +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax beq s1, s1, .L1 # RELAX-RELOC: R_RISCV_BRANCH .L1 0x0 # RELAX-FIXUP: fixup A - offset: 0, value: .L1, kind: fixup_riscv_branch +# RELAX-FIXUP-NOT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +lui t1, %hi(foo) +# NORELAX-RELOC: R_RISCV_HI20 foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_HI20 foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %hi(foo), kind: fixup_riscv_hi20 +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +addi t1, t1, %lo(foo) +# NORELAX-RELOC: R_RISCV_LO12_I foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_LO12_I foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %lo(foo), kind: fixup_riscv_lo12_i +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +sb t1, %lo(foo)(a2) +# NORELAX-RELOC: R_RISCV_LO12_S foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_LO12_S foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %lo(foo), kind: fixup_riscv_lo12_s +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +auipc t1, %pcrel_hi(foo) +# NORELAX-RELOC: R_RISCV_PCREL_HI20 foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_PCREL_HI20 foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_hi(foo), kind: fixup_riscv_pcrel_hi20 +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +addi t1, t1, %pcrel_lo(foo) +# NORELAX-RELOC: R_RISCV_PCREL_LO12_I foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_PCREL_LO12_I foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(foo), kind: fixup_riscv_pcrel_lo12_i +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax + +sb t1, %pcrel_lo(foo)(a2) +# NORELAX-RELOC: R_RISCV_PCREL_LO12_S foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELOC: R_RISCV_PCREL_LO12_S foo 0x0 +# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(foo), kind: fixup_riscv_pcrel_lo12_s +# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax