Skip to content
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
2 changes: 1 addition & 1 deletion bolt/test/RISCV/reloc-label-diff.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ _start:
// BOLT removes this nop so the label difference is initially 8 but should be
// 4 after BOLT processes it.
nop
beq x0, x0, _test_end
li x0, _test_end-.
_test_end:
ret
.size _start, .-_start
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -822,8 +822,9 @@ static bool relaxableFixupNeedsRelocation(const MCFixupKind Kind) {
default:
break;
case RISCV::fixup_riscv_rvc_jump:
case RISCV::fixup_riscv_branch:
case RISCV::fixup_riscv_rvc_branch:
case RISCV::fixup_riscv_jal:
case RISCV::fixup_riscv_qc_e_branch:
return false;
}
return true;
Expand Down
40 changes: 25 additions & 15 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ void RISCVMCCodeEmitter::expandTLSDESCCall(const MCInst &MI,
MCRegister Dest = MI.getOperand(1).getReg();
int64_t Imm = MI.getOperand(2).getImm();
addFixup(Fixups, 0, Expr, ELF::R_RISCV_TLSDESC_CALL);
if (STI.hasFeature(RISCV::FeatureRelax))
Fixups.back().setLinkerRelaxable();
MCInst Call =
MCInstBuilder(RISCV::JALR).addReg(Link).addReg(Dest).addImm(Imm);

Expand Down Expand Up @@ -344,8 +346,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 @@ -392,8 +397,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 @@ -602,8 +610,8 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
// The actual emission of `R_RISCV_RELAX` will be handled in
// `RISCVAsmBackend::applyFixup`.
bool RelaxCandidate = false;
auto AsmRelaxToLinkerRelaxableWithFeature = [&](unsigned Feature) -> void {
if (!STI.hasFeature(RISCV::FeatureExactAssembly) && STI.hasFeature(Feature))
auto AsmRelaxToLinkerRelaxable = [&]() -> void {
if (!STI.hasFeature(RISCV::FeatureExactAssembly))
RelaxCandidate = true;
};

Expand Down Expand Up @@ -658,9 +666,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 @@ -669,31 +674,36 @@ 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:
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;
AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
RelaxCandidate = true;
} else if (MIFrm == RISCVII::InstFormatB) {
FixupKind = RISCV::fixup_riscv_branch;
// This might be assembler relaxed to `b<cc>; jal` but we cannot relax
// the `jal` again in the assembler.
// Relaxes to B<cc>; JAL, with fixup_riscv_jal
AsmRelaxToLinkerRelaxable();
} else if (MIFrm == RISCVII::InstFormatCJ) {
FixupKind = RISCV::fixup_riscv_rvc_jump;
AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
// Relaxes to JAL with fixup_riscv_jal
AsmRelaxToLinkerRelaxable();
} else if (MIFrm == RISCVII::InstFormatCB) {
FixupKind = RISCV::fixup_riscv_rvc_branch;
// This might be assembler relaxed to `b<cc>; jal` but we cannot relax
// the `jal` again in the assembler.
// Relaxes to B<cc>; JAL, with fixup_riscv_jal
AsmRelaxToLinkerRelaxable();
} else if (MIFrm == RISCVII::InstFormatCI) {
FixupKind = RISCV::fixup_riscv_rvc_imm;
} else if (MIFrm == RISCVII::InstFormatI) {
FixupKind = RISCV::fixup_riscv_12_i;
} else if (MIFrm == RISCVII::InstFormatQC_EB) {
FixupKind = RISCV::fixup_riscv_qc_e_branch;
// This might be assembler relaxed to `qc.e.b<cc>; jal` but we cannot
// relax the `jal` again in the assembler.
// Relaxes to QC.E.B<cc>I; JAL, with fixup_riscv_jal
AsmRelaxToLinkerRelaxable();
} else if (MIFrm == RISCVII::InstFormatQC_EAI) {
FixupKind = RISCV::fixup_riscv_qc_e_32;
RelaxCandidate = true;
Expand Down
28 changes: 20 additions & 8 deletions llvm/test/CodeGen/RISCV/option-relax-relocation.ll
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
;; 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
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
10 changes: 7 additions & 3 deletions llvm/test/MC/RISCV/Relocations/expr.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@

## This is linker-relaxable to avoid resolving the following fixups
call relax
# CHECK-RELOC: R_RISCV_CALL_PLT
# CHECK-RELOC-NEXT: R_RISCV_RELAX

jal zero, .LBB0+16
# CHECK-INSTR: jal zero, 0x10
# CHECK-RELOC: R_RISCV_JAL
# CHECK-RELOC-NEXT: R_RISCV_JAL
# CHECK-RELOC-NEXT: R_RISCV_RELAX

beq a0, a1, .LBB1+32
# CHECK-INSTR: beq a0, a1, 0x20
Expand All @@ -24,11 +27,12 @@ c.j .+32

c.j .LBB2+4
# CHECK-INSTR: c.j 0x22
# CHECK-RELOC-NEXT: R_RISCV_RVC_JUMP
# CHECK-RELOC-NEXT: R_RISCV_RVC_JUMP

c.beqz a0, .-2
# CHECK-INSTR: c.beqz a0, 0x12

call relax
# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT
# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT
# CHECK-RELOC-NEXT: R_RISCV_RELAX
.LBB2:
6 changes: 6 additions & 0 deletions llvm/test/MC/RISCV/Relocations/relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@
# RUN: | FileCheck -check-prefix=INSTR %s
# 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-RELAX %s

# Check prefixes:
# RELOC - Check the relocation in the object.
# RELOC-RELAX - Check the relocation in the object with relaxations
# INSTR - Check the instruction is handled properly by the ASMPrinter

.long foo
# RELOC: R_RISCV_32 foo
# RELOC-RELAX: R_RISCV_32 foo

.quad foo
# RELOC: R_RISCV_64 foo
# RELOC-RELAX: R_RISCV_64 foo

lui t1, %hi(foo)
# RELOC: R_RISCV_HI20 foo 0x0
# RELOC
# INSTR: lui t1, %hi(foo)

lui t1, %hi(foo+4)
Expand Down
21 changes: 17 additions & 4 deletions llvm/test/MC/RISCV/align.s
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,14 @@ data2:
add a0, a0, a1

## Branches crossing the linker-relaxable R_RISCV_ALIGN need relocations.
# RELAX-RELOC-NOT: .rela.text3 {
# C-OR-ZCA-EXT-RELAX-RELOC-NOT: .rela.text3 {
# RELAX-RELOC: .rela.text3 {
# RELAX-RELOC-NEXT: 0x0 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x6
# RELAX-RELOC-NEXT: 0xE R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x12 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: }
# C-OR-ZCA-EXT-RELAX-RELOC: .rela.text3 {
.section .text3, "ax"
bnez t1, 1f
bnez t2, 2f
Expand All @@ -153,9 +159,11 @@ data2:
# RELAX-RELOC: .rela.text3a {
# RELAX-RELOC-NEXT: 0x0 R_RISCV_CALL_PLT foo 0x0
# RELAX-RELOC-NEXT: 0x0 R_RISCV_RELAX - 0x0
# RELAX-RELOC-NEXT: 0x8 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x10 R_RISCV_ALIGN - 0x6
# RELAX-RELOC-NEXT: 0x16 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x1A R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: }
# C-OR-ZCA-EXT-NORELAX-RELOC: .rela.text3a
# C-OR-ZCA-EXT-RELAX-RELOC: .rela.text3a
Expand All @@ -171,8 +179,13 @@ bnez t1, 2b

## .text3 with a call at the end
# RELAX-RELOC: .rela.text3b {
# RELAX-RELOC-NEXT: 0x10 R_RISCV_CALL_PLT foo 0x0
# RELAX-RELOC-NEXT: 0x10 R_RISCV_RELAX - 0x0
# RELAX-RELOC-NEXT: 0x0 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x6
# RELAX-RELOC-NEXT: 0xE R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x12 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: 0x16 R_RISCV_CALL_PLT foo 0x0
# RELAX-RELOC-NEXT: 0x16 R_RISCV_RELAX - 0x0
# RELAX-RELOC-NEXT: }
.section .text3b, "ax"
bnez t1, 1f
Expand Down
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
Loading