Skip to content

Conversation

pcc
Copy link
Contributor

@pcc pcc commented Aug 27, 2025

The result of the MachineFunction preferred alignment query is emitted
as a .prefalign directive if supported, otherwise it gets combined into
the minimum alignment.

Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019

Created using spr 1.3.6-beta.1
@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2025

@llvm/pr-subscribers-lld
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-backend-powerpc

@llvm/pr-subscribers-backend-x86

Author: Peter Collingbourne (pcc)

Changes

MachineFunction can now be queried for the preferred alignment which
comes from the function attributes (optsize, minsize, prefalign) and
TargetLowering. The result of this query is emitted as a .prefalign
directive if supported, otherwise it gets combined into the minimum
alignment.

Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019


Full diff: https://github.com/llvm/llvm-project/pull/155529.diff

8 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/MachineFunction.h (+2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+14-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/WinException.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/MachineFunction.cpp (+12-5)
  • (modified) llvm/lib/Target/X86/X86AsmPrinter.cpp (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/alloca-crspill.ll (+1-1)
  • (added) llvm/test/CodeGen/X86/prefalign.ll (+27)
  • (modified) llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll (+2-2)
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index ef783f276b7d4..a454ad02df23d 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -818,6 +818,8 @@ class LLVM_ABI MachineFunction {
       Alignment = A;
   }
 
+  Align getPreferredAlignment() const;
+  
   /// exposesReturnsTwice - Returns true if the function calls setjmp or
   /// any other similar functions with attribute "returns twice" without
   /// having the attribute itself.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cd14a4f57f760..25037651b92ea 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -977,8 +977,20 @@ void AsmPrinter::emitFunctionHeader() {
     emitVisibility(CurrentFnSym, F.getVisibility());
 
   emitLinkage(&F, CurrentFnSym);
-  if (MAI->hasFunctionAlignment())
-    emitAlignment(MF->getAlignment(), &F);
+  if (MAI->hasFunctionAlignment()) {
+    // The preferred alignment directive will not have the intended effect
+    // unless function sections are enabled.
+    if (MAI->useIntegratedAssembler() && MAI->hasPreferredAlignment() &&
+        TM.getFunctionSections()) {
+      Align Alignment = MF->getAlignment();
+      Align PrefAlignment = MF->getPreferredAlignment();
+      emitAlignment(Alignment, &F);
+      if (Alignment != PrefAlignment)
+        OutStreamer->emitPrefAlign(PrefAlignment);
+    } else {
+      emitAlignment(MF->getPreferredAlignment(), &F);
+    }
+  }
 
   if (MAI->hasDotTypeDotSizeDirective())
     OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 13fd270ec7410..90d8196ffb82a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -204,8 +204,8 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
 
     // We want our funclet's entry point to be aligned such that no nops will be
     // present after the label.
-    Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
-                       &F);
+    Asm->emitAlignment(
+        std::max(Asm->MF->getPreferredAlignment(), MBB.getAlignment()), &F);
 
     // Now that we've emitted the alignment directive, point at our funclet.
     Asm->OutStreamer->emitLabel(Sym);
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 224231cb90fe2..eabe1a510d92d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -211,11 +211,6 @@ void MachineFunction::init() {
   ConstantPool = new (Allocator) MachineConstantPool(getDataLayout());
   Alignment = STI.getTargetLowering()->getMinFunctionAlignment();
 
-  // FIXME: Shouldn't use pref alignment if explicit alignment is set on F.
-  if (!F.hasOptSize())
-    Alignment = std::max(Alignment,
-                         STI.getTargetLowering()->getPrefFunctionAlignment());
-
   // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls
   // to load a type hash before the function label. Ensure functions are aligned
   // by a least 4 to avoid unaligned access, which is especially important for
@@ -330,6 +325,18 @@ bool MachineFunction::shouldSplitStack() const {
   return getFunction().hasFnAttribute("split-stack");
 }
 
+Align MachineFunction::getPreferredAlignment() const {
+  Align PrefAlignment = Align(1);
+
+  if (!F.hasOptSize())
+    PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment();
+
+  if (MaybeAlign A = F.getPreferredAlignment())
+    PrefAlignment = *A;
+  
+  return std::max(PrefAlignment, getAlignment());
+}
+
 [[nodiscard]] unsigned
 MachineFunction::addFrameInst(const MCCFIInstruction &Inst) {
   FrameInstructions.push_back(Inst);
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index d406277e440bb..0912afa098b75 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -155,7 +155,7 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,
   if (HasType)
     PrefixBytes += 5;
 
-  emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment()));
+  emitNops(offsetToAlignment(PrefixBytes, MF.getPreferredAlignment()));
 }
 
 /// emitKCFITypeId - Emit the KCFI type information in architecture specific
