Skip to content

[RISCV] Mark More Relocs as Relaxable #151422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
27 changes: 20 additions & 7 deletions llvm/test/CodeGen/RISCV/option-relax-relocation.ll
Original file line number Diff line number Diff line change
@@ -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

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

; 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe J is not supposed to be assembler- or linker- relaxable. Then we should not mark it as such.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Table Jump Relaxation applies to JAL and want the R_RISCV_JAL to be marked with R_RISCV_RELAX: https://riscv-non-isa.github.io/riscv-elf-psabi-doc/#_table_jump_relaxation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL :) Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even aside from that couldn't jal be relaxed to c.jal and j to c.j (with the former only being available on RV32)? I don't think that's a currently-implemented relaxation, it's only done if the original (pseudo)instruction is a call, but for those that believe in the fun that is linker relaxation it would seem an obvious one to implement.

; 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
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/MC/RISCV/Relocations/expr.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -31,4 +32,5 @@ c.beqz a0, .-2

call relax
# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT
# CHECK-RELOC-NEXT: R_RISCV_RELAX
.LBB2:
4 changes: 3 additions & 1 deletion llvm/test/MC/RISCV/compressed-relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
# 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.
# INSTR - Check the instruction is handled properly by the ASMPrinter
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
112 changes: 72 additions & 40 deletions llvm/test/MC/RISCV/linker-relaxation.s
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/test/MC/RISCV/option-relax.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/MC/RISCV/xqcibi-relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ qc.e.bgeui s2, 24, same_section
# OBJ: qc.beqi t1, 0xa, 0x42 <same_section_extern+0x16>
# OBJ-NEXT: j 0x3e <same_section_extern+0x12>
# 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 <same_section_extern+0x20>
# OBJ-NEXT: j 0x48 <same_section_extern+0x1c>
# OBJ-NEXT: R_RISCV_JAL undef{{$}}
# OBJ-NEXT: R_RISCV_RELAX *ABS*{{$}}
qc.e.bgeui s0, 40, undef

.section .text.second, "ax", @progbits
Expand Down