https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/208917
>From d3a9d50b0d989d96be71a254761d05609dd9199e Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 13:27:46 +0200 Subject: [PATCH 01/10] inline `ABIArgInfo::classifyArgumentType` --- clang/lib/CodeGen/Targets/PPC.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 5109567212adb..adcb2dd96189a 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -371,6 +371,7 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty) const; void computeInfo(CGFunctionInfo &FI) const override { if (!getCXXABI().classifyReturnType(FI)) @@ -427,6 +428,36 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (isAggregateTypeForABI(Ty)) { + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); + + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); + } + + // Treat an enum type as its underlying type. + if (const auto *ED = Ty->getAsEnumDecl()) + Ty = ED->getIntegerType(); + + ASTContext &Context = getContext(); + if (const auto *EIT = Ty->getAs<BitIntType>()) + if (EIT->getNumBits() > + Context.getTypeSize(Context.getTargetInfo().hasInt128Type() + ? Context.Int128Ty + : Context.LongLongTy)) + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); + + return (isPromotableIntegerTypeForABI(Ty) + ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) + : ABIArgInfo::getDirect()); +} + ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { uint64_t Size; >From 2f8d093a1f5716d4aeba4677800e22d05e9669dd Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 13:29:53 +0200 Subject: [PATCH 02/10] add `isComplexGnuABI` --- clang/lib/CodeGen/Targets/PPC.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index adcb2dd96189a..861b362318db9 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -362,6 +362,12 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool isComplexGnuABI() const { + return !getTarget().getTriple().isOSDarwin() && + !getContext().getLangOpts().isCompatibleWith( + LangOptions::ClangABI::Ver22); + } + CharUnits getParamTypeAlignment(QualType Ty) const; public: >From 1e8b524793570d92bb48f1004e8c1ca729e3838b Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 13:36:43 +0200 Subject: [PATCH 03/10] add `ArgGPRsLeft` parameter to `classifyArgumentType` --- clang/lib/CodeGen/Targets/PPC.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 861b362318db9..ec8fc9718803f 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -362,6 +362,10 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + // Number of GPRs (r3..=r10) available for passing arguments, and their width. + static const int NumArgGPRs = 8; + static const unsigned GPRBits = 32; + bool isComplexGnuABI() const { return !getTarget().getTriple().isOSDarwin() && !getContext().getLangOpts().isCompatibleWith( @@ -377,13 +381,15 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType Ty) const; + ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft) const; void computeInfo(CGFunctionInfo &FI) const override { if (!getCXXABI().classifyReturnType(FI)) FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + + int ArgGPRsLeft = NumArgGPRs; for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); + I.info = classifyArgumentType(I.type, ArgGPRsLeft); } RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, @@ -434,7 +440,9 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } -ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, + int &ArgGPRsLeft) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); Ty = useFirstFieldIfTransparentUnion(Ty); if (isAggregateTypeForABI(Ty)) { @@ -501,8 +509,10 @@ RValue PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, TI.Align = getParamTypeAlignment(Ty); CharUnits SlotSize = CharUnits::fromQuantity(4); + int ArgGPRsLeft = NumArgGPRs; return emitVoidPtrVAArg(CGF, VAList, Ty, - classifyArgumentType(Ty).isIndirect(), TI, SlotSize, + classifyArgumentType(Ty, ArgGPRsLeft).isIndirect(), + TI, SlotSize, /*AllowHigherAlign=*/true, Slot); } >From c2da0a94636c0f7384a833ddd70615e230d69c76 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 14:01:32 +0200 Subject: [PATCH 04/10] add GPR budget logic --- clang/lib/CodeGen/Targets/PPC.cpp | 50 ++++++++++++++++++------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index ec8fc9718803f..a5ff0fc3c5443 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -445,31 +445,39 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); Ty = useFirstFieldIfTransparentUnion(Ty); - if (isAggregateTypeForABI(Ty)) { - // Records with non-trivial destructors/copy-constructors should not be - // passed by value. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), - RAA == CGCXXABI::RAA_DirectInMemory); + bool IsComplex = Ty->isAnyComplexType() && isComplexGnuABI(); - return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); - } + // Use the default implementation when this argument is not relevant for GPR + // budget: + // + // - floating-point types are passed in FPRs + // - when GPRs are already exhausted + // + // Complex types (when GNU compatible) always need custom handling. + if (!IsComplex && (!ArgGPRsLeft || (Ty->isFloatingType() && !IsSoftFloatABI))) + return DefaultABIInfo::classifyArgumentType(Ty); - // Treat an enum type as its underlying type. - if (const auto *ED = Ty->getAsEnumDecl()) - Ty = ED->getIntegerType(); + uint64_t TypeSize = getContext().getTypeSize(Ty); + uint64_t RegsNeeded = (TypeSize + GPRBits - 1) / GPRBits; - ASTContext &Context = getContext(); - if (const auto *EIT = Ty->getAs<BitIntType>()) - if (EIT->getNumBits() > - Context.getTypeSize(Context.getTargetInfo().hasInt128Type() - ? Context.Int128Ty - : Context.LongLongTy)) - return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); + if (IsComplex || !isAggregateTypeForABI(Ty)) { + // Complex values and scalars are passed in GPRs. - return (isPromotableIntegerTypeForABI(Ty) - ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) - : ABIArgInfo::getDirect()); + // An 8-byte value (e.g. _Complex float, _Complex int, i64, soft-float + // double) must start in an even-numbered GPR, so skip an odd register to + // keep the pair aligned. + if (TypeSize == 2 * GPRBits && ArgGPRsLeft % 2 == 1) + ArgGPRsLeft -= 1; + + if (RegsNeeded <= (uint64_t)ArgGPRsLeft) { + ArgGPRsLeft -= RegsNeeded; + } + } else { + // Other aggregates are passed indirectly, and consume one GPR. + ArgGPRsLeft -= 1; + } + + return DefaultABIInfo::classifyArgumentType(Ty); } ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { >From 5e7caf37efefc0faa9be504de8263907841fea15 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 15:10:03 +0200 Subject: [PATCH 05/10] add `classifyComplexType` --- clang/lib/CodeGen/Targets/PPC.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index a5ff0fc3c5443..e340eb9baee24 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -373,6 +373,7 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { } CharUnits getParamTypeAlignment(QualType Ty) const; + ABIArgInfo classifyComplexType(QualType Ty) const; public: PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI, @@ -440,6 +441,32 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::classifyComplexType(QualType Ty) const { + uint64_t Size = getContext().getTypeSize(Ty); + llvm::LLVMContext &VMC = getVMContext(); + llvm::Type *I32 = llvm::Type::getInt32Ty(VMC); + QualType ElemTy = Ty->castAs<ComplexType>()->getElementType(); + + // Work around https://github.com/llvm/llvm-project/issues/44482. + // This is a bug where the two halves of a ppc_fp128 are swapped. + // Using i128 for the ABI instead circumvents this issue. + if (CGT.ConvertType(ElemTy)->isPPC_FP128Ty()) + return ABIArgInfo::getDirect( + llvm::ArrayType::get(llvm::Type::getInt128Ty(VMC), 2)); + + // Coerce to an integer for _Complex char and _Complex short. + if (Size <= GPRBits) + return ABIArgInfo::getDirect(llvm::IntegerType::get(VMC, Size)); + + // Coerce to a vector <N x i32> for _Complex float and _Complex int. + if (Size == 2 * GPRBits) + return ABIArgInfo::getDirect(llvm::FixedVectorType::get(I32, 2)); + + // Coerce to an array [N x i32] for _Complex double and similar. + // Using i32 gives the correct 4-byte register alignment. + return ABIArgInfo::getDirect(llvm::ArrayType::get(I32, Size / GPRBits)); +} + ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft) const { assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); >From cf112c9dafe9ff6aa964d2c3d3a62471c7e6e805 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 15:18:33 +0200 Subject: [PATCH 06/10] hook up new complex abi logic --- clang/lib/CodeGen/Targets/PPC.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index e340eb9baee24..537ed33651044 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -445,6 +445,8 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyComplexType(QualType Ty) const { uint64_t Size = getContext().getTypeSize(Ty); llvm::LLVMContext &VMC = getVMContext(); llvm::Type *I32 = llvm::Type::getInt32Ty(VMC); + + assert(Ty->isAnyComplexType() && "not a complex type"); QualType ElemTy = Ty->castAs<ComplexType>()->getElementType(); // Work around https://github.com/llvm/llvm-project/issues/44482. @@ -459,11 +461,12 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyComplexType(QualType Ty) const { return ABIArgInfo::getDirect(llvm::IntegerType::get(VMC, Size)); // Coerce to a vector <N x i32> for _Complex float and _Complex int. + // A vector gives this the correct 8-byte register alignment. if (Size == 2 * GPRBits) return ABIArgInfo::getDirect(llvm::FixedVectorType::get(I32, 2)); // Coerce to an array [N x i32] for _Complex double and similar. - // Using i32 gives the correct 4-byte register alignment. + // An array of i32 gives the correct 4-byte register alignment. return ABIArgInfo::getDirect(llvm::ArrayType::get(I32, Size / GPRBits)); } @@ -497,7 +500,28 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, ArgGPRsLeft -= 1; if (RegsNeeded <= (uint64_t)ArgGPRsLeft) { + // All fits. ArgGPRsLeft -= RegsNeeded; + + // _Complex needs a type coercion to be passed correctly. + if (IsComplex) + return classifyComplexType(Ty); + } else if (IsComplex) { + // Never split a Complex value across GPRs and the stack. When a Complex + // value does not fit in the remaining GPRs, it is passed via the stack + // and the remaining GPRs are considered consumed, so any further + // arguments will be passed via the stack as well. + + // _Complex needs a type coercion to be passed correctly. + llvm::Type *CoerceTy = classifyComplexType(Ty).getCoerceToType(); + + // Soak up the remaining GPRs with a padding argument. + llvm::Type *I32 = llvm::Type::getInt32Ty(getVMContext()); + llvm::Type *Padding = + ArgGPRsLeft > 0 ? llvm::ArrayType::get(I32, ArgGPRsLeft) : nullptr; + + ArgGPRsLeft = 0; + return ABIArgInfo::getDirect(CoerceTy, /*Offset=*/0, Padding); } } else { // Other aggregates are passed indirectly, and consume one GPR. @@ -510,6 +534,9 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { uint64_t Size; + if (RetTy->isAnyComplexType() && isComplexGnuABI()) + return classifyComplexType(RetTy); + // -msvr4-struct-return puts small aggregates in GPR3 and GPR4. if (isAggregateTypeForABI(RetTy) && IsRetSmallStructInRegABI && (Size = getContext().getTypeSize(RetTy)) <= 64) { >From 2e7de5297cfb62ad4cebf81cc677b83048371a19 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 11 Jul 2026 16:57:51 +0200 Subject: [PATCH 07/10] fix test --- .../PowerPC/builtins-ppc-xlcompat-cmplx.c | 360 +++++++++++------- .../test/CodeGen/PowerPC/powerpc-c99complex.c | 92 ++++- clang/test/CodeGen/long_double_fp128.cpp | 9 +- .../math-libcalls-tbaa-indirect-args.c | 71 ++-- 4 files changed, 350 insertions(+), 182 deletions(-) diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-cmplx.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-cmplx.c index cf03af38b3784..ae224aef66da9 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-cmplx.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-cmplx.c @@ -6,10 +6,14 @@ // RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s --check-prefix=64BITLE // RUN: %clang_cc1 -triple powerpc64-unknown-aix \ // RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=64BITAIX -// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu \ -// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=32BIT -// RUN: %clang_cc1 -triple powerpcle-unknown-linux-gnu \ -// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s --check-prefix=32BITLE +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fclang-abi-compat=22 \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=32BIT-CLANG22 +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fclang-abi-compat=23 \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=32BIT-CLANG23 +// RUN: %clang_cc1 -triple powerpcle-unknown-linux-gnu -fclang-abi-compat=22 \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s --check-prefix=32BITLE-CLANG22 +// RUN: %clang_cc1 -triple powerpcle-unknown-linux-gnu -fclang-abi-compat=23 \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s --check-prefix=32BITLE-CLANG23 // RUN: %clang_cc1 -triple powerpc-unknown-aix \ // RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=32BITAIX @@ -61,49 +65,81 @@ // 64BITAIX-NEXT: [[TMP2:%.*]] = load { double, double }, ptr [[RETVAL]], align 4 // 64BITAIX-NEXT: ret { double, double } [[TMP2]] // -// 32BIT-LABEL: @testcmplx( -// 32BIT-NEXT: entry: -// 32BIT-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 -// 32BIT-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 -// 32BIT-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 -// 32BIT-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 -// 32BIT-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 -// 32BIT-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 -// 32BIT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store double [[TMP0]], ptr [[AGG_RESULT_REALP]], align 8 -// 32BIT-NEXT: store double [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 8 -// 32BIT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 -// 32BIT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 -// 32BIT-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 -// 32BIT-NEXT: ret void +// 32BIT-CLANG22-LABEL: @testcmplx( +// 32BIT-CLANG22-NEXT: entry: +// 32BIT-CLANG22-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 +// 32BIT-CLANG22-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 +// 32BIT-CLANG22-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 +// 32BIT-CLANG22-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 +// 32BIT-CLANG22-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 +// 32BIT-CLANG22-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store double [[TMP0]], ptr [[AGG_RESULT_REALP]], align 8 +// 32BIT-CLANG22-NEXT: store double [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 8 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// 32BIT-CLANG22-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// 32BIT-CLANG22-NEXT: ret void // -// 32BITLE-LABEL: @testcmplx( -// 32BITLE-NEXT: entry: -// 32BITLE-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 -// 32BITLE-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 -// 32BITLE-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 -// 32BITLE-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 -// 32BITLE-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 -// 32BITLE-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 -// 32BITLE-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store double [[TMP0]], ptr [[AGG_RESULT_REALP]], align 8 -// 32BITLE-NEXT: store double [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 8 -// 32BITLE-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 -// 32BITLE-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 -// 32BITLE-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 -// 32BITLE-NEXT: ret void +// 32BIT-CLANG23-LABEL: @testcmplx( +// 32BIT-CLANG23-NEXT: entry: +// 32BIT-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// 32BIT-CLANG23-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 +// 32BIT-CLANG23-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 +// 32BIT-CLANG23-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 +// 32BIT-CLANG23-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 +// 32BIT-CLANG23-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 +// 32BIT-CLANG23-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 +// 32BIT-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// 32BIT-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// 32BIT-CLANG23-NEXT: store double [[TMP0]], ptr [[RETVAL_REALP]], align 8 +// 32BIT-CLANG23-NEXT: store double [[TMP1]], ptr [[RETVAL_IMAGP]], align 8 +// 32BIT-CLANG23-NEXT: [[TMP2:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// 32BIT-CLANG23-NEXT: ret [4 x i32] [[TMP2]] +// +// 32BITLE-CLANG22-LABEL: @testcmplx( +// 32BITLE-CLANG22-NEXT: entry: +// 32BITLE-CLANG22-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 +// 32BITLE-CLANG22-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 +// 32BITLE-CLANG22-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 +// 32BITLE-CLANG22-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 +// 32BITLE-CLANG22-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 +// 32BITLE-CLANG22-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store double [[TMP0]], ptr [[AGG_RESULT_REALP]], align 8 +// 32BITLE-CLANG22-NEXT: store double [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 8 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// 32BITLE-CLANG22-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// 32BITLE-CLANG22-NEXT: ret void +// +// 32BITLE-CLANG23-LABEL: @testcmplx( +// 32BITLE-CLANG23-NEXT: entry: +// 32BITLE-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// 32BITLE-CLANG23-NEXT: [[REAL_ADDR:%.*]] = alloca double, align 8 +// 32BITLE-CLANG23-NEXT: [[IMAG_ADDR:%.*]] = alloca double, align 8 +// 32BITLE-CLANG23-NEXT: store double [[REAL:%.*]], ptr [[REAL_ADDR]], align 8 +// 32BITLE-CLANG23-NEXT: store double [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 8 +// 32BITLE-CLANG23-NEXT: [[TMP0:%.*]] = load double, ptr [[REAL_ADDR]], align 8 +// 32BITLE-CLANG23-NEXT: [[TMP1:%.*]] = load double, ptr [[IMAG_ADDR]], align 8 +// 32BITLE-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// 32BITLE-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// 32BITLE-CLANG23-NEXT: store double [[TMP0]], ptr [[RETVAL_REALP]], align 8 +// 32BITLE-CLANG23-NEXT: store double [[TMP1]], ptr [[RETVAL_IMAGP]], align 8 +// 32BITLE-CLANG23-NEXT: [[TMP2:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// 32BITLE-CLANG23-NEXT: ret [4 x i32] [[TMP2]] // // 32BITAIX-LABEL: @testcmplx( // 32BITAIX-NEXT: entry: @@ -173,49 +209,81 @@ double _Complex testcmplx(double real, double imag) { // 64BITAIX-NEXT: [[TMP2:%.*]] = load { float, float }, ptr [[RETVAL]], align 4 // 64BITAIX-NEXT: ret { float, float } [[TMP2]] // -// 32BIT-LABEL: @testcmplxf( -// 32BIT-NEXT: entry: -// 32BIT-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 -// 32BIT-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 -// 32BIT-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 -// 32BIT-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 -// 32BIT-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 -// 32BIT-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 -// 32BIT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store float [[TMP0]], ptr [[AGG_RESULT_REALP]], align 4 -// 32BIT-NEXT: store float [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 4 -// 32BIT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 -// 32BIT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 -// 32BIT-NEXT: store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 -// 32BIT-NEXT: ret void +// 32BIT-CLANG22-LABEL: @testcmplxf( +// 32BIT-CLANG22-NEXT: entry: +// 32BIT-CLANG22-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 +// 32BIT-CLANG22-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 +// 32BIT-CLANG22-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 +// 32BIT-CLANG22-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 +// 32BIT-CLANG22-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 +// 32BIT-CLANG22-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store float [[TMP0]], ptr [[AGG_RESULT_REALP]], align 4 +// 32BIT-CLANG22-NEXT: store float [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 4 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 +// 32BIT-CLANG22-NEXT: store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 +// 32BIT-CLANG22-NEXT: ret void +// +// 32BIT-CLANG23-LABEL: @testcmplxf( +// 32BIT-CLANG23-NEXT: entry: +// 32BIT-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// 32BIT-CLANG23-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 +// 32BIT-CLANG23-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 +// 32BIT-CLANG23-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 +// 32BIT-CLANG23-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 +// 32BIT-CLANG23-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 +// 32BIT-CLANG23-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 +// 32BIT-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// 32BIT-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// 32BIT-CLANG23-NEXT: store float [[TMP0]], ptr [[RETVAL_REALP]], align 4 +// 32BIT-CLANG23-NEXT: store float [[TMP1]], ptr [[RETVAL_IMAGP]], align 4 +// 32BIT-CLANG23-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 4 +// 32BIT-CLANG23-NEXT: ret <2 x i32> [[TMP2]] // -// 32BITLE-LABEL: @testcmplxf( -// 32BITLE-NEXT: entry: -// 32BITLE-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 -// 32BITLE-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 -// 32BITLE-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 -// 32BITLE-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 -// 32BITLE-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 -// 32BITLE-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 -// 32BITLE-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store float [[TMP0]], ptr [[AGG_RESULT_REALP]], align 4 -// 32BITLE-NEXT: store float [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 4 -// 32BITLE-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: [[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 -// 32BITLE-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 -// 32BITLE-NEXT: store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 -// 32BITLE-NEXT: ret void +// 32BITLE-CLANG22-LABEL: @testcmplxf( +// 32BITLE-CLANG22-NEXT: entry: +// 32BITLE-CLANG22-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 +// 32BITLE-CLANG22-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 +// 32BITLE-CLANG22-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 +// 32BITLE-CLANG22-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 +// 32BITLE-CLANG22-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 +// 32BITLE-CLANG22-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store float [[TMP0]], ptr [[AGG_RESULT_REALP]], align 4 +// 32BITLE-CLANG22-NEXT: store float [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 4 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 +// 32BITLE-CLANG22-NEXT: store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 +// 32BITLE-CLANG22-NEXT: ret void +// +// 32BITLE-CLANG23-LABEL: @testcmplxf( +// 32BITLE-CLANG23-NEXT: entry: +// 32BITLE-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// 32BITLE-CLANG23-NEXT: [[REAL_ADDR:%.*]] = alloca float, align 4 +// 32BITLE-CLANG23-NEXT: [[IMAG_ADDR:%.*]] = alloca float, align 4 +// 32BITLE-CLANG23-NEXT: store float [[REAL:%.*]], ptr [[REAL_ADDR]], align 4 +// 32BITLE-CLANG23-NEXT: store float [[IMAG:%.*]], ptr [[IMAG_ADDR]], align 4 +// 32BITLE-CLANG23-NEXT: [[TMP0:%.*]] = load float, ptr [[REAL_ADDR]], align 4 +// 32BITLE-CLANG23-NEXT: [[TMP1:%.*]] = load float, ptr [[IMAG_ADDR]], align 4 +// 32BITLE-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// 32BITLE-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// 32BITLE-CLANG23-NEXT: store float [[TMP0]], ptr [[RETVAL_REALP]], align 4 +// 32BITLE-CLANG23-NEXT: store float [[TMP1]], ptr [[RETVAL_IMAGP]], align 4 +// 32BITLE-CLANG23-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 4 +// 32BITLE-CLANG23-NEXT: ret <2 x i32> [[TMP2]] // // 32BITAIX-LABEL: @testcmplxf( // 32BITAIX-NEXT: entry: @@ -285,49 +353,81 @@ float _Complex testcmplxf(float real, float imag) { // 64BITAIX-NEXT: [[TMP2:%.*]] = load { double, double }, ptr [[RETVAL]], align 4 // 64BITAIX-NEXT: ret { double, double } [[TMP2]] // -// 32BIT-LABEL: @test_xl_cmplxl( -// 32BIT-NEXT: entry: -// 32BIT-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 -// 32BIT-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 -// 32BIT-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 -// 32BIT-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 -// 32BIT-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 -// 32BIT-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 -// 32BIT-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store ppc_fp128 [[TMP0]], ptr [[AGG_RESULT_REALP]], align 16 -// 32BIT-NEXT: store ppc_fp128 [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 16 -// 32BIT-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_REAL:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_REALP1]], align 16 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: [[AGG_RESULT_IMAG:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_IMAGP2]], align 16 -// 32BIT-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BIT-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BIT-NEXT: store ppc_fp128 [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 16 -// 32BIT-NEXT: store ppc_fp128 [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 16 -// 32BIT-NEXT: ret void +// 32BIT-CLANG22-LABEL: @test_xl_cmplxl( +// 32BIT-CLANG22-NEXT: entry: +// 32BIT-CLANG22-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BIT-CLANG22-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 +// 32BIT-CLANG22-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 +// 32BIT-CLANG22-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[TMP0]], ptr [[AGG_RESULT_REALP]], align 16 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 16 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_REALP1]], align 16 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_IMAGP2]], align 16 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BIT-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 16 +// 32BIT-CLANG22-NEXT: store ppc_fp128 [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 16 +// 32BIT-CLANG22-NEXT: ret void +// +// 32BIT-CLANG23-LABEL: @test_xl_cmplxl( +// 32BIT-CLANG23-NEXT: entry: +// 32BIT-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// 32BIT-CLANG23-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BIT-CLANG23-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BIT-CLANG23-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 +// 32BIT-CLANG23-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 +// 32BIT-CLANG23-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 +// 32BIT-CLANG23-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 +// 32BIT-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// 32BIT-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// 32BIT-CLANG23-NEXT: store ppc_fp128 [[TMP0]], ptr [[RETVAL_REALP]], align 16 +// 32BIT-CLANG23-NEXT: store ppc_fp128 [[TMP1]], ptr [[RETVAL_IMAGP]], align 16 +// 32BIT-CLANG23-NEXT: [[TMP2:%.*]] = load [2 x i128], ptr [[RETVAL]], align 16 +// 32BIT-CLANG23-NEXT: ret [2 x i128] [[TMP2]] +// +// 32BITLE-CLANG22-LABEL: @test_xl_cmplxl( +// 32BITLE-CLANG22-NEXT: entry: +// 32BITLE-CLANG22-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BITLE-CLANG22-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 +// 32BITLE-CLANG22-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 +// 32BITLE-CLANG22-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[TMP0]], ptr [[AGG_RESULT_REALP]], align 16 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 16 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REAL:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_REALP1]], align 16 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAG:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_IMAGP2]], align 16 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 +// 32BITLE-CLANG22-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 16 +// 32BITLE-CLANG22-NEXT: store ppc_fp128 [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 16 +// 32BITLE-CLANG22-NEXT: ret void // -// 32BITLE-LABEL: @test_xl_cmplxl( -// 32BITLE-NEXT: entry: -// 32BITLE-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 -// 32BITLE-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 -// 32BITLE-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 -// 32BITLE-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 -// 32BITLE-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 -// 32BITLE-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 -// 32BITLE-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT:%.*]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store ppc_fp128 [[TMP0]], ptr [[AGG_RESULT_REALP]], align 16 -// 32BITLE-NEXT: store ppc_fp128 [[TMP1]], ptr [[AGG_RESULT_IMAGP]], align 16 -// 32BITLE-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_REAL:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_REALP1]], align 16 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: [[AGG_RESULT_IMAG:%.*]] = load ppc_fp128, ptr [[AGG_RESULT_IMAGP2]], align 16 -// 32BITLE-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 0 -// 32BITLE-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[AGG_RESULT]], i32 0, i32 1 -// 32BITLE-NEXT: store ppc_fp128 [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 16 -// 32BITLE-NEXT: store ppc_fp128 [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 16 -// 32BITLE-NEXT: ret void +// 32BITLE-CLANG23-LABEL: @test_xl_cmplxl( +// 32BITLE-CLANG23-NEXT: entry: +// 32BITLE-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// 32BITLE-CLANG23-NEXT: [[LDA_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BITLE-CLANG23-NEXT: [[LDB_ADDR:%.*]] = alloca ppc_fp128, align 16 +// 32BITLE-CLANG23-NEXT: store ppc_fp128 [[LDA:%.*]], ptr [[LDA_ADDR]], align 16 +// 32BITLE-CLANG23-NEXT: store ppc_fp128 [[LDB:%.*]], ptr [[LDB_ADDR]], align 16 +// 32BITLE-CLANG23-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr [[LDA_ADDR]], align 16 +// 32BITLE-CLANG23-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr [[LDB_ADDR]], align 16 +// 32BITLE-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// 32BITLE-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// 32BITLE-CLANG23-NEXT: store ppc_fp128 [[TMP0]], ptr [[RETVAL_REALP]], align 16 +// 32BITLE-CLANG23-NEXT: store ppc_fp128 [[TMP1]], ptr [[RETVAL_IMAGP]], align 16 +// 32BITLE-CLANG23-NEXT: [[TMP2:%.*]] = load [2 x i128], ptr [[RETVAL]], align 16 +// 32BITLE-CLANG23-NEXT: ret [2 x i128] [[TMP2]] // // 32BITAIX-LABEL: @test_xl_cmplxl( // 32BITAIX-NEXT: entry: diff --git a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c index 8911257741c33..b6b6832bce3df 100644 --- a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c +++ b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c @@ -1,19 +1,37 @@ -// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128 -// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128 -// RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128 -// RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128 -// RUN: %clang_cc1 -triple powerpc-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-NOLDBL128,CHECK +// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-NOLDBL128,CHECK +// RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-LDBL128,CHECK +// RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-LDBL128,CHECK +// RUN: %clang_cc1 -triple powerpc-unknown-linux -fclang-abi-compat=22 -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX-CLANG22 +// RUN: %clang_cc1 -triple powerpc-unknown-linux -fclang-abi-compat=23 -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX-CLANG23 _Complex float foo1(_Complex float x) { return x; // CHECK-LABEL: define{{.*}} { float, float } @foo1(float noundef %x.{{.*}}, float noundef %x.{{.*}}) #0 { // CHECK: ret { float, float } -// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4 -// PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETIMAG]], align 4 +// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { +// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG22-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4 +// PPC32LNX-CLANG22-NEXT: store float %{{.*}}, ptr [[RETIMAG]], align 4 + +// PPC32LNX-CLANG23-LABEL: define dso_local <2 x i32> @foo1( +// PPC32LNX-CLANG23-SAME: <2 x i32> noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] +// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { float, float }, align 4 +// PPC32LNX-CLANG23-NEXT: store <2 x i32> [[X_COERCE]], ptr [[X]], align 4 +// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store float [[X_REAL]], ptr [[RETVAL_REALP]], align 4 +// PPC32LNX-CLANG23-NEXT: store float [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 4 +// PPC32LNX-CLANG23-NEXT: ret <2 x i32> [[TMP0]] } _Complex double foo2(_Complex double x) { @@ -21,11 +39,28 @@ _Complex double foo2(_Complex double x) { // CHECK-LABEL: define{{.*}} { double, double } @foo2(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 { // CHECK: ret { double, double } -// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8 -// PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETIMAG]], align 8 +// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { +// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG22-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8 +// PPC32LNX-CLANG22-NEXT: store double %{{.*}}, ptr [[RETIMAG]], align 8 + +// PPC32LNX-CLANG23-LABEL: define dso_local [4 x i32] @foo2( +// PPC32LNX-CLANG23-SAME: [4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] +// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { double, double }, align 8 +// PPC32LNX-CLANG23-NEXT: store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// PPC32LNX-CLANG23-NEXT: store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// PPC32LNX-CLANG23-NEXT: ret [4 x i32] [[TMP0]] } _Complex long double foo3(_Complex long double x) { @@ -36,9 +71,26 @@ _Complex long double foo3(_Complex long double x) { // CHECK-LDBL128-LABEL: define{{.*}} { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 noundef %x.{{.*}}, ppc_fp128 noundef %x.{{.*}}) #0 { // CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 } -// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 -// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16 +// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { +// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 +// PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16 + +// PPC32LNX-CLANG23-LABEL: define dso_local [2 x i128] @foo3( +// PPC32LNX-CLANG23-SAME: [2 x i128] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] +// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// PPC32LNX-CLANG23-NEXT: store [2 x i128] [[X_COERCE]], ptr [[X]], align 16 +// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [2 x i128], ptr [[RETVAL]], align 16 +// PPC32LNX-CLANG23-NEXT: ret [2 x i128] [[TMP0]] } diff --git a/clang/test/CodeGen/long_double_fp128.cpp b/clang/test/CodeGen/long_double_fp128.cpp index a66e5c5be585f..6b2360d724fa1 100644 --- a/clang/test/CodeGen/long_double_fp128.cpp +++ b/clang/test/CodeGen/long_double_fp128.cpp @@ -8,8 +8,10 @@ // RUN: | FileCheck %s --check-prefix=A32 // RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefix=G32 -// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm -o - %s \ -// RUN: | FileCheck %s --check-prefix=P32 +// RUN: %clang_cc1 -triple powerpc-linux-gnu -fclang-abi-compat=22 -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=P32-CLANG22 +// RUN: %clang_cc1 -triple powerpc-linux-gnu -fclang-abi-compat=23 -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=P32-CLANG23 // Check mangled name of long double. // Android's gcc and llvm use fp128 for long double. @@ -19,4 +21,5 @@ void test(long, float, double, long double, long double _Complex) { } // P64: define{{.*}} void @_Z4testlfdgCg(i64 noundef %0, float noundef %1, double noundef %2, ppc_fp128 noundef %3, ppc_fp128 {{.*}}, ppc_fp128 // A32: define{{.*}} void @_Z4testlfdeCe(i32 noundef %0, float noundef %1, double noundef %2, double noundef %3, ptr // G32: define{{.*}} void @_Z4testlfdeCe(i32 noundef %0, float noundef %1, double noundef %2, x86_fp80 noundef %3, ptr -// P32: define{{.*}} void @_Z4testlfdgCg(i32 noundef %0, float noundef %1, double noundef %2, ppc_fp128 noundef %3, ptr +// P32-CLANG22: define{{.*}} void @_Z4testlfdgCg(i32 noundef %0, float noundef %1, double noundef %2, ppc_fp128 noundef %3, ptr +// P32-CLANG23: define{{.*}} void @_Z4testlfdgCg(i32 noundef %0, float noundef %1, double noundef %2, ppc_fp128 noundef %3, [7 x i32] {{.*}}, [2 x i128] diff --git a/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c index 3ae27960d2b7f..b03c0022867db 100644 --- a/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c +++ b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c @@ -2,7 +2,8 @@ // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s -check-prefixes=CHECK // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple x86_64-pc-win64 -o - | FileCheck %s -check-prefixes=CHECK-WIN64 // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple i686-unknown-unknown -o - | FileCheck %s -check-prefixes=CHECK-I686 -// RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple powerpc-unknown-unknown -o - | FileCheck %s -check-prefixes=CHECK-PPC +// RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple powerpc-unknown-unknown -fclang-abi-compat=22 -o - | FileCheck %s -check-prefixes=CHECK-PPC-CLANG22 +// RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple powerpc-unknown-unknown -fclang-abi-compat=23 -o - | FileCheck %s -check-prefixes=CHECK-PPC-CLANG23 // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple armv7-none-linux-gnueabi -o - | FileCheck %s -check-prefixes=CHECK-ARM // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s -check-prefixes=CHECK-ARM-HF // RUN: %clang_cc1 %s -O3 -fmath-errno -emit-llvm -triple thumbv7k-apple-watchos2.0 -o - -target-abi aapcs16 | FileCheck %s -check-prefixes=CHECK-THUMB @@ -28,9 +29,13 @@ long double powl(long double a, long double b); // CHECK-I686-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-I686: [[CALL:%.*]] = tail call x86_fp80 @powl(x86_fp80 noundef [[A]], x86_fp80 noundef [[B]]) #[[ATTR5:[0-9]+]] // -// CHECK-PPC-LABEL: define dso_local ppc_fp128 @test_powl( -// CHECK-PPC-SAME: ppc_fp128 noundef [[A:%.*]], ppc_fp128 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @powl(ppc_fp128 noundef [[A]], ppc_fp128 noundef [[B]]) #[[ATTR4:[0-9]+]] +// CHECK-PPC-CLANG22-LABEL: define dso_local ppc_fp128 @test_powl( +// CHECK-PPC-CLANG22-SAME: ppc_fp128 noundef [[A:%.*]], ppc_fp128 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-PPC-CLANG22: [[CALL:%.*]] = tail call ppc_fp128 @powl(ppc_fp128 noundef [[A]], ppc_fp128 noundef [[B]]) #[[ATTR4:[0-9]+]] +// +// CHECK-PPC-CLANG23-LABEL: define dso_local ppc_fp128 @test_powl( +// CHECK-PPC-CLANG23-SAME: ppc_fp128 noundef [[A:%.*]], ppc_fp128 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-PPC-CLANG23: [[CALL:%.*]] = tail call ppc_fp128 @powl(ppc_fp128 noundef [[A]], ppc_fp128 noundef [[B]]) #[[ATTR3:[0-9]+]] // // CHECK-ARM-LABEL: define dso_local double @test_powl( // CHECK-ARM-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { @@ -54,13 +59,13 @@ long double powl(long double a, long double b); // // CHECK-MINGW32-LABEL: define dso_local void @test_powl( // CHECK-MINGW32-SAME: ptr dead_on_unwind noalias nofree writable writeonly sret(x86_fp80) align 16 captures(none) initializes((0, 10)) [[AGG_RESULT:%.*]], ptr nofree noundef readonly align 16 captures(none) dead_on_return [[TMP0:%.*]], ptr nofree noundef readonly align 16 captures(none) dead_on_return [[TMP1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[LONG_DOUBLE_TBAA9:![0-9]+]] -// CHECK-MINGW32: [[B:%.*]] = load x86_fp80, ptr [[TMP1]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] -// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] -// CHECK-MINGW32: store x86_fp80 [[B]], ptr [[BYVAL_TEMP1:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] +// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[LONG_DOUBLE_TBAA10:![0-9]+]] +// CHECK-MINGW32: [[B:%.*]] = load x86_fp80, ptr [[TMP1]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] +// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] +// CHECK-MINGW32: store x86_fp80 [[B]], ptr [[BYVAL_TEMP1:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] // CHECK-MINGW32: call void @powl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr noundef nonnull align 16 dead_on_return [[BYVAL_TEMP]], ptr noundef nonnull align 16 dead_on_return [[BYVAL_TEMP1]]) #[[ATTR3:[0-9]+]] -// CHECK-MINGW32: [[TMP2:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] -// CHECK-MINGW32: store x86_fp80 [[TMP2]], ptr [[AGG_RESULT]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] +// CHECK-MINGW32: [[TMP2:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] +// CHECK-MINGW32: store x86_fp80 [[TMP2]], ptr [[AGG_RESULT]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] // long double test_powl(long double a, long double b) { return powl(a, b); @@ -92,15 +97,19 @@ long double test_powl(long double a, long double b) { // CHECK-I686: store x86_fp80 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 4 // CHECK-I686: store x86_fp80 [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 4 // -// CHECK-PPC-LABEL: define dso_local void @test_cargl( -// CHECK-PPC-SAME: ptr dead_on_unwind noalias nofree writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr nofree noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { -// CHECK-PPC: [[CLD_REAL:%.*]] = load ppc_fp128, ptr [[CLD]], align 16 -// CHECK-PPC: [[CLD_IMAG:%.*]] = load ppc_fp128, ptr [[CLD_IMAGP:%.*]], align 16 -// CHECK-PPC: store ppc_fp128 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 16 -// CHECK-PPC: store ppc_fp128 [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 16 -// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @cargl(ptr noundef nonnull byval({ ppc_fp128, ppc_fp128 }) align 16 [[BYVAL_TEMP]]) #[[ATTR4]] -// CHECK-PPC: store ppc_fp128 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 16 -// CHECK-PPC: store ppc_fp128 [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 16 +// CHECK-PPC-CLANG22-LABEL: define dso_local void @test_cargl( +// CHECK-PPC-CLANG22-SAME: ptr dead_on_unwind noalias nofree writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr nofree noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-PPC-CLANG22: [[CLD_REAL:%.*]] = load ppc_fp128, ptr [[CLD]], align 16 +// CHECK-PPC-CLANG22: [[CLD_IMAG:%.*]] = load ppc_fp128, ptr [[CLD_IMAGP:%.*]], align 16 +// CHECK-PPC-CLANG22: store ppc_fp128 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 16 +// CHECK-PPC-CLANG22: store ppc_fp128 [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 16 +// CHECK-PPC-CLANG22: [[CALL:%.*]] = tail call ppc_fp128 @cargl(ptr noundef nonnull byval({ ppc_fp128, ppc_fp128 }) align 16 [[BYVAL_TEMP]]) #[[ATTR4]] +// CHECK-PPC-CLANG22: store ppc_fp128 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 16 +// CHECK-PPC-CLANG22: store ppc_fp128 [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 16 +// +// CHECK-PPC-CLANG23-LABEL: define dso_local [2 x i128] @test_cargl( +// CHECK-PPC-CLANG23-SAME: [2 x i128] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-PPC-CLANG23: [[CALL:%.*]] = tail call ppc_fp128 @cargl([2 x i128] noundef [[CLD_COERCE]]) #[[ATTR3]] // // CHECK-ARM-LABEL: define dso_local void @test_cargl( // CHECK-ARM-SAME: ptr dead_on_unwind noalias nofree writable writeonly sret({ double, double }) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]], [2 x i64] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { @@ -137,7 +146,7 @@ long double test_powl(long double a, long double b) { // CHECK-MINGW32: store x86_fp80 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 16 // CHECK-MINGW32: store x86_fp80 [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 16 // CHECK-MINGW32: call void @cargl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr noundef nonnull align 16 dead_on_return [[BYVAL_TEMP]]) #[[ATTR3]] -// CHECK-MINGW32: [[TMP0:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] +// CHECK-MINGW32: [[TMP0:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] // CHECK-MINGW32: [[CLD_REAL3:%.*]] = load x86_fp80, ptr [[CLD]], align 16 // CHECK-MINGW32: [[CLD_IMAG5:%.*]] = load x86_fp80, ptr [[CLD_IMAGP]], align 16 // CHECK-MINGW32: store x86_fp80 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 16 @@ -164,9 +173,13 @@ int ilogbl(long double a); // CHECK-I686-SAME: x86_fp80 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-I686: [[CALL:%.*]] = tail call i32 @ilogbl(x86_fp80 noundef [[A]]) #[[ATTR5]] // -// CHECK-PPC-LABEL: define dso_local i32 @test_ilogb( -// CHECK-PPC-SAME: ppc_fp128 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-PPC: [[CALL:%.*]] = tail call i32 @ilogbl(ppc_fp128 noundef [[A]]) #[[ATTR4]] +// CHECK-PPC-CLANG22-LABEL: define dso_local i32 @test_ilogb( +// CHECK-PPC-CLANG22-SAME: ppc_fp128 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-PPC-CLANG22: [[CALL:%.*]] = tail call i32 @ilogbl(ppc_fp128 noundef [[A]]) #[[ATTR4]] +// +// CHECK-PPC-CLANG23-LABEL: define dso_local i32 @test_ilogb( +// CHECK-PPC-CLANG23-SAME: ppc_fp128 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-PPC-CLANG23: [[CALL:%.*]] = tail call i32 @ilogbl(ppc_fp128 noundef [[A]]) #[[ATTR3]] // // CHECK-ARM-LABEL: define dso_local i32 @test_ilogb( // CHECK-ARM-SAME: double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { @@ -190,16 +203,16 @@ int ilogbl(long double a); // // CHECK-MINGW32-LABEL: define dso_local i32 @test_ilogb( // CHECK-MINGW32-SAME: ptr nofree noundef readonly align 16 captures(none) dead_on_return [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] -// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA9]] +// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] +// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[LONG_DOUBLE_TBAA10]] // CHECK-MINGW32: [[CALL:%.*]] = call i32 @ilogbl(ptr noundef nonnull align 16 dead_on_return [[BYVAL_TEMP]]) #[[ATTR3]] // int test_ilogb(long double a) { return ilogbl(a); } //. -// CHECK-MINGW32: [[META7:![0-9]+]] = !{!"omnipotent char", [[META8:![0-9]+]], i64 0} -// CHECK-MINGW32: [[META8]] = !{!"Simple C/C++ TBAA"} -// CHECK-MINGW32: [[LONG_DOUBLE_TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0} -// CHECK-MINGW32: [[META10]] = !{!"long double", [[META7]], i64 0} +// CHECK-MINGW32: [[META8:![0-9]+]] = !{!"omnipotent char", [[META9:![0-9]+]], i64 0} +// CHECK-MINGW32: [[META9]] = !{!"Simple C/C++ TBAA"} +// CHECK-MINGW32: [[LONG_DOUBLE_TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0} +// CHECK-MINGW32: [[META11]] = !{!"long double", [[META8]], i64 0} //. >From 4d77e949687162f76be8517455421ac860b258d5 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Mon, 3 Aug 2026 01:32:55 +0200 Subject: [PATCH 08/10] remove special-casing of _Complex ppcfp128, it is not needed --- clang/lib/CodeGen/Targets/PPC.cpp | 12 ++---------- clang/test/CodeGen/PowerPC/powerpc-c99complex.c | 10 +++++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 537ed33651044..1f11aa2bd5be2 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -442,20 +442,12 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { } ABIArgInfo PPC32_SVR4_ABIInfo::classifyComplexType(QualType Ty) const { + assert(Ty->isAnyComplexType() && "not a complex type"); + uint64_t Size = getContext().getTypeSize(Ty); llvm::LLVMContext &VMC = getVMContext(); llvm::Type *I32 = llvm::Type::getInt32Ty(VMC); - assert(Ty->isAnyComplexType() && "not a complex type"); - QualType ElemTy = Ty->castAs<ComplexType>()->getElementType(); - - // Work around https://github.com/llvm/llvm-project/issues/44482. - // This is a bug where the two halves of a ppc_fp128 are swapped. - // Using i128 for the ABI instead circumvents this issue. - if (CGT.ConvertType(ElemTy)->isPPC_FP128Ty()) - return ABIArgInfo::getDirect( - llvm::ArrayType::get(llvm::Type::getInt128Ty(VMC), 2)); - // Coerce to an integer for _Complex char and _Complex short. if (Size <= GPRBits) return ABIArgInfo::getDirect(llvm::IntegerType::get(VMC, Size)); diff --git a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c index b6b6832bce3df..10e10fbe38dc2 100644 --- a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c +++ b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c @@ -77,12 +77,12 @@ _Complex long double foo3(_Complex long double x) { // PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 // PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16 -// PPC32LNX-CLANG23-LABEL: define dso_local [2 x i128] @foo3( -// PPC32LNX-CLANG23-SAME: [2 x i128] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// PPC32LNX-CLANG23-LABEL: define dso_local [8 x i32] @foo3( +// PPC32LNX-CLANG23-SAME: [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { // PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] // PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 // PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 -// PPC32LNX-CLANG23-NEXT: store [2 x i128] [[X_COERCE]], ptr [[X]], align 16 +// PPC32LNX-CLANG23-NEXT: store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 // PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 // PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 // PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 @@ -91,6 +91,6 @@ _Complex long double foo3(_Complex long double x) { // PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 // PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 // PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 -// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [2 x i128], ptr [[RETVAL]], align 16 -// PPC32LNX-CLANG23-NEXT: ret [2 x i128] [[TMP0]] +// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// PPC32LNX-CLANG23-NEXT: ret [8 x i32] [[TMP0]] } >From c8fcec04f2d678d12c4de6818444f3304622ec3f Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Wed, 5 Aug 2026 11:10:17 +0200 Subject: [PATCH 09/10] update for LLVM 23 --- clang/lib/CodeGen/Targets/PPC.cpp | 2 +- .../test/CodeGen/PowerPC/powerpc-c99complex.c | 128 +++++++++--------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 1f11aa2bd5be2..888b7bb40aaa0 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -369,7 +369,7 @@ class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool isComplexGnuABI() const { return !getTarget().getTriple().isOSDarwin() && !getContext().getLangOpts().isCompatibleWith( - LangOptions::ClangABI::Ver22); + LangOptions::ClangABI::Ver23); } CharUnits getParamTypeAlignment(QualType Ty) const; diff --git a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c index 10e10fbe38dc2..b0b0224f70135 100644 --- a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c +++ b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c @@ -2,36 +2,36 @@ // RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-NOLDBL128,CHECK // RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-LDBL128,CHECK // RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-LDBL128,CHECK -// RUN: %clang_cc1 -triple powerpc-unknown-linux -fclang-abi-compat=22 -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX-CLANG22 // RUN: %clang_cc1 -triple powerpc-unknown-linux -fclang-abi-compat=23 -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX-CLANG23 +// RUN: %clang_cc1 -triple powerpc-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX _Complex float foo1(_Complex float x) { return x; // CHECK-LABEL: define{{.*}} { float, float } @foo1(float noundef %x.{{.*}}, float noundef %x.{{.*}}) #0 { // CHECK: ret { float, float } -// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { -// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-CLANG22-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4 -// PPC32LNX-CLANG22-NEXT: store float %{{.*}}, ptr [[RETIMAG]], align 4 +// PPC32LNX-CLANG23-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { +// PPC32LNX-CLANG23: [[RETREAL:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { float, float }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4 +// PPC32LNX-CLANG23-NEXT: store float %{{.*}}, ptr [[RETIMAG]], align 4 -// PPC32LNX-CLANG23-LABEL: define dso_local <2 x i32> @foo1( -// PPC32LNX-CLANG23-SAME: <2 x i32> noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { -// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] -// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 -// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { float, float }, align 4 -// PPC32LNX-CLANG23-NEXT: store <2 x i32> [[X_COERCE]], ptr [[X]], align 4 -// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 -// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: store float [[X_REAL]], ptr [[RETVAL_REALP]], align 4 -// PPC32LNX-CLANG23-NEXT: store float [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 4 -// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 4 -// PPC32LNX-CLANG23-NEXT: ret <2 x i32> [[TMP0]] +// PPC32LNX-LABEL: define dso_local <2 x i32> @foo1( +// PPC32LNX-SAME: <2 x i32> noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PPC32LNX-NEXT: [[ENTRY:.*:]] +// PPC32LNX-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PPC32LNX-NEXT: [[X:%.*]] = alloca { float, float }, align 4 +// PPC32LNX-NEXT: store <2 x i32> [[X_COERCE]], ptr [[X]], align 4 +// PPC32LNX-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// PPC32LNX-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// PPC32LNX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-NEXT: store float [[X_REAL]], ptr [[RETVAL_REALP]], align 4 +// PPC32LNX-NEXT: store float [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// PPC32LNX-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 4 +// PPC32LNX-NEXT: ret <2 x i32> [[TMP0]] } _Complex double foo2(_Complex double x) { @@ -39,28 +39,28 @@ _Complex double foo2(_Complex double x) { // CHECK-LABEL: define{{.*}} { double, double } @foo2(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 { // CHECK: ret { double, double } -// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { -// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-CLANG22-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8 -// PPC32LNX-CLANG22-NEXT: store double %{{.*}}, ptr [[RETIMAG]], align 8 +// PPC32LNX-CLANG23-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { +// PPC32LNX-CLANG23: [[RETREAL:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { double, double }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8 +// PPC32LNX-CLANG23-NEXT: store double %{{.*}}, ptr [[RETIMAG]], align 8 -// PPC32LNX-CLANG23-LABEL: define dso_local [4 x i32] @foo2( -// PPC32LNX-CLANG23-SAME: [4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { -// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] -// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 -// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { double, double }, align 8 -// PPC32LNX-CLANG23-NEXT: store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 -// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 -// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 -// PPC32LNX-CLANG23-NEXT: store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 -// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 -// PPC32LNX-CLANG23-NEXT: ret [4 x i32] [[TMP0]] +// PPC32LNX-LABEL: define dso_local [4 x i32] @foo2( +// PPC32LNX-SAME: [4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// PPC32LNX-NEXT: [[ENTRY:.*:]] +// PPC32LNX-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PPC32LNX-NEXT: [[X:%.*]] = alloca { double, double }, align 8 +// PPC32LNX-NEXT: store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// PPC32LNX-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// PPC32LNX-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// PPC32LNX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-NEXT: store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// PPC32LNX-NEXT: store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// PPC32LNX-NEXT: [[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// PPC32LNX-NEXT: ret [4 x i32] [[TMP0]] } _Complex long double foo3(_Complex long double x) { @@ -71,26 +71,26 @@ _Complex long double foo3(_Complex long double x) { // CHECK-LDBL128-LABEL: define{{.*}} { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 noundef %x.{{.*}}, ppc_fp128 noundef %x.{{.*}}) #0 { // CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 } -// PPC32LNX-CLANG22-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { -// PPC32LNX-CLANG22: [[RETREAL:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0 -// PPC32LNX-CLANG22-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1 -// PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 -// PPC32LNX-CLANG22-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16 +// PPC32LNX-CLANG23-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { +// PPC32LNX-CLANG23: [[RETREAL:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0 +// PPC32LNX-CLANG23-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1 +// PPC32LNX-CLANG23-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 +// PPC32LNX-CLANG23-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16 -// PPC32LNX-CLANG23-LABEL: define dso_local [8 x i32] @foo3( -// PPC32LNX-CLANG23-SAME: [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { -// PPC32LNX-CLANG23-NEXT: [[ENTRY:.*:]] -// PPC32LNX-CLANG23-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 -// PPC32LNX-CLANG23-NEXT: [[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 -// PPC32LNX-CLANG23-NEXT: store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 -// PPC32LNX-CLANG23-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 -// PPC32LNX-CLANG23-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: [[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 -// PPC32LNX-CLANG23-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 -// PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 -// PPC32LNX-CLANG23-NEXT: store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 -// PPC32LNX-CLANG23-NEXT: [[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 -// PPC32LNX-CLANG23-NEXT: ret [8 x i32] [[TMP0]] +// PPC32LNX-LABEL: define dso_local [8 x i32] @foo3( +// PPC32LNX-SAME: [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// PPC32LNX-NEXT: [[ENTRY:.*:]] +// PPC32LNX-NEXT: [[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// PPC32LNX-NEXT: [[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// PPC32LNX-NEXT: store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// PPC32LNX-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// PPC32LNX-NEXT: [[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// PPC32LNX-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// PPC32LNX-NEXT: [[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// PPC32LNX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// PPC32LNX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// PPC32LNX-NEXT: store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// PPC32LNX-NEXT: store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// PPC32LNX-NEXT: [[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// PPC32LNX-NEXT: ret [8 x i32] [[TMP0]] } >From b35bb13a05fa691ffa759f3bc1743167aec2f541 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Wed, 5 Aug 2026 11:10:48 +0200 Subject: [PATCH 10/10] add to release notes and abiversions --- clang/docs/ReleaseNotes.md | 3 +++ clang/include/clang/Basic/ABIVersions.def | 1 + 2 files changed, 4 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 7108392abbaa1..6aaa8b5687592 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -74,6 +74,9 @@ features cannot lower the translation-unit ABI level; always passed the parts separately. `-fclang-abi-compat=23` restores the previous behavior. (#GH212109) +- On PowerPC (32-bit), the ABI of `_Complex` now matches GCC. + `-fclang-abi-compat=23` restores the previous behavior. (#GH208917) + ### AST Dumping Potentially Breaking Changes ### Clang Frontend Potentially Breaking Changes diff --git a/clang/include/clang/Basic/ABIVersions.def b/clang/include/clang/Basic/ABIVersions.def index 42ee3c3b5f210..6d07f551d9461 100644 --- a/clang/include/clang/Basic/ABIVersions.def +++ b/clang/include/clang/Basic/ABIVersions.def @@ -155,6 +155,7 @@ ABI_VER_MAJOR(22) /// - On MIPS N32/N64, always pass a `_Complex float` or `_Complex double` /// argument as its two parts, one floating-point register each, instead of /// packing it into integer registers once there is no room for both. +/// - On PowerPC (32-bit), treat `_Complex` like a struct of two scalar fields. ABI_VER_MAJOR(23) /// Conform to the underlying platform's C and C++ ABIs as closely as we can. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
