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

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


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

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 at anthropic.com>

>From 03581461ebd36c4c3c7804adb362dd030fbb64f0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 12 Sep 2026 14:32:11 +0200
Subject: [PATCH] clang: Emit llvm.loop.align metadata for -falign-loops

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 at anthropic.com>
---
 clang/lib/CodeGen/BackendUtil.cpp |  1 -
 clang/lib/CodeGen/CGLoopInfo.cpp  |  4 ++++
 clang/test/CodeGen/align-loops.c  | 37 ++++++++++++++++++++++++++-----
 3 files changed, 35 insertions(+), 7 deletions(-)

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();
+}



More information about the cfe-commits mailing list