[clang] [llvm] [PowerPC] Use the ELFv2 stack and vector alignment on FreeBSD (PR #232336)

Piotr Kubaj via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 15 06:55:34 PDT 2026


https://github.com/pkubaj created https://github.com/llvm/llvm-project/pull/232336

The 64-bit PowerPC data layout only appends
"-S128-v256:256:256-v512:512:512" for AIX and Linux. The explicit vector
alignment was added together with the MMA types in D84968 and the
16-byte natural stack alignment in D96265, and both changes were limited
to the two platforms they were tested on. FreeBSD was left out, so
powerpc64-freebsd and powerpc64le-freebsd still get
"E-m:e-Fn32-i64:64-i128:128-n32:64" and
"e-m:e-Fn32-i64:64-i128:128-n32:64".

FreeBSD uses the ELFv2 ABI on both byte orders, so its stack and vector
alignment rules are the ones of Linux and there is no ABI reason for the
layouts to differ. The incomplete layout has two effects:

- Without "S128" the natural stack alignment is unspecified, so
  alignment promotion of stack variables is not limited to 16 bytes and
  an over-aligned alloca forces dynamic stack realignment. This is what
  D96265 fixed for Linux.
- Consumers that compare a module's layout with the TargetMachine's
  reject modules built with the ELFv2 layout. Halide, for example,
  hard-codes the Linux layout for 64-bit PowerPC and aborts with
  "module's data layout does not match target machine's" when it
  targets powerpc64le-freebsd.

Add FreeBSD to the condition. Clang derives its data layout from
Triple::computeDataLayout(), so the frontend follows without further
changes. Update the two FreeBSD expectations in target-data.c and add a
unit test that pins the FreeBSD layout to the Linux one.

Assisted-by: Claude Fable 5.1


>From 52388c8ddecd3c42875932f7bb47f0d9c16d1803 Mon Sep 17 00:00:00 2001
From: Piotr Kubaj <pkubaj at FreeBSD.org>
Date: Thu, 15 Oct 2026 15:22:30 +0200
Subject: [PATCH] [PowerPC] Use the ELFv2 stack and vector alignment on FreeBSD

The 64-bit PowerPC data layout only appends
"-S128-v256:256:256-v512:512:512" for AIX and Linux. The explicit vector
alignment was added together with the MMA types in D84968 and the
16-byte natural stack alignment in D96265, and both changes were limited
to the two platforms they were tested on. FreeBSD was left out, so
powerpc64-freebsd and powerpc64le-freebsd still get
"E-m:e-Fn32-i64:64-i128:128-n32:64" and
"e-m:e-Fn32-i64:64-i128:128-n32:64".

FreeBSD uses the ELFv2 ABI on both byte orders, so its stack and vector
alignment rules are the ones of Linux and there is no ABI reason for the
layouts to differ. The incomplete layout has two effects:

- Without "S128" the natural stack alignment is unspecified, so
  alignment promotion of stack variables is not limited to 16 bytes and
  an over-aligned alloca forces dynamic stack realignment. This is what
  D96265 fixed for Linux.
- Consumers that compare a module's layout with the TargetMachine's
  reject modules built with the ELFv2 layout. Halide, for example,
  hard-codes the Linux layout for 64-bit PowerPC and aborts with
  "module's data layout does not match target machine's" when it
  targets powerpc64le-freebsd.

Add FreeBSD to the condition. Clang derives its data layout from
Triple::computeDataLayout(), so the frontend follows without further
changes. Update the two FreeBSD expectations in target-data.c and add a
unit test that pins the FreeBSD layout to the Linux one.

Assisted-by: Claude Fable 5.1
---
 clang/test/CodeGen/target-data.c           |  4 ++--
 llvm/lib/TargetParser/TargetDataLayout.cpp |  5 +++--
 llvm/unittests/TargetParser/TripleTest.cpp | 11 +++++++++++
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c
index d738d5faf18617..84c18aa5986679 100644
--- a/clang/test/CodeGen/target-data.c
+++ b/clang/test/CodeGen/target-data.c
@@ -112,11 +112,11 @@
 
 // RUN: %clang_cc1 -triple powerpc64-freebsd -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-FREEBSD
-// PPC64-FREEBSD: target datalayout = "E-m:e-Fn32-i64:64-i128:128-n32:64"
+// PPC64-FREEBSD: target datalayout = "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64le-freebsd -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64LE-FREEBSD
-// PPC64LE-FREEBSD: target datalayout = "e-m:e-Fn32-i64:64-i128:128-n32:64"
+// PPC64LE-FREEBSD: target datalayout = "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64-linux -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-LINUX
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index 83bc4a624bf99b..8659c0bea07a8f 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -276,8 +276,9 @@ static std::string computePowerDataLayout(const Triple &T, StringRef ABIName) {
 
   // Specify the vector alignment explicitly. For v256i1 and v512i1, the
   // calculated alignment would be 256*alignment(i1) and 512*alignment(i1),
-  // which is 256 and 512 bytes - way over aligned.
-  if (is64Bit && (T.isOSAIX() || T.isOSLinux()))
+  // which is 256 and 512 bytes - way over aligned. FreeBSD uses the same ELFv2
+  // ABI as Linux, so it shares the stack and vector alignment.
+  if (is64Bit && (T.isOSAIX() || T.isOSLinux() || T.isOSFreeBSD()))
     Ret += "-S128-v256:256:256-v512:512:512";
 
   return Ret;
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index 17176837300024..b33d5efaf8ede3 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -4054,6 +4054,17 @@ TEST(DataLayoutTest, NVPTX) {
                                    "p6:32:32", "p7:32:32", "p101:32:32"));
 }
 
+TEST(DataLayoutTest, PowerPC64FreeBSD) {
+  // FreeBSD uses the ELFv2 ABI on both big- and little-endian powerpc64 and
+  // shares the 16-byte stack alignment and the vector alignment of Linux.
+  EXPECT_EQ(Triple("powerpc64le-unknown-freebsd").computeDataLayout(),
+            Triple("powerpc64le-unknown-linux-gnu").computeDataLayout());
+  EXPECT_EQ(Triple("powerpc64le-unknown-freebsd").computeDataLayout(),
+            "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512");
+  EXPECT_EQ(Triple("powerpc64-unknown-freebsd").computeDataLayout(),
+            "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512");
+}
+
 TEST(DataLayoutTest, CheriRISCV32) {
   Triple TT = Triple("riscv32-unknown-unknown");
 



More information about the cfe-commits mailing list