[clang] 56bb311 - [MIPS] don't pass variadic arguments in float registers (#216519)

via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 19 04:53:25 PDT 2026


Author: Folkert de Vries
Date: 2026-08-19T13:53:19+02:00
New Revision: 56bb31141fe72e996d8c7babaf04136fa72bfc5d

URL: https://github.com/llvm/llvm-project/commit/56bb31141fe72e996d8c7babaf04136fa72bfc5d
DIFF: https://github.com/llvm/llvm-project/commit/56bb31141fe72e996d8c7babaf04136fa72bfc5d.diff

LOG: [MIPS] don't pass variadic arguments in float registers (#216519)

At least, I think that's what is going on here. Really it doesn't make
sense to use `inreg` float parameters here. Apparently the backend can
handle it on smaller floats but `_Complex long double` hits some edge
case and miscompiles.

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. The behavior of this PR
matches GCC.

cc https://github.com/llvm/llvm-project/pull/216509

Added: 
    

Modified: 
    clang/lib/CodeGen/Targets/Mips.cpp
    clang/test/CodeGen/Mips/variadic-aggregate.c

Removed: 
    


################################################################################
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) {


        


More information about the cfe-commits mailing list