Skip to content

[LoongArch][MC] Refine conditions for emitting ALIGN relocations #153365

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 1 commit 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
15 changes: 11 additions & 4 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,19 @@ getRelocPairForSize(unsigned Size) {
// size, the fixup encodes MaxBytesToEmit in the higher bits and references a
// per-section marker symbol.
bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
// Alignments before the first linker-relaxable instruction have fixed sizes
// and do not require relocations. Alignments after a linker-relaxable
// instruction require a relocation, even if the STI specifies norelax.
//
// firstLinkerRelaxable is the layout order within the subsection, which may
// be smaller than the section's order. Therefore, alignments in a
// lower-numbered subsection may be unnecessarily treated as linker-relaxable.
auto *Sec = F.getParent();
if (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
return false;

// Use default handling unless linker relaxation is enabled and the
// MaxBytesToEmit >= the nop size.
if (!F.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax))
return false;
const unsigned MinNopLen = 4;
unsigned MaxBytesToEmit = F.getAlignMaxBytesToEmit();
if (MaxBytesToEmit < MinNopLen)
Expand Down Expand Up @@ -254,8 +263,6 @@ bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN);
F.setVarFixups({Fixup});
F.setLinkerRelaxable();
if (!F.getParent()->isLinkerRelaxable())
F.getParent()->setFirstLinkerRelaxable(F.getLayoutOrder());
return true;
}

Expand Down
27 changes: 17 additions & 10 deletions llvm/test/CodeGen/LoongArch/linker-relaxation.ll
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ declare void @callee1() nounwind
declare dso_local void @callee2() nounwind
declare dso_local void @callee3() nounwind

