https://github.com/folkertdev created https://github.com/llvm/llvm-project/pull/216519
At least, I think that's what is going on here https://godbolt.org/z/nqTM46Ej5 ```c extern void sink(int, ...); void variadic_cld(_Complex long double z) { sink(0, z); } ``` Clang only sets up register 4 for the `int`, I think with the assumption that the `f128` arguments are already in the right place: ```asm variadic_cld: .Lfunc_begin0 = .Ltmp0 daddiu $sp, $sp, -16 sd $ra, 8($sp) sd $gp, 0($sp) lui $1, %hi(%neg(%gp_rel(variadic_cld))) daddu $1, $1, $25 daddiu $gp, $1, %lo(%neg(%gp_rel(variadic_cld))) ld $25, %call16(sink)($gp) jalr $25 daddiu $4, $zero, 0 ld $gp, 0($sp) ld $ra, 8($sp) jr $ra daddiu $sp, $sp, 16 ``` Contrast this with GCC ```asm variadic_cld: daddiu $sp,$sp,-16 sd $31,8($sp) sd $28,0($sp) lui $28,%hi(%neg(%gp_rel(variadic_cld))) daddu $28,$28,$25 daddiu $28,$28,%lo(%neg(%gp_rel(variadic_cld))) dmfc1 $5,$f13 dmfc1 $4,$f12 dmfc1 $3,$f15 dmfc1 $2,$f14 move $7,$5 move $6,$4 move $9,$3 move $8,$2 ld $25,%call16(sink)($28) 1: jalr $25 move $4,$0 ld $31,8($sp) ld $28,0($sp) jr $31 daddiu $sp,$sp,16 ``` Which actually loads from the FPRs into GPRs. >From 92be676aeda8831bb51d556274c9bc1844db3adb Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sun, 16 Aug 2026 01:10:56 +0200 Subject: [PATCH] [MIPS]: don't pass variadic arguments in float registers --- clang/lib/CodeGen/Targets/Mips.cpp | 19 ++-- clang/test/CodeGen/Mips/variadic-aggregate.c | 96 +++++++++++--------- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp index 220bdcb5886f8..6286e309dab22 100644 --- a/clang/lib/CodeGen/Targets/Mips.cpp +++ b/clang/lib/CodeGen/Targets/Mips.cpp @@ -45,7 +45,8 @@ class MipsABIInfo : public ABIInfo { StackAlignInBytes(IsO32 ? 8 : 16) {} ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const; + ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset, + bool IsNamedArg) const; void computeInfo(CGFunctionInfo &FI) const override; RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override; @@ -227,8 +228,8 @@ llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset, return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8); } -ABIArgInfo -MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { +ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset, + bool IsNamedArg) const { Ty = useFirstFieldIfTransparentUnion(Ty); uint64_t OrigOffset = Offset; @@ -241,13 +242,14 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8; // Only pass _Complex float and _Complex double in FPRs when there are 2 free - // slots, otherwise use GPRs (or the stack). + // slots, and it's not a variadic argument otherwise use GPRs (or the stack). // // _Complex long double never uses GPRs. Its parts are an FPR pair each, // so passing them as they are puts each part in a pair and spills to // the stack the parts that don't fit. - bool ComplexFitsInFPRs = true; - if (!IsO32 && Ty->isComplexType() && isComplexGnuABI() && TySize < 256) { + bool ComplexFitsInFPRs = IsNamedArg; + if (!IsO32 && IsNamedArg && Ty->isComplexType() && isComplexGnuABI() && + TySize < 256) { unsigned NumArgSlots = 8; uint64_t SlotsUsed = CurrOffset / MinABIStackAlignInBytes; if (SlotsUsed + 2 <= NumArgSlots) @@ -424,8 +426,9 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const { // Zero-sized arguments are not passed, but do end the run of floats. bool SawZeroSizedArg = false; - for (auto &I : FI.arguments()) { - I.info = classifyArgumentType(I.type, Offset); + for (auto [ArgNo, I] : llvm::enumerate(FI.arguments())) { + bool IsNamedArg = ArgNo < FI.getNumRequiredArgs(); + I.info = classifyArgumentType(I.type, Offset, IsNamedArg); // N32 and N64 always pass floating points in float registers. if (!IsO32) diff --git a/clang/test/CodeGen/Mips/variadic-aggregate.c b/clang/test/CodeGen/Mips/variadic-aggregate.c index 4c72dcb639c1a..8047f78f37501 100644 --- a/clang/test/CodeGen/Mips/variadic-aggregate.c +++ b/clang/test/CodeGen/Mips/variadic-aggregate.c @@ -1181,11 +1181,9 @@ void test_long_long_long_long(va_list *ap) { // GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // GPR64N32-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4 // GPR64N32-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 -// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N32-NEXT: [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4 -// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N32-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP3]], align 4 -// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, float inreg noundef [[TMP2]], float inreg noundef [[TMP4]]) +// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 +// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]]) // GPR64N32-NEXT: ret void // // GPR64N64BE-LABEL: define dso_local void @test_complex_float( @@ -1215,11 +1213,9 @@ void test_long_long_long_long(va_list *ap) { // GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64BE-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4 // GPR64N64BE-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 -// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64BE-NEXT: [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4 -// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64BE-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP3]], align 4 -// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, float inreg noundef [[TMP2]], float inreg noundef [[TMP4]]) +// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 +// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]]) // GPR64N64BE-NEXT: ret void // // GPR64N64LE-LABEL: define dso_local void @test_complex_float( @@ -1249,11 +1245,9 @@ void test_long_long_long_long(va_list *ap) { // GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64LE-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4 // GPR64N64LE-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 -// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64LE-NEXT: [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4 -// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64LE-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP3]], align 4 -// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, float inreg noundef [[TMP2]], float inreg noundef [[TMP4]]) +// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 +// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]]) // GPR64N64LE-NEXT: ret void // void test_complex_float(va_list *ap) { @@ -1399,11 +1393,11 @@ void test_float_float(va_list *ap) { // GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 // GPR64N32-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8 // GPR64N32-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 -// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N32-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 -// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N32-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8 -// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg noundef [[TMP2]], double inreg noundef [[TMP4]]) +// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 +// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]]) // GPR64N32-NEXT: ret void // // GPR64N64BE-LABEL: define dso_local void @test_complex_double( @@ -1433,11 +1427,11 @@ void test_float_float(va_list *ap) { // GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64BE-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8 // GPR64N64BE-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 -// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64BE-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 -// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64BE-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8 -// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg noundef [[TMP2]], double inreg noundef [[TMP4]]) +// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 +// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]]) // GPR64N64BE-NEXT: ret void // // GPR64N64LE-LABEL: define dso_local void @test_complex_double( @@ -1467,11 +1461,11 @@ void test_float_float(va_list *ap) { // GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64LE-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8 // GPR64N64LE-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 -// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64LE-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 -// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64LE-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8 -// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg noundef [[TMP2]], double inreg noundef [[TMP4]]) +// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 +// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]]) // GPR64N64LE-NEXT: ret void // void test_complex_double(va_list *ap) { @@ -1631,11 +1625,15 @@ void test_double_double(va_list *ap) { // GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 // GPR64N32-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16 // GPR64N32-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16 -// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N32-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP2]], align 16 -// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N32-NEXT: [[TMP5:%.*]] = load fp128, ptr [[TMP4]], align 16 -// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, fp128 inreg noundef [[TMP3]], fp128 inreg noundef [[TMP5]]) +// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N32-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16 +// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N32-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 +// GPR64N32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2 +// GPR64N32-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16 +// GPR64N32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3 +// GPR64N32-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]]) // GPR64N32-NEXT: ret void // // GPR64N64BE-LABEL: define dso_local void @test_complex_long_double( @@ -1667,11 +1665,15 @@ void test_double_double(va_list *ap) { // GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64BE-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16 // GPR64N64BE-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16 -// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64BE-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP2]], align 16 -// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64BE-NEXT: [[TMP5:%.*]] = load fp128, ptr [[TMP4]], align 16 -// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, fp128 inreg noundef [[TMP3]], fp128 inreg noundef [[TMP5]]) +// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64BE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16 +// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N64BE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 +// GPR64N64BE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2 +// GPR64N64BE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16 +// GPR64N64BE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3 +// GPR64N64BE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]]) // GPR64N64BE-NEXT: ret void // // GPR64N64LE-LABEL: define dso_local void @test_complex_long_double( @@ -1703,11 +1705,15 @@ void test_double_double(va_list *ap) { // GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 // GPR64N64LE-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16 // GPR64N64LE-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16 -// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0 -// GPR64N64LE-NEXT: [[TMP3:%.*]] = load fp128, ptr [[TMP2]], align 16 -// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1 -// GPR64N64LE-NEXT: [[TMP5:%.*]] = load fp128, ptr [[TMP4]], align 16 -// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, fp128 inreg noundef [[TMP3]], fp128 inreg noundef [[TMP5]]) +// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0 +// GPR64N64LE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16 +// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1 +// GPR64N64LE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 +// GPR64N64LE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2 +// GPR64N64LE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16 +// GPR64N64LE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3 +// GPR64N64LE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]]) // GPR64N64LE-NEXT: ret void // void test_complex_long_double(va_list *ap) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
