diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index cbeabdddb9371..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, @@ -628,9 +634,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 +642,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/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 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/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 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