define ptr @caller() nounwind {
; RELAX: R_LARCH_ALIGN - 0x1C
; CHECK-RELOC: R_LARCH_GOT_PC_HI20 g_e 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; RELAX: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_GOT_PC_LO12 g_e 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; PCALA-RELOC: R_LARCH_PCALA_HI20 .bss 0x0
Expand Down Expand Up @@ -77,26 +75,35 @@ define ptr @caller() nounwind {
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_TLS_LE_LO12_R t_le 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee1 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee2 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee3 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; PCALA-RELOC: R_LARCH_PCALA_HI20 .data 0x0
; RELAX-NEXT: R_LARCH_PCALA_HI20 g_i1 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; PCALA-RELOC: R_LARCH_PCALA_LO12 .data 0x0
; RELAX-NEXT: R_LARCH_PCALA_LO12 g_i1 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; RELAX-NEXT: R_LARCH_ALIGN - 0x1C
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee1 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee2 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0
; CHECK-RELOC-NEXT: R_LARCH_CALL36 callee3 0x0
; RELAX-NEXT: R_LARCH_RELAX - 0x0

;; No ALIGN reloc will emit before the first linker-relaxable instruction.
define ptr @loader() nounwind {
%a = load volatile i32, ptr @g_e
%b = load volatile i32, ptr @g_i
%c = load volatile i32, ptr @t_un
%d = load volatile i32, ptr @t_ld
%e = load volatile i32, ptr @t_ie
%f = load volatile i32, ptr @t_le
ret ptr @g_i1
}

;; ALIGN reloc will be emitted here.
define void @caller() nounwind {
call i32 @callee1()
call i32 @callee2()
tail call i32 @callee3()
ret ptr @g_i1
ret void
}
10 changes: 6 additions & 4 deletions llvm/test/MC/LoongArch/Misc/cfi-advance.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@
# RUN: | llvm-readobj -r - | FileCheck --check-prefix=RELAX %s

# RELOC: Relocations [
# RELOC-NEXT: .rela.eh_frame {
# RELOC: .rela.eh_frame {
# RELOC-NEXT: 0x1C R_LARCH_32_PCREL .text 0x0
# RELOC-NEXT: }
# RELOC-NEXT: ]
# DWARFDUMP: DW_CFA_advance_loc: 4
# DWARFDUMP: DW_CFA_advance_loc: 8
# DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8
# DWARFDUMP-NEXT: DW_CFA_advance_loc: 8
# DWARFDUMP-NEXT: DW_CFA_advance_loc: 4
# DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8

# RELAX: Relocations [
# RELAX: .rela.eh_frame {
# RELAX-NEXT: 0x1C R_LARCH_32_PCREL .L{{.*}} 0x0
# RELAX-NEXT: 0x20 R_LARCH_ADD32 .L{{.*}} 0x0
# RELAX-NEXT: 0x20 R_LARCH_SUB32 .L{{.*}} 0x0
# RELAX-NEXT: 0x25 R_LARCH_ADD6 .L{{.*}} 0x0
# RELAX-NEXT: 0x25 R_LARCH_SUB6 .L{{.*}} 0x0
# RELAX-NEXT: 0x28 R_LARCH_ADD6 .L{{.*}} 0x0
# RELAX-NEXT: 0x28 R_LARCH_SUB6 .L{{.*}} 0x0
# RELAX-NEXT: }
Expand All @@ -30,7 +32,7 @@
.type test,@function
test:
.cfi_startproc
nop
call36 foo
.cfi_def_cfa_offset 8
.p2align 3
nop
Expand Down
57 changes: 57 additions & 0 deletions llvm/test/MC/LoongArch/Relocations/align-after-relax.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## The file testing R_LARCH_ALIGN emitting when linker-relaxation enabled.

# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o %t.n
# RUN: llvm-objdump -dr %t.n | FileCheck %s --check-prefix=NORELAX
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.r
# RUN: llvm-objdump -dr %t.r | FileCheck %s --check-prefix=RELAX

# NORELAX: pcaddu18i $ra, 0
# NORELAX-NEXT: R_LARCH_CALL36 f
# NORELAX-NEXT: jirl $ra, $ra, 0
# NORELAX-COUNT-6: nop
# NORELAX: pcaddu18i $ra, 0
# NORELAX-NEXT: R_LARCH_CALL36 f
# NORELAX-NEXT: jirl $ra, $ra, 0
# NORELAX-COUNT-6: nop
# NORELAX: pcaddu18i $ra, 0
# NORELAX-NEXT: R_LARCH_CALL36 f
# NORELAX-NEXT: jirl $ra, $ra, 0

# RELAX: pcaddu18i $ra, 0
# RELAX-NEXT: R_LARCH_CALL36 f
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: jirl $ra, $ra, 0
# RELAX-NEXT: nop
# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0x1c
# RELAX-COUNT-6: nop
# RELAX: pcaddu18i $ra, 0
# RELAX-NEXT: R_LARCH_CALL36 f
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: jirl $ra, $ra, 0
# RELAX-NEXT: nop
# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0x1c
# RELAX-COUNT-6: nop
# RELAX: pcaddu18i $ra, 0
# RELAX-NEXT: R_LARCH_CALL36 f
# RELAX-NEXT: jirl $ra, $ra, 0

.text
## No R_LARCH_ALIGN before the first linker-relaxable instruction.
.p2align 5
foo:
call36 f

## R_LARCH_ALIGN is required after the first linker-relaxable instruction.
.p2align 5
bar:
call36 f

.option push
.option norelax
## R_LARCH_ALIGN is required even if norelax, because it is after a
## linker-relaxable instruction. No R_LARCH_RELAX for call36 because
## of the norelax.
.p2align 5
baz:
call36 f
.option pop
20 changes: 12 additions & 8 deletions llvm/test/MC/LoongArch/Relocations/relax-addsub.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

# NORELAX: Relocations [
# NORELAX-NEXT: Section ({{.*}}) .rela.text {
# NORELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .text 0x0
# NORELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .text 0x0
# NORELAX-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# NORELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .text 0x8
# NORELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .text 0x8
# NORELAX-NEXT: }
# NORELAX-NEXT: Section ({{.*}}) .rela.data {
# NORELAX-NEXT: 0x30 R_LARCH_ADD8 foo 0x0
Expand All @@ -22,17 +23,19 @@

# NORELAX: Hex dump of section '.data':
# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004
# NORELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c
# NORELAX-NEXT: 0x00000010 04040004 00000004 00000000 00000004
# NORELAX-NEXT: 0x00000020 08080008 00000008 00000000 00000008
# NORELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000

# RELAX: Relocations [
# RELAX-NEXT: Section ({{.*}}) .rela.text {
# RELAX-NEXT: 0x4 R_LARCH_ALIGN - 0xC
# RELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .L1 0x0
# RELAX-NEXT: 0x10 R_LARCH_RELAX - 0x0
# RELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .L1 0x0
# RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0
# RELAX-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# RELAX-NEXT: 0x0 R_LARCH_RELAX - 0x0
# RELAX-NEXT: 0xC R_LARCH_ALIGN - 0xC
# RELAX-NEXT: 0x18 R_LARCH_PCALA_HI20 .L1 0x0
# RELAX-NEXT: 0x18 R_LARCH_RELAX - 0x0
# RELAX-NEXT: 0x1C R_LARCH_PCALA_LO12 .L1 0x0
# RELAX-NEXT: 0x1C R_LARCH_RELAX - 0x0
# RELAX-NEXT: }
# RELAX-NEXT: Section ({{.*}}) .rela.data {
# RELAX-NEXT: 0x10 R_LARCH_ADD8 .L3 0x0
Expand Down Expand Up @@ -73,6 +76,7 @@
# RELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000

.text
call36 foo
.L1:
nop
.L2:
Expand Down
35 changes: 35 additions & 0 deletions llvm/test/MC/LoongArch/Relocations/relax-align-in-subsection.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## The file testing R_LARCH_ALIGN emitting when linker-relaxation enabled.

# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.n
# RUN: llvm-objdump -dr %t.n | FileCheck %s --check-prefix=RELAX
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym FILL=1 %s -o %t.f
# RUN: llvm-objdump -dr %t.f | FileCheck %s --check-prefixes=RELAX,ALIGN

# ALIGN: nop
# ALIGN-NEXT: R_LARCH_ALIGN *ABS*+0x1c
# ALIGN-COUNT-6: nop
# RELAX: ret
# RELAX: pcaddu18i $ra, 0
# RELAX-NEXT: R_LARCH_CALL36 f
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: jirl $ra, $ra, 0

.text
.option push
.option norelax
## When FILL is defined, the order of Alignment directive in this lower-numbered
## subsection will be larger, and even larger than the section order of the first
## linker-relaxable call36 instruction. It should conservatively be treated as
## linker-relaxable even has norelax.
.ifdef FILL
.space 0
.endif
.p2align 5
foo:
ret
.option pop

.text 1
.space 0
bar:
call36 f
26 changes: 16 additions & 10 deletions llvm/test/MC/LoongArch/Relocations/relax-align.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
# RUN: llvm-readobj -r %t.r | FileCheck %s --check-prefixes=RELOC,RELAX-RELOC

.text
break 0
# INSTR: break 0
call36 foo
# INSTR: pcaddu18i $ra, 0
# INSTR-NEXT: jirl $ra, $ra, 0

## Not emit R_LARCH_ALIGN if alignment directive is less than or equal to
## minimum code alignment(a.k.a 4).
Expand All @@ -24,8 +25,8 @@ break 0
## The behavior is the same as GNU assembler.
break 1
.p2align 4, 1
# INSTR-NEXT: break 1
# INSTR-COUNT-2: 01 01 01 01
# INSTR-NEXT: break 1
# INSTR-NEXT: 01 01 01 01

break 2
.p2align 4, 1, 12
Expand Down Expand Up @@ -62,20 +63,25 @@ ret

## Test the symbol index is different from .text.
.section .text2, "ax"
call36 foo
.p2align 4
.p2align 4, , 4
break 7

# RELOC: Relocations [
# RELAX-RELOC-NEXT: Section ({{.*}}) .rela.text {
# RELOC-NEXT: Section ({{.*}}) .rela.text {
# RELOC-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# RELAX-RELOC-NEXT: 0x0 R_LARCH_RELAX - 0x0
# RELAX-RELOC-NEXT: 0x24 R_LARCH_ALIGN - 0xC
# RELAX-RELOC-NEXT: 0x34 R_LARCH_ALIGN - 0x1C
# RELAX-RELOC-NEXT: 0x50 R_LARCH_ALIGN - 0xC
# RELAX-RELOC-NEXT: 0x60 R_LARCH_ALIGN .Lla-relax-align0 0xB04
# RELAX-RELOC-NEXT: 0x70 R_LARCH_ALIGN - 0xC
# RELAX-RELOC-NEXT: }
# RELAX-RELOC-NEXT: Section ({{.*}}) .rela.text2 {
# RELAX-RELOC-NEXT: 0x0 R_LARCH_ALIGN - 0xC
# RELAX-RELOC-NEXT: 0xC R_LARCH_ALIGN .Lla-relax-align1 0x404
# RELAX-RELOC-NEXT: }
# RELOC-NEXT: }
# RELOC-NEXT: Section ({{.*}}) .rela.text2 {
# RELOC-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# RELAX-RELOC-NEXT: 0x0 R_LARCH_RELAX - 0x0
# RELAX-RELOC-NEXT: 0x8 R_LARCH_ALIGN - 0xC
# RELAX-RELOC-NEXT: 0x14 R_LARCH_ALIGN .Lla-relax-align1 0x404
# RELOC-NEXT: }
# RELOC-NEXT: ]
29 changes: 16 additions & 13 deletions llvm/test/MC/LoongArch/Relocations/sub-expr.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,29 @@
# CHECK-NEXT: Section ({{.*}}) .rela.sx {
# CHECK-NEXT: 0x4 R_LARCH_PCALA_HI20 z 0x0
# CHECK-NEXT: 0x8 R_LARCH_PCALA_LO12 z 0x0
# CHECK-NEXT: 0xC R_LARCH_32_PCREL .sy 0xC
# CHECK-NEXT: 0xC R_LARCH_32_PCREL .sy 0x10
# CHECK-NEXT: }
# CHECK-NEXT: Section ({{.*}}) .rela.data {
# CHECK-NEXT: 0x0 R_LARCH_64_PCREL .sx 0x4
# CHECK-NEXT: 0x8 R_LARCH_64_PCREL .sy 0x4
# CHECK-NEXT: 0x8 R_LARCH_64_PCREL .sy 0x8
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL .sx 0x4
# CHECK-NEXT: 0x14 R_LARCH_32_PCREL .sy 0x4
# CHECK-NEXT: 0x14 R_LARCH_32_PCREL .sy 0x8
# CHECK-NEXT: 0x18 R_LARCH_ADD64 .sx 0x4
# CHECK-NEXT: 0x18 R_LARCH_SUB64 .sy 0x4
# CHECK-NEXT: 0x20 R_LARCH_ADD64 .sy 0x4
# CHECK-NEXT: 0x18 R_LARCH_SUB64 .sy 0x8
# CHECK-NEXT: 0x20 R_LARCH_ADD64 .sy 0x8
# CHECK-NEXT: 0x20 R_LARCH_SUB64 .sx 0x4
# CHECK-NEXT: 0x28 R_LARCH_ADD32 .sx 0x4
# CHECK-NEXT: 0x28 R_LARCH_SUB32 .sy 0x4
# CHECK-NEXT: 0x2C R_LARCH_ADD32 .sy 0x4
# CHECK-NEXT: 0x28 R_LARCH_SUB32 .sy 0x8
# CHECK-NEXT: 0x2C R_LARCH_ADD32 .sy 0x8
# CHECK-NEXT: 0x2C R_LARCH_SUB32 .sx 0x4
# CHECK-NEXT: 0x30 R_LARCH_ADD64 .data 0x30
# CHECK-NEXT: 0x30 R_LARCH_SUB64 .sx 0x4
# CHECK-NEXT: 0x38 R_LARCH_ADD32 .data 0x38
# CHECK-NEXT: 0x38 R_LARCH_SUB32 .sy 0x4
# CHECK-NEXT: 0x38 R_LARCH_SUB32 .sy 0x8
# CHECK-NEXT: }
# CHECK-NEXT: Section ({{.*}}) .rela.sy {
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL .sx 0x10
# CHECK-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL .sx 0xC
# CHECK-NEXT: }
# CHECK-NEXT: ]

Expand Down Expand Up @@ -64,9 +65,11 @@
# RELAX-NEXT: 0x38 R_LARCH_SUB32 y 0x0
# RELAX-NEXT: }
# RELAX-NEXT: Section ({{.*}}) .rela.sy {
# RELAX-NEXT: 0x4 R_LARCH_ALIGN - 0xC
# RELAX-NEXT: 0x10 R_LARCH_ADD32 x 0x0
# RELAX-NEXT: 0x10 R_LARCH_SUB32 y 0x0
# RELAX-NEXT: 0x0 R_LARCH_CALL36 foo 0x0
# RELAX-NEXT: 0x0 R_LARCH_RELAX - 0x0
# RELAX-NEXT: 0x8 R_LARCH_ALIGN - 0xC
# RELAX-NEXT: 0x14 R_LARCH_ADD32 x 0x0
# RELAX-NEXT: 0x14 R_LARCH_SUB32 y 0x0
# RELAX-NEXT: }
# RELAX-NEXT: ]

Expand All @@ -89,7 +92,7 @@ la.pcrel $a0, z
.4byte .-y

.section .sy,"ax"
nop
call36 foo
y:
.p2align 4
.4byte x-y