[llvm] [LoongArch] Insert nops and emit align reloc when handle alignment directive (PR #72962)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 23:05:37 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
@llvm/pr-subscribers-mc
Author: Jinyang He (MQ-mengqing)
<details>
<summary>Changes</summary>
Refer to RISCV, we will fix up the alignment if linker relaxation changes code size and breaks alignment. Insert enough Nops and emit R_LARCH_ALIGN relocation type so that linker could satisfy the alignment by removing Nops. It does so only in sections with the SHF_EXECINSTR flag.
---
Full diff: https://github.com/llvm/llvm-project/pull/72962.diff
4 Files Affected:
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp (+48)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h (+9)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h (+3-1)
- (added) llvm/test/MC/LoongArch/Relocations/relax-align.s (+28)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index a35916d2ad2197d..6625ad6bc94d188 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -160,6 +160,54 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
}
}
+// Linker relaxation may change code size. We have to insert Nops
+// for .align directive when linker relaxation enabled. So then Linker
+// could satisfy alignment by removing Nops.
+// The function returns the total Nops Size we need to insert.
+bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign(
+ const MCAlignFragment &AF, unsigned &Size) {
+ // Calculate Nops Size only when linker relaxation enabled.
+ const MCSubtargetInfo *STI = AF.getSubtargetInfo();
+ if (!STI->hasFeature(LoongArch::FeatureRelax))
+ return false;
+
+ const unsigned MinNopLen = 4;
+ Size = AF.getAlignment().value() - MinNopLen;
+ return AF.getAlignment() > MinNopLen;
+}
+
+// We need to insert R_LARCH_ALIGN relocation type to indicate the
+// position of Nops and the total bytes of the Nops have been inserted
+// when linker relaxation enabled.
+// The function inserts fixup_loongarch_align fixup which eventually will
+// transfer to R_LARCH_ALIGN relocation type.
+bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign(
+ MCAssembler &Asm, const MCAsmLayout &Layout, MCAlignFragment &AF) {
+ // Insert the fixup only when linker relaxation enabled.
+ const MCSubtargetInfo *STI = AF.getSubtargetInfo();
+ if (!STI->hasFeature(LoongArch::FeatureRelax))
+ return false;
+
+ // Calculate total Nops we need to insert. If there are none to insert
+ // then simply return.
+ unsigned Count;
+ if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count))
+ return false;
+
+ const MCExpr *Dummy = MCConstantExpr::create(0, Asm.getContext());
+ // Create fixup_loongarch_align fixup.
+ MCFixup Fixup = MCFixup::create(
+ 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_align), SMLoc());
+
+ uint64_t FixedValue = 0;
+ MCValue NopBytes = MCValue::get(Count);
+
+ Asm.getWriter().recordRelocation(Asm, Layout, &AF, Fixup, NopBytes,
+ FixedValue);
+
+ return true;
+}
+
bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
const MCFixup &Fixup,
const MCValue &Target) {
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
index f840f9fa2b6a007..1f4743f34dad2a7 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
@@ -40,6 +40,15 @@ class LoongArchAsmBackend : public MCAsmBackend {
uint64_t Value, bool IsResolved,
const MCSubtargetInfo *STI) const override;
+ // Return Size with extra Nop Bytes for alignment directive in code section.
+ bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
+ unsigned &Size) override;
+
+ // Insert target specific fixup type for alignment directive in code section.
+ bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ MCAlignFragment &AF) override;
+
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target) override;
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
index ba2d6718cdf9a27..8d773b649107ed6 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
@@ -106,7 +106,9 @@ enum Fixups {
// 20-bit fixup corresponding to %gd_pc_hi20(foo) for instruction pcalau12i.
fixup_loongarch_tls_gd_pc_hi20,
// 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w.
- fixup_loongarch_tls_gd_hi20
+ fixup_loongarch_tls_gd_hi20,
+ // Generate an R_LARCH_ALIGN which indicates the linker may fixup align here.
+ fixup_loongarch_align = FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN
};
} // end namespace LoongArch
} // end namespace llvm
diff --git a/llvm/test/MC/LoongArch/Relocations/relax-align.s b/llvm/test/MC/LoongArch/Relocations/relax-align.s
new file mode 100644
index 000000000000000..36524182777cb02
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Relocations/relax-align.s
@@ -0,0 +1,28 @@
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=CHECKR
+
+# CHECKR: Relocations [
+# CHECKR-NEXT: Section ({{.*}}) .rela.text {
+# CHECKR-NEXT: 0x0 R_LARCH_ALIGN - 0xC
+# CHECKR-NEXT: 0x10 R_LARCH_ALIGN - 0x1C
+# CHECKR-NEXT: 0x2C R_LARCH_ALIGN - 0xC
+# CHECKR-NEXT: }
+# CHECKR-NEXT: ]
+
+# CHECK: Relocations [
+# CHECK-NEXT: ]
+
+.text
+.p2align 4
+nop
+.p2align 5
+.p2align 4
+nop
+## Not emit R_LARCH_ALIGN if code alignment great than alignment directive.
+.p2align 2
+.p2align 1
+.p2align 0
+## Not emit R_LARCH_ALIGN if alignment directive with specific padding value.
+.p2align 4, 1
``````````
</details>
https://github.com/llvm/llvm-project/pull/72962
More information about the llvm-commits
mailing list