[clang] clang: Emit llvm.loop.align metadata for -falign-loops (PR #223147)

via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 12 06:57:44 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Make -falign-loops=N attach per-loop llvm.loop.align metadata instead
of setting the module-wide TargetOptions::LoopAlignment. This reuses
the existing [[clang::code_align]] metadata path, with the source
attribute taking precedence over the flag.

Co-authored-by: Claude (Opus 4.8) <noreply@<!-- -->anthropic.com>

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


3 Files Affected:

- (modified) clang/lib/CodeGen/BackendUtil.cpp (-1) 
- (modified) clang/lib/CodeGen/CGLoopInfo.cpp (+4) 
- (modified) clang/test/CodeGen/align-loops.c (+31-6) 


``````````diff
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 9d8fd319f6f17..48a6c01e74b3b 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -449,7 +449,6 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
   Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;
   Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;
-  Options.LoopAlignment = CodeGenOpts.LoopAlignment;
   Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf;
   Options.ObjectFilenameForDebug =
       CodeGenOpts.remapDebugPathPrefix(CodeGenOpts.ObjectFilenameForDebug);
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index e4e9c56fbfc77..c13c2f6c60089 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -809,10 +809,14 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
   // Identify loop attribute 'code_align' from Attrs.
   // For attribute code_align:
   // n - 'llvm.loop.align i32 n' metadata will be emitted.
+  // A source-level [[clang::code_align]] attribute takes precedence over the
+  // -falign-loops=N command-line default.
   if (const auto *CodeAlign = getSpecificAttr<CodeAlignAttr>(Attrs)) {
     const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
     llvm::APSInt ArgVal = CE->getResultAsAPSInt();
     setCodeAlign(ArgVal.getSExtValue());
+  } else if (CGOpts.LoopAlignment) {
+    setCodeAlign(CGOpts.LoopAlignment);
   }
 
   setMustProgress(MustProgress);
diff --git a/clang/test/CodeGen/align-loops.c b/clang/test/CodeGen/align-loops.c
index 25f8cded59f32..f4b0dc8c64b78 100644
--- a/clang/test/CodeGen/align-loops.c
+++ b/clang/test/CodeGen/align-loops.c
@@ -1,15 +1,40 @@
 // REQUIRES: x86-registered-target
-/// Check asm because we use llvm::TargetOptions.
 
-// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=8 -O -o - | FileCheck %s --check-prefixes=CHECK,CHECK_8
-// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=32 -O -o - | FileCheck %s --check-prefixes=CHECK,CHECK_32
+/// -falign-loops=N emits per-loop !{!"llvm.loop.align", i32 N} metadata.
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm %s -falign-loops=8 -O -o - | FileCheck %s --check-prefix=MD8
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm %s -falign-loops=32 -O -o - | FileCheck %s --check-prefix=MD32
 
-// CHECK-LABEL: foo:
-// CHECK_8:       .p2align 3
-// CHECK_32:      .p2align 5
+/// End-to-end: the metadata still lowers to .p2align in the backend. The
+/// backend takes max(target preferred, metadata), so use values >= the x86
+/// default (16) to get an unambiguous alignment.
+// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=32 -O -o - | FileCheck %s --check-prefix=ASM32
+// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=64 -O -o - | FileCheck %s --check-prefix=ASM64
+
+// MD8: !{!"llvm.loop.align", i32 8}
+// MD32: !{!"llvm.loop.align", i32 32}
+
+// ASM32-LABEL: foo:
+// ASM32: .p2align 5
+// ASM64-LABEL: foo:
+// ASM64: .p2align 6
 
 void bar(void);
 void foo(void) {
   for (int i = 0; i < 64; ++i)
     bar();
 }
+
+/// A source-level [[clang::code_align]] takes precedence over -falign-loops.
+/// The attribute value 16 (not the flag's 32) proves the attribute wins; 16 has
+/// no other source in this module.
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm %s -falign-loops=32 -O -o - | FileCheck %s --check-prefix=OVERRIDE
+
+// OVERRIDE-LABEL: @baz
+// OVERRIDE: br {{.*}}!llvm.loop
+// OVERRIDE: !{!"llvm.loop.align", i32 16}
+
+void baz(void) {
+  [[clang::code_align(16)]]
+  for (int i = 0; i < 64; ++i)
+    bar();
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/223147


More information about the cfe-commits mailing list