diff --git a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
index cbcfd9a6a0dab..bd88b5d89202d 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
@@ -26,7 +26,7 @@ entry:
 declare signext i32 @do_something(ptr)
 
 ; CHECK: name:            test
-; CHECK: alignment:       16
+; CHECK: alignment:       4
 ; CHECK: liveins:
 ; CHECK64:   - { reg: '$x3', virtual-reg: '' }
 ; CHECK32:   - { reg: '$r3', virtual-reg: '' }
diff --git a/llvm/test/CodeGen/X86/prefalign.ll b/llvm/test/CodeGen/X86/prefalign.ll
new file mode 100644
index 0000000000000..9a775bc328c60
--- /dev/null
+++ b/llvm/test/CodeGen/X86/prefalign.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s | FileCheck --check-prefixes=CHECK,NOFS %s
+; RUN: llc -function-sections < %s | FileCheck --check-prefixes=CHECK,FS %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: .globl f1
+; NOFS-NEXT: .p2align 4
+; FS-NEXT: .prefalign 16
+define void @f1() {
+  ret void
+}
+
+; CHECK: .globl f2
+; CHECK-NOT: .prefalign
+; CHECK-NOT: .p2align
+define void @f2() prefalign 1 {
+  ret void
+}
+
+; CHECK: .globl f3
+; NOFS-NEXT: .p2align 2
+; FS-NEXT: .p2align 1
+; FS-NEXT: .prefalign 4
+define void @f3() align 2 prefalign 4 {
+  ret void
+}
diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
index 62d3d8255a175..4143b0ef580ba 100644
--- a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
+++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
@@ -107,7 +107,7 @@ entry:
 ; CHECK-SEC:       [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC:       [ 3] .text.foo          PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC:       [ 5] .text.foo2         PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC-COUNT-3:    .pseudo_probe_desc PROGBITS
 ; CHECK-SEC:            .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC-NEXT:       .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1
@@ -135,7 +135,7 @@ entry:
 ; CHECK-SEC2:      [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC2:      [ 3] .text              PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC2:      [ 5] .text              PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC2-COUNT-3:   .pseudo_probe_desc PROGBITS
 ; CHECK-SEC2:           .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC2-NEXT:      .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1

@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Peter Collingbourne (pcc)

Changes

MachineFunction can now be queried for the preferred alignment which
comes from the function attributes (optsize, minsize, prefalign) and
TargetLowering. The result of this query is emitted as a .prefalign
directive if supported, otherwise it gets combined into the minimum
alignment.

Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019


Full diff: https://github.com/llvm/llvm-project/pull/155529.diff

8 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/MachineFunction.h (+2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+14-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/WinException.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/MachineFunction.cpp (+12-5)
  • (modified) llvm/lib/Target/X86/X86AsmPrinter.cpp (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/alloca-crspill.ll (+1-1)
  • (added) llvm/test/CodeGen/X86/prefalign.ll (+27)
  • (modified) llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll (+2-2)
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index ef783f276b7d4..a454ad02df23d 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -818,6 +818,8 @@ class LLVM_ABI MachineFunction {
       Alignment = A;
   }
 
+  Align getPreferredAlignment() const;
+  
   /// exposesReturnsTwice - Returns true if the function calls setjmp or
   /// any other similar functions with attribute "returns twice" without
   /// having the attribute itself.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cd14a4f57f760..25037651b92ea 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -977,8 +977,20 @@ void AsmPrinter::emitFunctionHeader() {
     emitVisibility(CurrentFnSym, F.getVisibility());
 
   emitLinkage(&F, CurrentFnSym);
-  if (MAI->hasFunctionAlignment())
-    emitAlignment(MF->getAlignment(), &F);
+  if (MAI->hasFunctionAlignment()) {
+    // The preferred alignment directive will not have the intended effect
+    // unless function sections are enabled.
+    if (MAI->useIntegratedAssembler() && MAI->hasPreferredAlignment() &&
+        TM.getFunctionSections()) {
+      Align Alignment = MF->getAlignment();
+      Align PrefAlignment = MF->getPreferredAlignment();
+      emitAlignment(Alignment, &F);
+      if (Alignment != PrefAlignment)
+        OutStreamer->emitPrefAlign(PrefAlignment);
+    } else {
+      emitAlignment(MF->getPreferredAlignment(), &F);
+    }
+  }
 
   if (MAI->hasDotTypeDotSizeDirective())
     OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 13fd270ec7410..90d8196ffb82a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -204,8 +204,8 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
 
     // We want our funclet's entry point to be aligned such that no nops will be
     // present after the label.
-    Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
-                       &F);
+    Asm->emitAlignment(
+        std::max(Asm->MF->getPreferredAlignment(), MBB.getAlignment()), &F);
 
     // Now that we've emitted the alignment directive, point at our funclet.
     Asm->OutStreamer->emitLabel(Sym);
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 224231cb90fe2..eabe1a510d92d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -211,11 +211,6 @@ void MachineFunction::init() {
   ConstantPool = new (Allocator) MachineConstantPool(getDataLayout());
   Alignment = STI.getTargetLowering()->getMinFunctionAlignment();
 
-  // FIXME: Shouldn't use pref alignment if explicit alignment is set on F.
-  if (!F.hasOptSize())
-    Alignment = std::max(Alignment,
-                         STI.getTargetLowering()->getPrefFunctionAlignment());
-
   // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls
   // to load a type hash before the function label. Ensure functions are aligned
   // by a least 4 to avoid unaligned access, which is especially important for
@@ -330,6 +325,18 @@ bool MachineFunction::shouldSplitStack() const {
   return getFunction().hasFnAttribute("split-stack");
 }
 
+Align MachineFunction::getPreferredAlignment() const {
+  Align PrefAlignment = Align(1);
+
+  if (!F.hasOptSize())
+    PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment();
+
+  if (MaybeAlign A = F.getPreferredAlignment())
+    PrefAlignment = *A;
+  
+  return std::max(PrefAlignment, getAlignment());
+}
+
 [[nodiscard]] unsigned
 MachineFunction::addFrameInst(const MCCFIInstruction &Inst) {
   FrameInstructions.push_back(Inst);
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index d406277e440bb..0912afa098b75 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -155,7 +155,7 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,
   if (HasType)
     PrefixBytes += 5;
 
-  emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment()));
+  emitNops(offsetToAlignment(PrefixBytes, MF.getPreferredAlignment()));
 }
 
 /// emitKCFITypeId - Emit the KCFI type information in architecture specific
diff --git a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
index cbcfd9a6a0dab..bd88b5d89202d 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
@@ -26,7 +26,7 @@ entry:
 declare signext i32 @do_something(ptr)
 
 ; CHECK: name:            test
-; CHECK: alignment:       16
+; CHECK: alignment:       4
 ; CHECK: liveins:
 ; CHECK64:   - { reg: '$x3', virtual-reg: '' }
 ; CHECK32:   - { reg: '$r3', virtual-reg: '' }
diff --git a/llvm/test/CodeGen/X86/prefalign.ll b/llvm/test/CodeGen/X86/prefalign.ll
new file mode 100644
index 0000000000000..9a775bc328c60
--- /dev/null
+++ b/llvm/test/CodeGen/X86/prefalign.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s | FileCheck --check-prefixes=CHECK,NOFS %s
+; RUN: llc -function-sections < %s | FileCheck --check-prefixes=CHECK,FS %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: .globl f1
+; NOFS-NEXT: .p2align 4
+; FS-NEXT: .prefalign 16
+define void @f1() {
+  ret void
+}
+
+; CHECK: .globl f2
+; CHECK-NOT: .prefalign
+; CHECK-NOT: .p2align
+define void @f2() prefalign 1 {
+  ret void
+}
+
+; CHECK: .globl f3
+; NOFS-NEXT: .p2align 2
+; FS-NEXT: .p2align 1
+; FS-NEXT: .prefalign 4
+define void @f3() align 2 prefalign 4 {
+  ret void
+}
diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
index 62d3d8255a175..4143b0ef580ba 100644
--- a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
+++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
@@ -107,7 +107,7 @@ entry:
 ; CHECK-SEC:       [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC:       [ 3] .text.foo          PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC:       [ 5] .text.foo2         PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC-COUNT-3:    .pseudo_probe_desc PROGBITS
 ; CHECK-SEC:            .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC-NEXT:       .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1
@@ -135,7 +135,7 @@ entry:
 ; CHECK-SEC2:      [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC2:      [ 3] .text              PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC2:      [ 5] .text              PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC2-COUNT-3:   .pseudo_probe_desc PROGBITS
 ; CHECK-SEC2:           .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC2-NEXT:      .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1

@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2025

@llvm/pr-subscribers-pgo

Author: Peter Collingbourne (pcc)

Changes

MachineFunction can now be queried for the preferred alignment which
comes from the function attributes (optsize, minsize, prefalign) and
TargetLowering. The result of this query is emitted as a .prefalign
directive if supported, otherwise it gets combined into the minimum
alignment.

Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019


Full diff: https://github.com/llvm/llvm-project/pull/155529.diff

8 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/MachineFunction.h (+2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+14-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/WinException.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/MachineFunction.cpp (+12-5)
  • (modified) llvm/lib/Target/X86/X86AsmPrinter.cpp (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/alloca-crspill.ll (+1-1)
  • (added) llvm/test/CodeGen/X86/prefalign.ll (+27)
  • (modified) llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll (+2-2)
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index ef783f276b7d4..a454ad02df23d 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -818,6 +818,8 @@ class LLVM_ABI MachineFunction {
       Alignment = A;
   }
 
+  Align getPreferredAlignment() const;
+  
   /// exposesReturnsTwice - Returns true if the function calls setjmp or
   /// any other similar functions with attribute "returns twice" without
   /// having the attribute itself.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cd14a4f57f760..25037651b92ea 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -977,8 +977,20 @@ void AsmPrinter::emitFunctionHeader() {
     emitVisibility(CurrentFnSym, F.getVisibility());
 
   emitLinkage(&F, CurrentFnSym);
-  if (MAI->hasFunctionAlignment())
-    emitAlignment(MF->getAlignment(), &F);
+  if (MAI->hasFunctionAlignment()) {
+    // The preferred alignment directive will not have the intended effect
+    // unless function sections are enabled.
+    if (MAI->useIntegratedAssembler() && MAI->hasPreferredAlignment() &&
+        TM.getFunctionSections()) {
+      Align Alignment = MF->getAlignment();
+      Align PrefAlignment = MF->getPreferredAlignment();
+      emitAlignment(Alignment, &F);
+      if (Alignment != PrefAlignment)
+        OutStreamer->emitPrefAlign(PrefAlignment);
+    } else {
+      emitAlignment(MF->getPreferredAlignment(), &F);
+    }
+  }
 
   if (MAI->hasDotTypeDotSizeDirective())
     OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 13fd270ec7410..90d8196ffb82a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -204,8 +204,8 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
 
     // We want our funclet's entry point to be aligned such that no nops will be
     // present after the label.
-    Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
-                       &F);
+    Asm->emitAlignment(
+        std::max(Asm->MF->getPreferredAlignment(), MBB.getAlignment()), &F);
 
     // Now that we've emitted the alignment directive, point at our funclet.
     Asm->OutStreamer->emitLabel(Sym);
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 224231cb90fe2..eabe1a510d92d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -211,11 +211,6 @@ void MachineFunction::init() {
   ConstantPool = new (Allocator) MachineConstantPool(getDataLayout());
   Alignment = STI.getTargetLowering()->getMinFunctionAlignment();
 
-  // FIXME: Shouldn't use pref alignment if explicit alignment is set on F.
-  if (!F.hasOptSize())
-    Alignment = std::max(Alignment,
-                         STI.getTargetLowering()->getPrefFunctionAlignment());
-
   // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls
   // to load a type hash before the function label. Ensure functions are aligned
   // by a least 4 to avoid unaligned access, which is especially important for
@@ -330,6 +325,18 @@ bool MachineFunction::shouldSplitStack() const {
   return getFunction().hasFnAttribute("split-stack");
 }
 
+Align MachineFunction::getPreferredAlignment() const {
+  Align PrefAlignment = Align(1);
+
+  if (!F.hasOptSize())
+    PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment();
+
+  if (MaybeAlign A = F.getPreferredAlignment())
+    PrefAlignment = *A;
+  
+  return std::max(PrefAlignment, getAlignment());
+}
+
 [[nodiscard]] unsigned
 MachineFunction::addFrameInst(const MCCFIInstruction &Inst) {
   FrameInstructions.push_back(Inst);
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index d406277e440bb..0912afa098b75 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -155,7 +155,7 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,
   if (HasType)
     PrefixBytes += 5;
 
-  emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment()));
+  emitNops(offsetToAlignment(PrefixBytes, MF.getPreferredAlignment()));
 }
 
 /// emitKCFITypeId - Emit the KCFI type information in architecture specific
diff --git a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
index cbcfd9a6a0dab..bd88b5d89202d 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
@@ -26,7 +26,7 @@ entry:
 declare signext i32 @do_something(ptr)
 
 ; CHECK: name:            test
-; CHECK: alignment:       16
+; CHECK: alignment:       4
 ; CHECK: liveins:
 ; CHECK64:   - { reg: '$x3', virtual-reg: '' }
 ; CHECK32:   - { reg: '$r3', virtual-reg: '' }
diff --git a/llvm/test/CodeGen/X86/prefalign.ll b/llvm/test/CodeGen/X86/prefalign.ll
new file mode 100644
index 0000000000000..9a775bc328c60
--- /dev/null
+++ b/llvm/test/CodeGen/X86/prefalign.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s | FileCheck --check-prefixes=CHECK,NOFS %s
+; RUN: llc -function-sections < %s | FileCheck --check-prefixes=CHECK,FS %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: .globl f1
+; NOFS-NEXT: .p2align 4
+; FS-NEXT: .prefalign 16
+define void @f1() {
+  ret void
+}
+
+; CHECK: .globl f2
+; CHECK-NOT: .prefalign
+; CHECK-NOT: .p2align
+define void @f2() prefalign 1 {
+  ret void
+}
+
+; CHECK: .globl f3
+; NOFS-NEXT: .p2align 2
+; FS-NEXT: .p2align 1
+; FS-NEXT: .prefalign 4
+define void @f3() align 2 prefalign 4 {
+  ret void
+}
diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
index 62d3d8255a175..4143b0ef580ba 100644
--- a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
+++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll
@@ -107,7 +107,7 @@ entry:
 ; CHECK-SEC:       [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC:       [ 3] .text.foo          PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC:       [ 5] .text.foo2         PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC:       [ 8] .text.foo3         PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC-COUNT-3:    .pseudo_probe_desc PROGBITS
 ; CHECK-SEC:            .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC-NEXT:       .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1
@@ -135,7 +135,7 @@ entry:
 ; CHECK-SEC2:      [Nr] Name               Type     {{.*}} ES Flg Lk Inf Al
 ; CHECK-SEC2:      [ 3] .text              PROGBITS {{.*}} 00  AX  0   0 16
 ; CHECK-SEC2:      [ 5] .text              PROGBITS {{.*}} 00  AX  0   0 16
-; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0 16
+; CHECK-SEC2:      [ 8] .text              PROGBITS {{.*}} 00  AXG 0   0  1
 ; CHECK-SEC2-COUNT-3:   .pseudo_probe_desc PROGBITS
 ; CHECK-SEC2:           .pseudo_probe      PROGBITS {{.*}} 00   L  3   0  1
 ; CHECK-SEC2-NEXT:      .pseudo_probe      PROGBITS {{.*}} 00   L  5   0  1

Copy link

github-actions bot commented Aug 27, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@pcc pcc requested review from nikic, MaskRay and efriedma-quic August 27, 2025 00:17
Created using spr 1.3.6-beta.1
}

Align MachineFunction::getPreferredAlignment() const {
Align PrefAlignment = Align(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of reassigning to the variable multiple times, it's better to reverse the order the following two conditions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Created using spr 1.3.6-beta.1
@pcc
Copy link
Contributor Author

pcc commented Sep 12, 2025

Ping

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you split "implement basic codegen support for prefalign" (the bits which don't depend on the .prefalign directive) into a separate patch? It's not clear what's causing the test changes here.

Created using spr 1.3.6-beta.1
@pcc
Copy link
Contributor Author

pcc commented Sep 12, 2025

Can you split "implement basic codegen support for prefalign" (the bits which don't depend on the .prefalign directive) into a separate patch? It's not clear what's causing the test changes here.

Done: #158368

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants