From a41bb0608aa39118cc90f3fc7421ad51b9166d15 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Wed, 30 Jul 2025 16:32:05 -0700 Subject: [PATCH 1/3] [RISCV] Mark More Relocs as Relaxable Since this code was last reviewed, more relaxations have been added for existing standard relocations that LLVM didn't have marked as relaxable. This code ensures that LLVM marks the following relocations (and their respective fixups) as relaxable: - `R_RISCV_JAL` - `R_RISCV_GOT_HI20` - `R_RISCV_TPREL_HI20` - `R_RISCV_TLSDESC_HI20` --- .../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 9 +- llvm/test/MC/RISCV/linker-relaxation.s | 112 +++++++++++------- 2 files changed, 78 insertions(+), 43 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index cbeabdddb9371..c7135c8e7ab7f 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -628,9 +628,6 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, llvm_unreachable("VK_TPREL_LO used with unexpected instruction format"); RelaxCandidate = true; break; - case ELF::R_RISCV_TPREL_HI20: - RelaxCandidate = true; - break; case ELF::R_RISCV_CALL_PLT: FixupKind = RISCV::fixup_riscv_call_plt; RelaxCandidate = true; @@ -639,11 +636,17 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, FixupKind = RISCV::fixup_riscv_qc_abs20_u; RelaxCandidate = true; break; + case ELF::R_RISCV_GOT_HI20: + case ELF::R_RISCV_TPREL_HI20: + case ELF::R_RISCV_TLSDESC_HI20: + RelaxCandidate = true; + break; } } else if (Kind == MCExpr::SymbolRef || Kind == MCExpr::Binary) { // FIXME: Sub kind binary exprs have chance of underflow. if (MIFrm == RISCVII::InstFormatJ) { FixupKind = RISCV::fixup_riscv_jal; + RelaxCandidate = true; } else if (MIFrm == RISCVII::InstFormatB) { FixupKind = RISCV::fixup_riscv_branch; } else if (MIFrm == RISCVII::InstFormatCJ) { diff --git a/llvm/test/MC/RISCV/linker-relaxation.s b/llvm/test/MC/RISCV/linker-relaxation.s index 6b0685baaa69e..c5c4e4877ff2e 100644 --- a/llvm/test/MC/RISCV/linker-relaxation.s +++ b/llvm/test/MC/RISCV/linker-relaxation.s @@ -8,49 +8,57 @@ # RUN: | llvm-readobj -r - | FileCheck -check-prefix=NORELAX-RELOC %s .long foo +# NORELAX-RELOC: R_RISCV_32 foo 0x0 +# RELAX-RELOC: R_RISCV_32 foo 0x0 call foo -# NORELAX-RELOC: R_RISCV_CALL_PLT foo 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_CALL_PLT foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_CALL_PLT foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_CALL_PLT foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 + +jal foo +# NORELAX-RELOC-NEXT: R_RISCV_JAL foo 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELAX-RELOC-NEXT: R_RISCV_JAL foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 lui t1, %hi(foo) -# NORELAX-RELOC: R_RISCV_HI20 foo 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_HI20 foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_HI20 foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_HI20 foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 addi t1, t1, %lo(foo) -# NORELAX-RELOC: R_RISCV_LO12_I foo 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_LO12_I foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_LO12_I foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_LO12_I foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 sb t1, %lo(foo)(a2) -# NORELAX-RELOC: R_RISCV_LO12_S foo 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_LO12_S foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_LO12_S foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_LO12_S foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 1: auipc t1, %pcrel_hi(foo) -# NORELAX-RELOC: R_RISCV_PCREL_HI20 foo 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_PCREL_HI20 foo 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_HI20 foo 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_HI20 foo 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 addi t1, t1, %pcrel_lo(1b) -# NORELAX-RELOC: R_RISCV_PCREL_LO12_I .Ltmp0 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_I .Ltmp0 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_I .Ltmp0 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_I .Ltmp0 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 sb t1, %pcrel_lo(1b)(a2) -# NORELAX-RELOC: R_RISCV_PCREL_LO12_S .Ltmp0 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_S .Ltmp0 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_S .Ltmp0 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_S .Ltmp0 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 # Check behaviour when a locally defined symbol is referenced. @@ -63,64 +71,88 @@ call bar # NORELAX-RELOC-NOT: R_RISCV_CALL # NORELAX-RELOC-NOT: R_RISCV_RELAX # RELAX-RELOC-NEXT: R_RISCV_CALL_PLT bar 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 + +jal bar +# NORELAX-RELOC-NOT: R_RISCV_JAL +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELAX-RELOC-NEXT: R_RISCV_JAL bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 beq s1, s1, bar # NORELAX-RELOC-NOT: R_RISCV_BRANCH # RELAX-RELOC-NEXT: R_RISCV_BRANCH bar 0x0 lui t1, %hi(bar) -# NORELAX-RELOC: R_RISCV_HI20 bar 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_HI20 bar 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_HI20 bar 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_HI20 bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 addi t1, t1, %lo(bar) -# NORELAX-RELOC: R_RISCV_LO12_I bar 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_LO12_I bar 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_LO12_I bar 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_LO12_I bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 sb t1, %lo(bar)(a2) -# NORELAX-RELOC: R_RISCV_LO12_S bar 0x0 +# NORELAX-RELOC-NEXT: R_RISCV_LO12_S bar 0x0 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_LO12_S bar 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_LO12_S bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 2: auipc t1, %pcrel_hi(bar) # NORELAX-RELOC-NOT: R_RISCV_PCREL_HI20 # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_HI20 bar 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_HI20 bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 addi t1, t1, %pcrel_lo(2b) # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_I # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_I .Ltmp1 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_I .Ltmp1 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 sb t1, %pcrel_lo(2b)(a2) # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_S # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_S .Ltmp1 0x0 -# RELAX-RELOC: R_RISCV_RELAX - 0x0 +# RELAX-RELOC-NEXT: R_RISCV_PCREL_LO12_S .Ltmp1 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 + +auipc t1, %got_pcrel_hi(bar) +# NORELAX-RELOC-NEXT: R_RISCV_GOT_HI20 bar 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELAX-RELOC-NEXT: R_RISCV_GOT_HI20 bar 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 + +lui t1, %tprel_hi(baz) +# NORELAX-RELOC-NEXT: R_RISCV_TPREL_HI20 baz 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELAX-RELOC-NEXT: R_RISCV_TPREL_HI20 baz 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 + +auipc t1, %tlsdesc_hi(baz) +# NORELAX-RELOC-NEXT: R_RISCV_TLSDESC_HI20 baz 0x0 +# NORELAX-RELOC-NOT: R_RISCV_RELAX +# RELAX-RELOC-NEXT: R_RISCV_TLSDESC_HI20 baz 0x0 +# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 ## %hi/%lo on an absolute symbol (not yet defined) leads to relocations when relaxation is enabled. lui t2, %hi(abs) # NORELAX-RELOC-NOT: R_RISCV_ -# RELAX-RELOC: R_RISCV_HI20 - 0x12345 +# RELAX-RELOC-NEXT: R_RISCV_HI20 - 0x12345 # RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 addi t2, t2, %lo(abs) # NORELAX-RELOC-NOT: R_RISCV_ -# RELAX-RELOC: R_RISCV_LO12_I - 0x12345 +# RELAX-RELOC-NEXT: R_RISCV_LO12_I - 0x12345 # RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 .set abs, 0x12345 lui t3, %hi(abs) -# RELAX-RELOC: R_RISCV_HI20 - 0x12345 +# RELAX-RELOC-NEXT: R_RISCV_HI20 - 0x12345 # RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0 # Check that a relocation is not emitted for a symbol difference which has From c9c3edfc3343321ec7d79084d92eb597b662194a Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Wed, 30 Jul 2025 17:42:17 -0700 Subject: [PATCH 2/3] Fix Tests, Relaxation --- .../Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 10 ++++++++-- llvm/test/MC/RISCV/Relocations/expr.s | 2 ++ llvm/test/MC/RISCV/compressed-relocations.s | 4 +++- llvm/test/MC/RISCV/option-relax.s | 1 + llvm/test/MC/RISCV/xqcibi-relocations.s | 2 ++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index c7135c8e7ab7f..3ec7ce549d950 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -340,8 +340,11 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI, // Drop any fixup added so we can add the correct one. Fixups.resize(FixupStartIndex); - if (SrcSymbol.isExpr()) + if (SrcSymbol.isExpr()) { addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal); + if (STI.hasFeature(RISCV::FeatureRelax)) + Fixups.back().setLinkerRelaxable(); + } } // Expand PseudoLongQC_(E_)Bxxx to an inverted conditional branch and an @@ -388,8 +391,11 @@ void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI, support::endian::write(CB, JBinary, llvm::endianness::little); // Drop any fixup added so we can add the correct one. Fixups.resize(FixupStartIndex); - if (SrcSymbol.isExpr()) + if (SrcSymbol.isExpr()) { addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal); + if (STI.hasFeature(RISCV::FeatureRelax)) + Fixups.back().setLinkerRelaxable(); + } } void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, diff --git a/llvm/test/MC/RISCV/Relocations/expr.s b/llvm/test/MC/RISCV/Relocations/expr.s index 7d4dfd30e3fb7..c26ef98f653fb 100644 --- a/llvm/test/MC/RISCV/Relocations/expr.s +++ b/llvm/test/MC/RISCV/Relocations/expr.s @@ -14,6 +14,7 @@ call relax jal zero, .LBB0+16 # CHECK-INSTR: jal zero, 0x10 # CHECK-RELOC: R_RISCV_JAL +# CHECK-RELOC-NEXT: R_RISCV_RELAX beq a0, a1, .LBB1+32 # CHECK-INSTR: beq a0, a1, 0x20 @@ -31,4 +32,5 @@ c.beqz a0, .-2 call relax # CHECK-RELOC-NEXT: R_RISCV_CALL_PLT +# CHECK-RELOC-NEXT: R_RISCV_RELAX .LBB2: diff --git a/llvm/test/MC/RISCV/compressed-relocations.s b/llvm/test/MC/RISCV/compressed-relocations.s index 82cb1a12c389b..ba57507d0b4e8 100644 --- a/llvm/test/MC/RISCV/compressed-relocations.s +++ b/llvm/test/MC/RISCV/compressed-relocations.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c < %s \ # RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,+relax < %s \ -# RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s +# RUN: | llvm-readobj -r - | FileCheck -check-prefixes=RELOC,RELAX %s # Check prefixes: # RELOC - Check the relocation in the object. @@ -11,10 +11,12 @@ c.jal foo # A compressed jump (c.j) to an unresolved symbol will be relaxed to a (jal). # RELOC: R_RISCV_JAL +# RELAX-NEXT: R_RISCV_RELAX # INSTR: c.jal foo c.bnez a0, foo # A compressed branch (c.bnez) to an unresolved symbol will be relaxed to a (bnez). # The (bnez) to an unresolved symbol will in turn be relaxed to (beqz; jal) # RELOC-NEXT: R_RISCV_JAL +# RELAX-NEXT: R_RISCV_RELAX # INSTR: c.bnez a0, foo diff --git a/llvm/test/MC/RISCV/option-relax.s b/llvm/test/MC/RISCV/option-relax.s index 55cdbeae01a4e..e591c824eb437 100644 --- a/llvm/test/MC/RISCV/option-relax.s +++ b/llvm/test/MC/RISCV/option-relax.s @@ -39,6 +39,7 @@ call bar .dword .L2-.L1 # CHECK-RELOC-NEXT: R_RISCV_JAL +# CHECK-RELOC-NEXT: R_RISCV_RELAX jal zero, .L1 # CHECK-RELOC-NEXT: R_RISCV_BRANCH beq s1, s1, .L1 diff --git a/llvm/test/MC/RISCV/xqcibi-relocations.s b/llvm/test/MC/RISCV/xqcibi-relocations.s index 931cd7c9314bb..e613bc7bc4778 100644 --- a/llvm/test/MC/RISCV/xqcibi-relocations.s +++ b/llvm/test/MC/RISCV/xqcibi-relocations.s @@ -91,12 +91,14 @@ qc.e.bgeui s2, 24, same_section # OBJ: qc.beqi t1, 0xa, 0x42 # OBJ-NEXT: j 0x3e # OBJ-NEXT: R_RISCV_JAL undef{{$}} +# OBJ-NEXT: R_RISCV_RELAX *ABS*{{$}} qc.bnei t1, 10, undef # ASM: qc.e.bgeui s0, 40, undef # OBJ-NEXT: qc.e.bltui s0, 0x28, 0x4c # OBJ-NEXT: j 0x48 # OBJ-NEXT: R_RISCV_JAL undef{{$}} +# OBJ-NEXT: R_RISCV_RELAX *ABS*{{$}} qc.e.bgeui s0, 40, undef .section .text.second, "ax", @progbits From 5f3d90ccfa889ef511d25e949b76d927f6683bb3 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Wed, 30 Jul 2025 20:58:56 -0700 Subject: [PATCH 3/3] Fix .option relax inline asm test --- .../CodeGen/RISCV/option-relax-relocation.ll | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/option-relax-relocation.ll b/llvm/test/CodeGen/RISCV/option-relax-relocation.ll index fd3d9435e22a3..a6c65c816d3d8 100644 --- a/llvm/test/CodeGen/RISCV/option-relax-relocation.ll +++ b/llvm/test/CodeGen/RISCV/option-relax-relocation.ll @@ -1,32 +1,45 @@ -;; With +relax, J below needs a relocation to ensure the target is correct -;; after linker relaxation. See https://github.com/ClangBuiltLinux/linux/issues/1965 ; RUN: llc -mtriple=riscv64 -mattr=-relax -filetype=obj < %s \ ; RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefixes=CHECK,NORELAX ; RUN: llc -mtriple=riscv64 -mattr=+relax -filetype=obj < %s \ ; RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefixes=CHECK,RELAX +;; With +relax, All `j` instructions below need a relocation to ensure the target is correct +;; after linker relaxation. See https://github.com/ClangBuiltLinux/linux/issues/1965 + ; CHECK: j {{.*}} ; RELAX-NEXT: R_RISCV_JAL {{.*}} +; RELAX-NOT: R_RISCV_RELAX ; CHECK-NEXT: auipc ra, 0x0 ; CHECK-NEXT: R_RISCV_CALL_PLT f ; RELAX-NEXT: R_RISCV_RELAX *ABS* ; CHECK-NEXT: jalr ra ; CHECK-NEXT: j {{.*}} +; RELAX-NEXT: R_RISCV_JAL {{.*}} +; RELAX-NOT: R_RISCV_RELAX ; CHECK-NEXT: j {{.*}} -; RELAX-NEXT: R_RISCV_JAL .L0 +; RELAX-NEXT: R_RISCV_JAL {{.*}} +; RELAX-NEXT: R_RISCV_RELAX *ABS* ; NORELAX-NEXT: li a0, 0x0 ; RELAX-EMPTY: define dso_local noundef signext i32 @main() local_unnamed_addr #0 { entry: - callbr void asm sideeffect ".option push\0A.option norelax\0Aj $0\0A.option pop\0A", "!i"() - to label %asm.fallthrough [label %label] + callbr void asm sideeffect " + .option push + .option norelax + j $0 + .option pop", + "!i"() to label %asm.fallthrough [label %label] asm.fallthrough: ; preds = %entry tail call void @f() - callbr void asm sideeffect ".option push\0A.option norelax\0Aj $0\0A.option pop\0A", "!i"() - to label %asm.fallthrough [label %label] + callbr void asm sideeffect " + .option push + .option norelax + j $0 + .option pop", + "!i"() to label %asm.fallthrough [label %label] br label %label label: ; preds = %asm.fallthrough, %entry