[llvm] [BOLT][NFC] Set minimal alignment for BF (PR #67707)

Vladislav Khmelevsky via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 3 03:06:27 PDT 2023


https://github.com/yota9 updated https://github.com/llvm/llvm-project/pull/67707

>From 3ee97eb401a562e403aba78e9da102bcc7773730 Mon Sep 17 00:00:00 2001
From: Vladislav Khmelevsky <och95 at yandex.ru>
Date: Tue, 3 Oct 2023 14:02:40 +0400
Subject: [PATCH] [BOLT] Return proper minimal alignment from BF

Currently minimal alignment of function is hardcoded to 2 bytes.
Add 2 more cases:
1. In case BF is data in code return the alignment of CI as minimal
alignment
2. For aarch64 and riscv platforms return the minimal value of 4 (added
test for aarch64)
Otherwise fallback to returning the 2 as it previously was.
---
 bolt/include/bolt/Core/BinaryFunction.h | 21 ++++++++++++---
 bolt/lib/Core/BinaryEmitter.cpp         |  2 +-
 bolt/lib/Core/BinaryFunction.cpp        |  2 --
 bolt/lib/Passes/Aligner.cpp             | 16 -----------
 bolt/lib/Passes/LongJmp.cpp             |  4 +--
 bolt/test/AArch64/bf_min_alignment.s    | 35 +++++++++++++++++++++++++
 6 files changed, 55 insertions(+), 25 deletions(-)
 create mode 100644 bolt/test/AArch64/bf_min_alignment.s

diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index dea1d55b15026e4..a4c9eb4265ec9aa 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -192,9 +192,6 @@ class BinaryFunction {
   static constexpr uint64_t COUNT_NO_PROFILE =
       BinaryBasicBlock::COUNT_NO_PROFILE;
 
-  /// We have to use at least 2-byte alignment for functions because of C++ ABI.
-  static constexpr unsigned MinAlign = 2;
-
   static const char TimerGroupName[];
   static const char TimerGroupDesc[];
 
@@ -1720,8 +1717,24 @@ class BinaryFunction {
     return *this;
   }
 
-  Align getAlign() const { return Align(Alignment); }
+  uint16_t getMinAlignment() const {
+    // Align data in code BFs minimum to CI alignment
+    if (!size() && hasIslandsInfo())
+      return getConstantIslandAlignment();
+
+    // Minimal code alignment on AArch64 and RISCV is 4
+    if (BC.isAArch64() || BC.isRISCV())
+      return 4;
+
+    // We have to use at least 2-byte alignment for functions because
+    // of C++ ABI.
+    return 2;
+  }
+
+  Align getMinAlign() const { return Align(getMinAlignment()); }
+
   uint16_t getAlignment() const { return Alignment; }
+  Align getAlign() const { return Align(getAlignment()); }
 
   BinaryFunction &setMaxAlignmentBytes(uint16_t MaxAlignBytes) {
     MaxAlignmentBytes = MaxAlignBytes;
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 95ab63521c06a56..6c17f69d7aeceb5 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -309,7 +309,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
     // tentative layout.
     Section->ensureMinAlignment(Align(opts::AlignFunctions));
 
-    Streamer.emitCodeAlignment(Align(BinaryFunction::MinAlign), &*BC.STI);
+    Streamer.emitCodeAlignment(Function.getMinAlign(), &*BC.STI);
     uint16_t MaxAlignBytes = FF.isSplitFragment()
                                  ? Function.getMaxColdAlignmentBytes()
                                  : Function.getMaxAlignmentBytes();
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 6cf1cfb50a9c12c..02a896558e17ced 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -164,8 +164,6 @@ bool shouldPrint(const BinaryFunction &Function) {
 namespace llvm {
 namespace bolt {
 
-constexpr unsigned BinaryFunction::MinAlign;
-
 template <typename R> static bool emptyRange(const R &Range) {
   return Range.begin() == Range.end();
 }
diff --git a/bolt/lib/Passes/Aligner.cpp b/bolt/lib/Passes/Aligner.cpp
index c5b63d881e17991..7c387525434bd39 100644
--- a/bolt/lib/Passes/Aligner.cpp
+++ b/bolt/lib/Passes/Aligner.cpp
@@ -158,22 +158,6 @@ void AlignerPass::runOnFunctions(BinaryContext &BC) {
     BinaryContext::IndependentCodeEmitter Emitter =
         BC.createIndependentMCCodeEmitter();
 
-    // Align objects that contains constant islands and no code
-    // to at least 8 bytes.
-    if (!BF.size() && BF.hasIslandsInfo()) {
-      uint16_t Alignment = BF.getConstantIslandAlignment();
-      // Check if we're forcing output alignment and it is greater than minimal
-      // CI required one
-      if (!opts::UseCompactAligner && Alignment < opts::AlignFunctions &&
-          opts::AlignFunctions <= opts::AlignFunctionsMaxBytes)
-        Alignment = opts::AlignFunctions;
-
-      BF.setAlignment(Alignment);
-      BF.setMaxAlignmentBytes(Alignment);
-      BF.setMaxColdAlignmentBytes(Alignment);
-      return;
-    }
-
     if (opts::UseCompactAligner)
       alignCompact(BF, Emitter.MCE.get());
     else
diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp
index 31bb8000dda00c3..ccfc950704b89ee 100644
--- a/bolt/lib/Passes/LongJmp.cpp
+++ b/bolt/lib/Passes/LongJmp.cpp
@@ -290,7 +290,7 @@ uint64_t LongJmpPass::tentativeLayoutRelocColdPart(
   for (BinaryFunction *Func : SortedFunctions) {
     if (!Func->isSplit())
       continue;
-    DotAddress = alignTo(DotAddress, BinaryFunction::MinAlign);
+    DotAddress = alignTo(DotAddress, Func->getMinAlignment());
     uint64_t Pad =
         offsetToAlignment(DotAddress, llvm::Align(Func->getAlignment()));
     if (Pad <= Func->getMaxColdAlignmentBytes())
@@ -349,7 +349,7 @@ uint64_t LongJmpPass::tentativeLayoutRelocMode(
         DotAddress = alignTo(DotAddress, opts::AlignText);
     }
 
-    DotAddress = alignTo(DotAddress, BinaryFunction::MinAlign);
+    DotAddress = alignTo(DotAddress, Func->getMinAlignment());
     uint64_t Pad =
         offsetToAlignment(DotAddress, llvm::Align(Func->getAlignment()));
     if (Pad <= Func->getMaxAlignmentBytes())
diff --git a/bolt/test/AArch64/bf_min_alignment.s b/bolt/test/AArch64/bf_min_alignment.s
new file mode 100644
index 000000000000000..2dd06b373a79801
--- /dev/null
+++ b/bolt/test/AArch64/bf_min_alignment.s
@@ -0,0 +1,35 @@
+// This tests checks the minimum alignment of the AARch64 function
+// is equal to 4. Otherwise the jitlinker would fail to link the
+// binary since the size of the first function after reorder is not
+// not a multiple of 4.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -nostdlib -Wl,-q
+# RUN: link_fdata %s %t.o %t.fdata
+# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 \
+# RUN:   --align-functions-max-bytes=1 \
+# RUN:   --data %t.fdata --reorder-functions=exec-count
+# RUN: llvm-nm -n %t.bolt | FileCheck %s
+
+# CHECK: {{0|4|8|c}} T dummy
+# CHECK-NEXT: {{0|4|8|c}} T _start
+
+  .text
+  .align 4
+  .global _start
+  .type _start, %function
+_start:
+# FDATA: 0 [unknown] 0 1 _start 0 0 1
+   bl dymmy
+   ret
+  .size _start, .-_start
+
+  .global dummy
+  .type dummy, %function
+dummy:
+# FDATA: 0 [unknown] 0 1 dummy 0 0 42
+  adr x0, .Lci
+  ret
+.Lci:
+  .byte 0
+  .size dummy, .-dummy



More information about the llvm-commits mailing list