[clang] [clang][X86] bring `regparm` in line with GCC (PR #227130)
Folkert de Vries via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 3 04:57:52 PDT 2026
https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/227130
>From 236a98c7a712d2a2ccf066791df177bff2f73e43 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Mon, 28 Sep 2026 23:19:06 +0200
Subject: [PATCH 1/4] [clang][X86] Don't pass non-float/double floating-point
types in regparm registers
---
clang/lib/CodeGen/Targets/X86.cpp | 6 ++----
clang/test/CodeGen/regparm-struct.c | 26 +++++++++++++++++++++++++-
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 21f9929cfa8828..56cf23b1e9246f 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -639,11 +639,9 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
if (!T)
T = Ty.getTypePtr();
- if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
- BuiltinType::Kind K = BT->getKind();
- if (K == BuiltinType::Float || K == BuiltinType::Double)
+ if (const BuiltinType *BT = T->getAs<BuiltinType>())
+ if (BT->isFloatingPoint())
return Float;
- }
return Integer;
}
diff --git a/clang/test/CodeGen/regparm-struct.c b/clang/test/CodeGen/regparm-struct.c
index a533f6cedbba24..54c0ded11e2732 100644
--- a/clang/test/CodeGen/regparm-struct.c
+++ b/clang/test/CodeGen/regparm-struct.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +sse2 %s -emit-llvm -o - | FileCheck %s
__attribute__((regparm(3))) void f1(int a, int b, int c, int d);
// CHECK: declare void @f1(i32 inreg noundef, i32 inreg noundef, i32 inreg noundef, i32 noundef)
@@ -175,3 +175,27 @@ void g18(void) {
struct s13 x = {{41}};
f18(x, 42, 43, 44);
}
+
+__attribute__((regparm(3))) void pass_f16(_Float16 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_f16(half noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+__attribute__((regparm(3))) void pass_bf16(__bf16 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_bf16(bfloat noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+__attribute__((regparm(3))) void pass_f80(long double a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_f80(x86_fp80 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+__attribute__((regparm(3))) void pass_f128(__float128 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_f128(fp128 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+struct s14 {
+ _Float16 x1;
+};
+__attribute__((regparm(3))) void pass_wrapped_f16(struct s14 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_wrapped_f16(ptr noundef byval(%struct.s14) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+struct s15 {
+ __float128 x1;
+};
+__attribute__((regparm(3))) void pass_wrapped_f128(struct s15 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_wrapped_f128(ptr noundef byval(%struct.s15) align 4 {{%[^,]*}}, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
>From f8de6469c414c4f3781b30f9b242705a21b084ac Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Mon, 28 Sep 2026 23:19:13 +0200
Subject: [PATCH 2/4] [clang][X86] Don't pass _Complex values in regparm
registers
---
clang/lib/CodeGen/Targets/X86.cpp | 93 +++++++++++++++++++++++++----
clang/test/CodeGen/regparm-struct.c | 24 ++++++++
2 files changed, 104 insertions(+), 13 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 56cf23b1e9246f..57229e33d25f99 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -101,10 +101,7 @@ struct CCState {
/// X86_32ABIInfo - The X86-32 ABI information.
class X86_32ABIInfo : public ABIInfo {
- enum Class {
- Integer,
- Float
- };
+ enum Class { Integer, Float, AlwaysStack };
static const unsigned MinABIStackAlignInBytes = 4;
@@ -634,23 +631,93 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal,
Realign);
}
+/// Like isSingleElementStruct, but only looks through one level of records.
+/// This mirrors how GCC gives a record the mode of its only field.
+static const Type *getSingleFieldType(QualType T, ASTContext &Context) {
+ const auto *RD = T->getAsRecordDecl();
+ if (!RD)
+ return nullptr;
+
+ if (RD->hasFlexibleArrayMember())
+ return nullptr;
+
+ const Type *Found = nullptr;
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (const auto &I : CXXRD->bases()) {
+ // Ignore empty records.
+ if (isEmptyRecord(Context, I.getType(), true))
+ continue;
+
+ // If we already found an element then this isn't a single-element struct.
+ if (Found)
+ return nullptr;
+
+ Found = I.getType().getTypePtr();
+ }
+ }
+
+ // Check for single element.
+ for (const auto *FD : RD->fields()) {
+ QualType FT = FD->getType();
+
+ // Ignore empty fields.
+ if (isEmptyField(Context, FD, true))
+ continue;
+
+ // If we already found an element then this isn't a single-element
+ // struct.
+ if (Found)
+ return nullptr;
+
+ // Treat single element arrays as the element.
+ while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
+ if (AT->getZExtSize() != 1)
+ break;
+ FT = AT->getElementType();
+ }
+
+ Found = FT.getTypePtr();
+ }
+
+ // We don't consider a struct a single-element struct if it has
+ // padding beyond the element type.
+ if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))
+ return nullptr;
+
+ return Found;
+}
+
X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
- const Type *T = isSingleElementStruct(Ty, getContext());
- if (!T)
- T = Ty.getTypePtr();
+ while (Ty->getAsRecordDecl()) {
+ const Type *FT = getSingleFieldType(Ty, getContext());
- if (const BuiltinType *BT = T->getAs<BuiltinType>())
+ // Pick integer for zero-sized types. They will be ignored down the line.
+ if (!FT)
+ return Integer;
+
+ Ty = QualType(FT, 0);
+ }
+
+ // All complex values are passed via the stack.
+ if (Ty->isAnyComplexType())
+ return AlwaysStack;
+
+ // Types like bfloat16 or __float128 are all passed like floats.
+ if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
if (BT->isFloatingPoint())
return Float;
+
return Integer;
}
bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State) const {
- if (!IsSoftFloatABI) {
- Class C = classify(Ty);
- if (C == Float)
- return false;
- }
+ Class C = classify(Ty);
+ if (C == AlwaysStack && !IsMCUABI)
+ return false;
+ if (C == Float && !IsSoftFloatABI)
+ return false;
unsigned Size = getContext().getTypeSize(Ty);
unsigned SizeInRegs = (Size + 31) / 32;
diff --git a/clang/test/CodeGen/regparm-struct.c b/clang/test/CodeGen/regparm-struct.c
index 54c0ded11e2732..6346cec9653fe5 100644
--- a/clang/test/CodeGen/regparm-struct.c
+++ b/clang/test/CodeGen/regparm-struct.c
@@ -199,3 +199,27 @@ struct s15 {
};
__attribute__((regparm(3))) void pass_wrapped_f128(struct s15 a, int b, int c, int d) {}
// CHECK-LABEL: define{{.*}} void @pass_wrapped_f128(ptr noundef byval(%struct.s15) align 4 {{%[^,]*}}, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+__attribute__((regparm(3))) void pass_complex_float(_Complex float a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr noundef byval({ float, float }) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+__attribute__((regparm(3))) void pass_complex_int(int a, _Complex int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_complex_int(i32 inreg noundef %a, ptr noundef byval({ i32, i32 }) align 4 %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+struct s16 {
+ _Complex float x1;
+};
+__attribute__((regparm(3))) void pass_wrapped_complex_float(struct s16 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_wrapped_complex_float(float %a.0, float %a.1, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+struct s17 {
+ _Complex int x1[1];
+};
+__attribute__((regparm(3))) void pass_wrapped_complex_int(struct s17 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_wrapped_complex_int(ptr noundef byval(%struct.s17) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+struct s18 {
+ float x1[1];
+};
+__attribute__((regparm(3))) void pass_struct_singleton_array_float(struct s18 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_struct_singleton_array_float(ptr noundef byval(%struct.s18) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
>From a57091159645beb0b5e2f2d49c160bb02b5051d0 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Mon, 28 Sep 2026 23:19:20 +0200
Subject: [PATCH 3/4] [clang][X86] Don't look through unions when classifying
regparm arguments
---
clang/lib/CodeGen/Targets/X86.cpp | 6 +++++-
clang/test/CodeGen/regparm-struct.c | 25 +++++++++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 57229e33d25f99..984da407f44030 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -690,7 +690,11 @@ static const Type *getSingleFieldType(QualType T, ASTContext &Context) {
}
X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
- while (Ty->getAsRecordDecl()) {
+ while (const RecordDecl *RD = Ty->getAsRecordDecl()) {
+ // Unions are always passed as integers.
+ if (RD->isUnion())
+ return Integer;
+
const Type *FT = getSingleFieldType(Ty, getContext());
// Pick integer for zero-sized types. They will be ignored down the line.
diff --git a/clang/test/CodeGen/regparm-struct.c b/clang/test/CodeGen/regparm-struct.c
index 6346cec9653fe5..497c3a5ff0acd3 100644
--- a/clang/test/CodeGen/regparm-struct.c
+++ b/clang/test/CodeGen/regparm-struct.c
@@ -223,3 +223,28 @@ struct s18 {
};
__attribute__((regparm(3))) void pass_struct_singleton_array_float(struct s18 a, int b, int c, int d) {}
// CHECK-LABEL: define{{.*}} void @pass_struct_singleton_array_float(ptr noundef byval(%struct.s18) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+
+// Unions are passed like integers.
+union u1 {
+ float x1;
+};
+__attribute__((regparm(3))) void pass_union_float(union u1 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+
+union u2 {
+ struct s5 x1;
+};
+__attribute__((regparm(3))) void pass_union_struct_float(union u2 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_union_struct_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+
+union u3 {
+ _Complex float x1;
+};
+__attribute__((regparm(3))) void pass_union_complex_float(union u3 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_union_complex_float(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg noundef %b, i32 noundef %c, i32 noundef %d)
+
+struct s19 {
+ union u1 x1;
+};
+__attribute__((regparm(3))) void pass_nested_union_float(struct s19 a, int b, int c, int d) {}
+// CHECK-LABEL: define{{.*}} void @pass_nested_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
>From 3b35d254ec73c9ec294f6d99024cf39291003820 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Wed, 30 Sep 2026 23:19:06 +0000
Subject: [PATCH 4/4] [clang][X86] Add ABI compatibility for regparm fixes
---
clang/docs/ReleaseNotes.md | 7 ++++
clang/include/clang/Basic/ABIVersions.def | 2 ++
clang/lib/CodeGen/Targets/X86.cpp | 14 ++++++++
clang/test/CodeGen/regparm-struct.c | 42 +++++++++++++++--------
4 files changed, 51 insertions(+), 14 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 49d669db5749c0..1796b7789f7e10 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -105,6 +105,13 @@ features cannot lower the translation-unit ABI level;
This also fixes a crash when such a struct was passed or returned.
`-fclang-abi-compat=23` restores the previous behavior. (#GH202205)
+- On 32-bit x86, Clang now matches GCC when classifying arguments for the
+ `regparm` calling convention. Floating-point types other than `float` and
+ `double` no longer consume general-purpose register slots, complex values
+ are passed on the stack without consuming register slots, and unions are no
+ longer classified according to a single member. `-fclang-abi-compat=23`
+ restores the previous behavior. (#GH227130)
+
- Clang now considers matrix types in its isHomogeneousAggregate() handling,
which can lead to differences in how structures containing matrix types are
classified for ABI purposes. The previous exclusion of matrix types appears
diff --git a/clang/include/clang/Basic/ABIVersions.def b/clang/include/clang/Basic/ABIVersions.def
index 3c434da91bfab8..399be760fc7a3a 100644
--- a/clang/include/clang/Basic/ABIVersions.def
+++ b/clang/include/clang/Basic/ABIVersions.def
@@ -167,6 +167,8 @@ ABI_VER_MAJOR(22)
/// faithfully reproduces Clang 23, including its crash on aggregates such
/// as a run of `__int128` bit-fields, where skipping the unnamed field
/// leaves part of a wider access unit unclassified.)
+/// - On 32-bit x86, use the legacy `regparm` classification for floating-point
+/// types other than `float` and `double`, complex types, and unions.
ABI_VER_MAJOR(23)
/// Conform to the underlying platform's C and C++ ABIs as closely as we can.
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 984da407f44030..c0947c481d2b07 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -690,6 +690,20 @@ static const Type *getSingleFieldType(QualType T, ASTContext &Context) {
}
X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
+ if (getContext().getLangOpts().isCompatibleWith(
+ LangOptions::ClangABI::Ver23)) {
+ const Type *T = isSingleElementStruct(Ty, getContext());
+ if (!T)
+ T = Ty.getTypePtr();
+
+ if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
+ BuiltinType::Kind K = BT->getKind();
+ if (K == BuiltinType::Float || K == BuiltinType::Double)
+ return Float;
+ }
+ return Integer;
+ }
+
while (const RecordDecl *RD = Ty->getAsRecordDecl()) {
// Unions are always passed as integers.
if (RD->isUnion())
diff --git a/clang/test/CodeGen/regparm-struct.c b/clang/test/CodeGen/regparm-struct.c
index 497c3a5ff0acd3..5dc2d96c36bfe7 100644
--- a/clang/test/CodeGen/regparm-struct.c
+++ b/clang/test/CodeGen/regparm-struct.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +sse2 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +sse2 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,LATEST
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +sse2 -fclang-abi-compat=23 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,COMPAT23
__attribute__((regparm(3))) void f1(int a, int b, int c, int d);
// CHECK: declare void @f1(i32 inreg noundef, i32 inreg noundef, i32 inreg noundef, i32 noundef)
@@ -177,46 +178,56 @@ void g18(void) {
}
__attribute__((regparm(3))) void pass_f16(_Float16 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_f16(half noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_f16(half noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_f16(half inreg noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
__attribute__((regparm(3))) void pass_bf16(__bf16 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_bf16(bfloat noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_bf16(bfloat noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_bf16(bfloat inreg noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
__attribute__((regparm(3))) void pass_f80(long double a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_f80(x86_fp80 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_f80(x86_fp80 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_f80(x86_fp80 inreg noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d)
__attribute__((regparm(3))) void pass_f128(__float128 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_f128(fp128 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_f128(fp128 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_f128(fp128 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d)
struct s14 {
_Float16 x1;
};
__attribute__((regparm(3))) void pass_wrapped_f16(struct s14 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_wrapped_f16(ptr noundef byval(%struct.s14) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_wrapped_f16(ptr noundef byval(%struct.s14) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_wrapped_f16(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
struct s15 {
__float128 x1;
};
__attribute__((regparm(3))) void pass_wrapped_f128(struct s15 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_wrapped_f128(ptr noundef byval(%struct.s15) align 4 {{%[^,]*}}, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_wrapped_f128(ptr noundef byval(%struct.s15) align 4 {{%[^,]*}}, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_wrapped_f128(ptr noundef byval(%struct.s15) align 4 {{%[^,]*}}, i32 noundef %b, i32 noundef %c, i32 noundef %d)
__attribute__((regparm(3))) void pass_complex_float(_Complex float a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr noundef byval({ float, float }) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_complex_float(ptr noundef byval({ float, float }) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_complex_float(i32 inreg noundef %a.coerce0, i32 inreg noundef %a.coerce1, i32 inreg noundef %b, i32 noundef %c, i32 noundef %d)
__attribute__((regparm(3))) void pass_complex_int(int a, _Complex int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_complex_int(i32 inreg noundef %a, ptr noundef byval({ i32, i32 }) align 4 %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_complex_int(i32 inreg noundef %a, ptr noundef byval({ i32, i32 }) align 4 %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_complex_int(i32 inreg noundef %a, i32 inreg noundef %b.coerce0, i32 inreg noundef %b.coerce1, i32 noundef %c, i32 noundef %d)
struct s16 {
_Complex float x1;
};
__attribute__((regparm(3))) void pass_wrapped_complex_float(struct s16 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_wrapped_complex_float(float %a.0, float %a.1, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_wrapped_complex_float(float %a.0, float %a.1, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_wrapped_complex_float(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg noundef %b, i32 noundef %c, i32 noundef %d)
struct s17 {
_Complex int x1[1];
};
__attribute__((regparm(3))) void pass_wrapped_complex_int(struct s17 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_wrapped_complex_int(ptr noundef byval(%struct.s17) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_wrapped_complex_int(ptr noundef byval(%struct.s17) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_wrapped_complex_int(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg noundef %b, i32 noundef %c, i32 noundef %d)
struct s18 {
float x1[1];
@@ -229,13 +240,15 @@ union u1 {
float x1;
};
__attribute__((regparm(3))) void pass_union_float(union u1 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_union_float(float %a.0, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
union u2 {
struct s5 x1;
};
__attribute__((regparm(3))) void pass_union_struct_float(union u2 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_union_struct_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_union_struct_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_union_struct_float(ptr noundef byval(%union.u2) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
union u3 {
_Complex float x1;
@@ -247,4 +260,5 @@ struct s19 {
union u1 x1;
};
__attribute__((regparm(3))) void pass_nested_union_float(struct s19 a, int b, int c, int d) {}
-// CHECK-LABEL: define{{.*}} void @pass_nested_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// LATEST-LABEL: define{{.*}} void @pass_nested_union_float(i32 inreg %a.coerce, i32 inreg noundef %b, i32 inreg noundef %c, i32 noundef %d)
+// COMPAT23-LABEL: define{{.*}} void @pass_nested_union_float(ptr noundef byval(%struct.s19) align 4 %a, i32 inreg noundef %b, i32 inreg noundef %c, i32 inreg noundef %d)
More information about the cfe-commits
mailing list