diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index ca5d27d54bb81..cb0014450702f 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -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) @@ -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; } diff --git a/llvm/test/CodeGen/LoongArch/linker-relaxation.ll b/llvm/test/CodeGen/LoongArch/linker-relaxation.ll index 2827a95547903..3bb83193ce7ac 100644 --- a/llvm/test/CodeGen/LoongArch/linker-relaxation.ll +++ b/llvm/test/CodeGen/LoongArch/linker-relaxation.ll @@ -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 @@ -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 } diff --git a/llvm/test/MC/LoongArch/Misc/cfi-advance.s b/llvm/test/MC/LoongArch/Misc/cfi-advance.s index 38eba7caf6106..494b8af21064b 100644 --- a/llvm/test/MC/LoongArch/Misc/cfi-advance.s +++ b/llvm/test/MC/LoongArch/Misc/cfi-advance.s @@ -5,13 +5,13 @@ # 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 [ @@ -19,6 +19,8 @@ # 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: } @@ -30,7 +32,7 @@ .type test,@function test: .cfi_startproc - nop + call36 foo .cfi_def_cfa_offset 8 .p2align 3 nop diff --git a/llvm/test/MC/LoongArch/Relocations/align-after-relax.s b/llvm/test/MC/LoongArch/Relocations/align-after-relax.s new file mode 100644 index 0000000000000..199c3fcfa0afd --- /dev/null +++ b/llvm/test/MC/LoongArch/Relocations/align-after-relax.s @@ -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 diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s index f2524b29d230b..da3f655e9a31e 100644 --- a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s @@ -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 @@ -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 @@ -73,6 +76,7 @@ # RELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000 .text + call36 foo .L1: nop .L2: diff --git a/llvm/test/MC/LoongArch/Relocations/relax-align-in-subsection.s b/llvm/test/MC/LoongArch/Relocations/relax-align-in-subsection.s new file mode 100644 index 0000000000000..92fceeb14faee --- /dev/null +++ b/llvm/test/MC/LoongArch/Relocations/relax-align-in-subsection.s @@ -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 diff --git a/llvm/test/MC/LoongArch/Relocations/relax-align.s b/llvm/test/MC/LoongArch/Relocations/relax-align.s index 477d5ca24ec7d..e9d7f31b68393 100644 --- a/llvm/test/MC/LoongArch/Relocations/relax-align.s +++ b/llvm/test/MC/LoongArch/Relocations/relax-align.s @@ -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). @@ -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 @@ -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: ] diff --git a/llvm/test/MC/LoongArch/Relocations/sub-expr.s b/llvm/test/MC/LoongArch/Relocations/sub-expr.s index 8bf046acc6975..2d439194eb932 100644 --- a/llvm/test/MC/LoongArch/Relocations/sub-expr.s +++ b/llvm/test/MC/LoongArch/Relocations/sub-expr.s @@ -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: ] @@ -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: ] @@ -89,7 +92,7 @@ la.pcrel $a0, z .4byte .-y .section .sy,"ax" -nop +call36 foo y: .p2align 4 .4byte x-y