diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -4630,14 +4630,45 @@ Address AIXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const { - if (Ty->isAnyComplexType()) - llvm::report_fatal_error("complex type is not supported on AIX yet"); - auto TypeInfo = getContext().getTypeInfoInChars(Ty); TypeInfo.Align = getParamTypeAlignment(Ty); CharUnits SlotSize = CharUnits::fromQuantity(PtrByteSize); + // If we have a complex type and the base type is smaller than the register + // size, the ABI calls for the real and imaginary parts to be right-adjusted + // in separate words in 32bit mode or doublewords in 64bit mode. However, + // Clang expects us to produce a pointer to a structure with the two parts + // packed tightly. So generate loads of the real and imaginary parts relative + // to the va_list pointer, and store them to a temporary structure. We do the + // same as the PPC64ABI here. + if (const ComplexType *CTy = Ty->getAs()) { + CharUnits EltSize = TypeInfo.Width / 2; + if (EltSize < SlotSize) { + Address Addr = + emitVoidPtrDirectVAArg(CGF, VAListAddr, CGF.Int8Ty, SlotSize * 2, + SlotSize, SlotSize, /*AllowHigher*/ true); + + Address RealAddr = Addr; + Address ImagAddr = RealAddr; + RealAddr = + CGF.Builder.CreateConstInBoundsByteGEP(RealAddr, SlotSize - EltSize); + ImagAddr = CGF.Builder.CreateConstInBoundsByteGEP(ImagAddr, + 2 * SlotSize - EltSize); + + llvm::Type *EltTy = CGF.ConvertTypeForMem(CTy->getElementType()); + RealAddr = CGF.Builder.CreateElementBitCast(RealAddr, EltTy); + ImagAddr = CGF.Builder.CreateElementBitCast(ImagAddr, EltTy); + llvm::Value *Real = CGF.Builder.CreateLoad(RealAddr, ".vareal"); + llvm::Value *Imag = CGF.Builder.CreateLoad(ImagAddr, ".vaimag"); + + Address Temp = CGF.CreateMemTemp(Ty, "vacplx"); + CGF.EmitStoreOfComplex({Real, Imag}, CGF.MakeAddrLValue(Temp, Ty), + /*init*/ true); + return Temp; + } + } + // Otherwise, just use the general rule. return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect*/ false, TypeInfo, SlotSize, /*AllowHigher*/ true); } diff --git a/clang/test/CodeGen/aix32-complex-varargs.c b/clang/test/CodeGen/aix32-complex-varargs.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix32-complex-varargs.c @@ -0,0 +1,66 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s + +#include + +void testva (int n, ...) +{ + va_list ap; + + _Complex int i = va_arg(ap, _Complex int); +// CHECK: %[[VAR40:[A-Za-z0-9.]+]] = load i8*, i8** %[[VAR100:[A-Za-z0-9.]+]] +// CHECK-NEXT: %[[VAR41:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR40]] +// CHECK-NEXT: store i8* %[[VAR41]], i8** %[[VAR100]], align 4 +// CHECK-NEXT: %[[VAR4:[A-Za-z0-9.]+]] = bitcast i8* %[[VAR40]] to { i32, i32 }* +// CHECK-NEXT: %[[VAR6:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* %[[VAR4]], i32 0, i32 0 +// CHECK-NEXT: %[[VAR7:[A-Za-z0-9.]+]] = load i32, i32* %[[VAR6]] +// CHECK-NEXT: %[[VAR8:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* %[[VAR4]], i32 0, i32 1 +// CHECK-NEXT: %[[VAR9:[A-Za-z0-9.]+]] = load i32, i32* %[[VAR8]] +// CHECK-NEXT: %[[VAR10:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* %[[VARINT:[A-Za-z0-9.]+]], i32 0, i32 0 +// CHECK-NEXT: %[[VAR11:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* %[[VARINT]], i32 0, i32 1 +// CHECK-NEXT: store i32 %[[VAR7]], i32* %[[VAR10]] +// CHECK-NEXT: store i32 %[[VAR9]], i32* %[[VAR11]] + + _Complex short s = va_arg(ap, _Complex short); +// CHECK: %[[VAR50:[A-Za-z0-9.]+]] = load i8*, i8** %[[VAR100:[A-Za-z0-9.]+]] +// CHECK-NEXT: %[[VAR51:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR50]] +// CHECK-NEXT: store i8* %[[VAR51]], i8** %[[VAR100]], align 4 +// CHECK-NEXT: %[[VAR12:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR50]], i32 2 +// CHECK-NEXT: %[[VAR13:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR50]], i32 6 +// CHECK-NEXT: %[[VAR14:[A-Za-z0-9.]+]] = bitcast i8* %[[VAR12]] to i16* +// CHECK-NEXT: %[[VAR15:[A-Za-z0-9.]+]] = bitcast i8* %[[VAR13]] to i16* +// CHECK-NEXT: %[[VAR16:[A-Za-z0-9.]+]] = load i16, i16* %[[VAR14]], align 2 +// CHECK-NEXT: %[[VAR17:[A-Za-z0-9.]+]] = load i16, i16* %[[VAR15]], align 2 +// CHECK-NEXT: %[[VAR18:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }, { i16, i16 }* %[[VAR19:[A-Za-z0-9.]+]], i32 0, i32 0 +// CHECK-NEXT: %[[VAR20:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }, { i16, i16 }* %[[VAR19]], i32 0, i32 1 +// CHECK-NEXT: store i16 %[[VAR16]], i16* %[[VAR18]] +// CHECK-NEXT: store i16 %[[VAR17]], i16* %[[VAR20]] + + + _Complex char c = va_arg(ap, _Complex char); +// CHECK: %[[VAR60:[A-Za-z0-9.]+]] = load i8*, i8** %[[VAR100:[A-Za-z0-9.]+]] +// CHECK-NEXT: %[[VAR61:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR60]] +// CHECK-NEXT: store i8* %[[VAR61]], i8** %[[VAR100]], align 4 +// CHECK-NEXT: %[[VAR21:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR60]], i32 3 +// CHECK-NEXT: %[[VAR22:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR60]], i32 7 +// CHECK-NEXT: %[[VAR23:[A-Za-z0-9.]+]] = load i8, i8* %[[VAR21]] +// CHECK-NEXT: %[[VAR24:[A-Za-z0-9.]+]] = load i8, i8* %[[VAR22]] +// CHECK-NEXT: %[[VAR25:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }, { i8, i8 }* %[[VAR26:[A-Za-z0-9.]+]], i32 0, i32 0 +// CHECK-NEXT: %[[VAR27:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }, { i8, i8 }* %[[VAR26]], i32 0, i32 1 +// CHECK-NEXT: store i8 %[[VAR23]], i8* %[[VAR25]] +// CHECK-NEXT: store i8 %[[VAR24]], i8* %[[VAR27]] + + + _Complex float f = va_arg(ap, _Complex float); +// CHECK: %[[VAR70:[A-Za-z0-9.]+]] = getelementptr inbounds i8, i8* %[[VAR71:[A-Za-z0-9.]+]], i32 8 +// CHECK-NEXT: store i8* %[[VAR70]], i8** %[[VAR100:[A-Za-z0-9.]+]] +// CHECK-NEXT: %[[VAR28:[A-Za-z0-9.]+]] = bitcast i8* %[[VAR71]] to { float, float }* +// CHECK-NEXT: %[[VAR29:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }, { float, float }* %[[VAR28]], i32 0, i32 0 +// CHECK-NEXT: %[[VAR30:[A-Za-z0-9.]+]] = load float, float* %[[VAR29]] +// CHECK-NEXT: %[[VAR31:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }, { float, float }* %[[VAR28]], i32 0, i32 1 +// CHECK-NEXT: %[[VAR32:[A-Za-z0-9.]+]] = load float, float* %[[VAR31]] +// CHECK-NEXT: %[[VAR33:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }, { float, float }* %f, i32 0, i32 0 +// CHECK-NEXT: %[[VAR34:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }, { float, float }* %f, i32 0, i32 1 +// CHECK-NEXT: store float %[[VAR30]], float* %[[VAR33]] +// CHECK-NEXT: store float %[[VAR32]], float* %[[VAR34]] +} diff --git a/clang/test/CodeGen/ppc64-varargs-complex.c b/clang/test/CodeGen/ppc64-varargs-complex.c --- a/clang/test/CodeGen/ppc64-varargs-complex.c +++ b/clang/test/CodeGen/ppc64-varargs-complex.c @@ -1,5 +1,6 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s #include diff --git a/llvm/test/CodeGen/PowerPC/aix32-complex-vararg.ll b/llvm/test/CodeGen/PowerPC/aix32-complex-vararg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix32-complex-vararg.ll @@ -0,0 +1,503 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec \ +; RUN: -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=32BIT %s + +@cdbl = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl1 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl2 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl3 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cflt = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt1 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt2 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt3 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cldbl = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl1 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl2 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl3 = local_unnamed_addr global { double, double } zeroinitializer, align 8 + +define { double, double } @foo1(double %x.coerce0, double %x.coerce1, ...) local_unnamed_addr { +; 32BIT-LABEL: foo1: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: lwz 3, L..C0(2) # %const.0 +; 32BIT-NEXT: stw 7, 40(1) +; 32BIT-NEXT: stw 8, 44(1) +; 32BIT-NEXT: stw 9, 48(1) +; 32BIT-NEXT: stw 10, 52(1) +; 32BIT-NEXT: lfd 4, 40(1) +; 32BIT-NEXT: lfd 5, 48(1) +; 32BIT-NEXT: lfs 0, 0(3) +; 32BIT-NEXT: fadd 3, 1, 0 +; 32BIT-NEXT: fadd 0, 2, 0 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 56(1) +; 32BIT-NEXT: lfd 5, 64(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 72(1) +; 32BIT-NEXT: lfd 5, 80(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 88(1) +; 32BIT-NEXT: lfd 5, 96(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: fadd 1, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: lfd 2, 104(1) +; 32BIT-NEXT: lfd 3, 112(1) +; 32BIT-NEXT: fadd 1, 1, 2 +; 32BIT-NEXT: fadd 2, 0, 3 +; 32BIT-NEXT: blr +entry: + %arg = alloca i8*, align 4 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %arg.promoted = load i8*, i8** %arg, align 4 + %add.r = fadd double %x.coerce0, 0.000000e+00 + %add.i = fadd double %x.coerce1, 0.000000e+00 + %argp.next = getelementptr inbounds i8, i8* %arg.promoted, i32 16 + %.realp = bitcast i8* %arg.promoted to double* + %.real = load double, double* %.realp, align 4 + %.imagp = getelementptr inbounds i8, i8* %arg.promoted, i32 8 + %1 = bitcast i8* %.imagp to double* + %.imag = load double, double* %1, align 4 + %add.r4 = fadd double %add.r, %.real + %add.i5 = fadd double %add.i, %.imag + %add.r.1 = fadd double %add.r4, %x.coerce0 + %add.i.1 = fadd double %add.i5, %x.coerce1 + %argp.next.1 = getelementptr inbounds i8, i8* %arg.promoted, i32 32 + %.realp.1 = bitcast i8* %argp.next to double* + %.real.1 = load double, double* %.realp.1, align 4 + %.imagp.1 = getelementptr inbounds i8, i8* %arg.promoted, i32 24 + %2 = bitcast i8* %.imagp.1 to double* + %.imag.1 = load double, double* %2, align 4 + %add.r4.1 = fadd double %add.r.1, %.real.1 + %add.i5.1 = fadd double %add.i.1, %.imag.1 + %add.r.2 = fadd double %add.r4.1, %x.coerce0 + %add.i.2 = fadd double %add.i5.1, %x.coerce1 + %argp.next.2 = getelementptr inbounds i8, i8* %arg.promoted, i32 48 + %.realp.2 = bitcast i8* %argp.next.1 to double* + %.real.2 = load double, double* %.realp.2, align 4 + %.imagp.2 = getelementptr inbounds i8, i8* %arg.promoted, i32 40 + %3 = bitcast i8* %.imagp.2 to double* + %.imag.2 = load double, double* %3, align 4 + %add.r4.2 = fadd double %add.r.2, %.real.2 + %add.i5.2 = fadd double %add.i.2, %.imag.2 + %add.r.3 = fadd double %add.r4.2, %x.coerce0 + %add.i.3 = fadd double %add.i5.2, %x.coerce1 + %argp.next.3 = getelementptr inbounds i8, i8* %arg.promoted, i32 64 + %.realp.3 = bitcast i8* %argp.next.2 to double* + %.real.3 = load double, double* %.realp.3, align 4 + %.imagp.3 = getelementptr inbounds i8, i8* %arg.promoted, i32 56 + %4 = bitcast i8* %.imagp.3 to double* + %.imag.3 = load double, double* %4, align 4 + %add.r4.3 = fadd double %add.r.3, %.real.3 + %add.i5.3 = fadd double %add.i.3, %.imag.3 + %add.r.4 = fadd double %add.r4.3, %x.coerce0 + %add.i.4 = fadd double %add.i5.3, %x.coerce1 + %.realp.4 = bitcast i8* %argp.next.3 to double* + %.real.4 = load double, double* %.realp.4, align 4 + %.imagp.4 = getelementptr inbounds i8, i8* %arg.promoted, i32 72 + %5 = bitcast i8* %.imagp.4 to double* + %.imag.4 = load double, double* %5, align 4 + %add.r4.4 = fadd double %add.r.4, %.real.4 + %add.i5.4 = fadd double %add.i.4, %.imag.4 + %scevgep = getelementptr i8, i8* %arg.promoted, i32 80 + store i8* %scevgep, i8** %arg, align 4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) + %.fca.0.insert = insertvalue { double, double } undef, double %add.r4.4, 0 + %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i5.4, 1 + ret { double, double } %.fca.1.insert +} + +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) + +declare void @llvm.va_start(i8*) + +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) + +declare void @llvm.va_end(i8*) + +define { float, float } @foo2(float %x.coerce0, float %x.coerce1, ...) local_unnamed_addr { +; 32BIT-LABEL: foo2: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: lwz 3, L..C1(2) # %const.0 +; 32BIT-NEXT: stw 5, 32(1) +; 32BIT-NEXT: stw 6, 36(1) +; 32BIT-NEXT: lfs 4, 32(1) +; 32BIT-NEXT: lfs 5, 36(1) +; 32BIT-NEXT: stw 7, 40(1) +; 32BIT-NEXT: stw 8, 44(1) +; 32BIT-NEXT: lfs 0, 0(3) +; 32BIT-NEXT: stw 9, 48(1) +; 32BIT-NEXT: addi 3, 1, 32 +; 32BIT-NEXT: stw 10, 52(1) +; 32BIT-NEXT: fadds 3, 1, 0 +; 32BIT-NEXT: fadds 0, 2, 0 +; 32BIT-NEXT: fadds 3, 3, 4 +; 32BIT-NEXT: fadds 0, 0, 5 +; 32BIT-NEXT: lfsu 4, 8(3) +; 32BIT-NEXT: lfs 5, 44(1) +; 32BIT-NEXT: fadds 3, 3, 1 +; 32BIT-NEXT: fadds 0, 0, 2 +; 32BIT-NEXT: fadds 3, 3, 4 +; 32BIT-NEXT: fadds 0, 0, 5 +; 32BIT-NEXT: lfs 4, 48(1) +; 32BIT-NEXT: lfs 5, 52(1) +; 32BIT-NEXT: fadds 3, 3, 1 +; 32BIT-NEXT: fadds 0, 0, 2 +; 32BIT-NEXT: fadds 3, 3, 4 +; 32BIT-NEXT: fadds 0, 0, 5 +; 32BIT-NEXT: lfs 4, 56(1) +; 32BIT-NEXT: lfs 5, 60(1) +; 32BIT-NEXT: fadds 3, 3, 1 +; 32BIT-NEXT: fadds 0, 0, 2 +; 32BIT-NEXT: fadds 3, 3, 4 +; 32BIT-NEXT: fadds 0, 0, 5 +; 32BIT-NEXT: fadds 1, 3, 1 +; 32BIT-NEXT: fadds 0, 0, 2 +; 32BIT-NEXT: lfs 2, 64(1) +; 32BIT-NEXT: lfs 3, 68(1) +; 32BIT-NEXT: fadds 1, 1, 2 +; 32BIT-NEXT: fadds 2, 0, 3 +; 32BIT-NEXT: blr +entry: + %arg = alloca i8*, align 4 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %add.r = fadd float %x.coerce0, 0.000000e+00 + %add.i = fadd float %x.coerce1, 0.000000e+00 + %argp.cur = load i8*, i8** %arg, align 4 + %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 8 + store i8* %argp.next, i8** %arg, align 4 + %.realp = bitcast i8* %argp.cur to float* + %.real = load float, float* %.realp, align 4 + %.imagp = getelementptr inbounds i8, i8* %argp.cur, i32 4 + %1 = bitcast i8* %.imagp to float* + %.imag = load float, float* %1, align 4 + %add.r4 = fadd float %add.r, %.real + %add.i5 = fadd float %add.i, %.imag + %add.r.1 = fadd float %add.r4, %x.coerce0 + %add.i.1 = fadd float %add.i5, %x.coerce1 + %argp.next.1 = getelementptr inbounds i8, i8* %argp.cur, i32 16 + %.realp.1 = bitcast i8* %argp.next to float* + %.real.1 = load float, float* %.realp.1, align 4 + %.imagp.1 = getelementptr inbounds i8, i8* %argp.cur, i32 12 + %2 = bitcast i8* %.imagp.1 to float* + %.imag.1 = load float, float* %2, align 4 + %add.r4.1 = fadd float %add.r.1, %.real.1 + %add.i5.1 = fadd float %add.i.1, %.imag.1 + %add.r.2 = fadd float %add.r4.1, %x.coerce0 + %add.i.2 = fadd float %add.i5.1, %x.coerce1 + %argp.next.2 = getelementptr inbounds i8, i8* %argp.cur, i32 24 + %.realp.2 = bitcast i8* %argp.next.1 to float* + %.real.2 = load float, float* %.realp.2, align 4 + %.imagp.2 = getelementptr inbounds i8, i8* %argp.cur, i32 20 + %3 = bitcast i8* %.imagp.2 to float* + %.imag.2 = load float, float* %3, align 4 + %add.r4.2 = fadd float %add.r.2, %.real.2 + %add.i5.2 = fadd float %add.i.2, %.imag.2 + %add.r.3 = fadd float %add.r4.2, %x.coerce0 + %add.i.3 = fadd float %add.i5.2, %x.coerce1 + %argp.next.3 = getelementptr inbounds i8, i8* %argp.cur, i32 32 + %.realp.3 = bitcast i8* %argp.next.2 to float* + %.real.3 = load float, float* %.realp.3, align 4 + %.imagp.3 = getelementptr inbounds i8, i8* %argp.cur, i32 28 + %4 = bitcast i8* %.imagp.3 to float* + %.imag.3 = load float, float* %4, align 4 + %add.r4.3 = fadd float %add.r.3, %.real.3 + %add.i5.3 = fadd float %add.i.3, %.imag.3 + %add.r.4 = fadd float %add.r4.3, %x.coerce0 + %add.i.4 = fadd float %add.i5.3, %x.coerce1 + %argp.next.4 = getelementptr inbounds i8, i8* %argp.cur, i32 40 + store i8* %argp.next.4, i8** %arg, align 4 + %.realp.4 = bitcast i8* %argp.next.3 to float* + %.real.4 = load float, float* %.realp.4, align 4 + %.imagp.4 = getelementptr inbounds i8, i8* %argp.cur, i32 36 + %5 = bitcast i8* %.imagp.4 to float* + %.imag.4 = load float, float* %5, align 4 + %add.r4.4 = fadd float %add.r.4, %.real.4 + %add.i5.4 = fadd float %add.i.4, %.imag.4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) + %.fca.0.insert = insertvalue { float, float } undef, float %add.r4.4, 0 + %.fca.1.insert = insertvalue { float, float } %.fca.0.insert, float %add.i5.4, 1 + ret { float, float } %.fca.1.insert +} + +define { double, double } @foo3(double %x.coerce0, double %x.coerce1, ...) local_unnamed_addr { +; 32BIT-LABEL: foo3: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: lwz 3, L..C2(2) # %const.0 +; 32BIT-NEXT: stw 7, 40(1) +; 32BIT-NEXT: stw 8, 44(1) +; 32BIT-NEXT: stw 9, 48(1) +; 32BIT-NEXT: stw 10, 52(1) +; 32BIT-NEXT: lfd 4, 40(1) +; 32BIT-NEXT: lfd 5, 48(1) +; 32BIT-NEXT: lfs 0, 0(3) +; 32BIT-NEXT: fadd 3, 1, 0 +; 32BIT-NEXT: fadd 0, 2, 0 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 56(1) +; 32BIT-NEXT: lfd 5, 64(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 72(1) +; 32BIT-NEXT: lfd 5, 80(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: lfd 4, 88(1) +; 32BIT-NEXT: lfd 5, 96(1) +; 32BIT-NEXT: fadd 3, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: fadd 3, 3, 4 +; 32BIT-NEXT: fadd 0, 0, 5 +; 32BIT-NEXT: fadd 1, 3, 1 +; 32BIT-NEXT: fadd 0, 0, 2 +; 32BIT-NEXT: lfd 2, 104(1) +; 32BIT-NEXT: lfd 3, 112(1) +; 32BIT-NEXT: fadd 1, 1, 2 +; 32BIT-NEXT: fadd 2, 0, 3 +; 32BIT-NEXT: blr +entry: + %arg = alloca i8*, align 4 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %arg.promoted = load i8*, i8** %arg, align 4 + %add.r = fadd double %x.coerce0, 0.000000e+00 + %add.i = fadd double %x.coerce1, 0.000000e+00 + %argp.next = getelementptr inbounds i8, i8* %arg.promoted, i32 16 + %.realp = bitcast i8* %arg.promoted to double* + %.real = load double, double* %.realp, align 4 + %.imagp = getelementptr inbounds i8, i8* %arg.promoted, i32 8 + %1 = bitcast i8* %.imagp to double* + %.imag = load double, double* %1, align 4 + %add.r4 = fadd double %add.r, %.real + %add.i5 = fadd double %add.i, %.imag + %add.r.1 = fadd double %add.r4, %x.coerce0 + %add.i.1 = fadd double %add.i5, %x.coerce1 + %argp.next.1 = getelementptr inbounds i8, i8* %arg.promoted, i32 32 + %.realp.1 = bitcast i8* %argp.next to double* + %.real.1 = load double, double* %.realp.1, align 4 + %.imagp.1 = getelementptr inbounds i8, i8* %arg.promoted, i32 24 + %2 = bitcast i8* %.imagp.1 to double* + %.imag.1 = load double, double* %2, align 4 + %add.r4.1 = fadd double %add.r.1, %.real.1 + %add.i5.1 = fadd double %add.i.1, %.imag.1 + %add.r.2 = fadd double %add.r4.1, %x.coerce0 + %add.i.2 = fadd double %add.i5.1, %x.coerce1 + %argp.next.2 = getelementptr inbounds i8, i8* %arg.promoted, i32 48 + %.realp.2 = bitcast i8* %argp.next.1 to double* + %.real.2 = load double, double* %.realp.2, align 4 + %.imagp.2 = getelementptr inbounds i8, i8* %arg.promoted, i32 40 + %3 = bitcast i8* %.imagp.2 to double* + %.imag.2 = load double, double* %3, align 4 + %add.r4.2 = fadd double %add.r.2, %.real.2 + %add.i5.2 = fadd double %add.i.2, %.imag.2 + %add.r.3 = fadd double %add.r4.2, %x.coerce0 + %add.i.3 = fadd double %add.i5.2, %x.coerce1 + %argp.next.3 = getelementptr inbounds i8, i8* %arg.promoted, i32 64 + %.realp.3 = bitcast i8* %argp.next.2 to double* + %.real.3 = load double, double* %.realp.3, align 4 + %.imagp.3 = getelementptr inbounds i8, i8* %arg.promoted, i32 56 + %4 = bitcast i8* %.imagp.3 to double* + %.imag.3 = load double, double* %4, align 4 + %add.r4.3 = fadd double %add.r.3, %.real.3 + %add.i5.3 = fadd double %add.i.3, %.imag.3 + %add.r.4 = fadd double %add.r4.3, %x.coerce0 + %add.i.4 = fadd double %add.i5.3, %x.coerce1 + %.realp.4 = bitcast i8* %argp.next.3 to double* + %.real.4 = load double, double* %.realp.4, align 4 + %.imagp.4 = getelementptr inbounds i8, i8* %arg.promoted, i32 72 + %5 = bitcast i8* %.imagp.4 to double* + %.imag.4 = load double, double* %5, align 4 + %add.r4.4 = fadd double %add.r.4, %.real.4 + %add.i5.4 = fadd double %add.i.4, %.imag.4 + %scevgep = getelementptr i8, i8* %arg.promoted, i32 80 + store i8* %scevgep, i8** %arg, align 4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) + %.fca.0.insert = insertvalue { double, double } undef, double %add.r4.4, 0 + %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i5.4, 1 + ret { double, double } %.fca.1.insert +} + +; Function Attrs: nofree nosync nounwind +define void @bar1() local_unnamed_addr { +; 32BIT-LABEL: bar1: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: mflr 0 +; 32BIT-NEXT: stw 0, 8(1) +; 32BIT-NEXT: stwu 1, -128(1) +; 32BIT-NEXT: lwz 3, L..C3(2) # @cdbl +; 32BIT-NEXT: lwz 7, L..C4(2) # @cdbl1 +; 32BIT-NEXT: lwz 9, L..C5(2) # @cdbl2 +; 32BIT-NEXT: lwz 10, L..C6(2) # @cdbl3 +; 32BIT-NEXT: lfd 1, 0(3) +; 32BIT-NEXT: stfd 1, 120(1) +; 32BIT-NEXT: lfd 2, 8(3) +; 32BIT-NEXT: lwz 3, 120(1) +; 32BIT-NEXT: lwz 4, 124(1) +; 32BIT-NEXT: stfd 2, 112(1) +; 32BIT-NEXT: lfd 3, 0(7) +; 32BIT-NEXT: lwz 5, 112(1) +; 32BIT-NEXT: lwz 6, 116(1) +; 32BIT-NEXT: stfd 3, 104(1) +; 32BIT-NEXT: lfd 4, 8(7) +; 32BIT-NEXT: lwz 7, 104(1) +; 32BIT-NEXT: lwz 8, 108(1) +; 32BIT-NEXT: stfd 4, 96(1) +; 32BIT-NEXT: lfd 5, 0(9) +; 32BIT-NEXT: lfd 6, 8(9) +; 32BIT-NEXT: lfd 7, 0(10) +; 32BIT-NEXT: lfd 8, 8(10) +; 32BIT-NEXT: lwz 9, 96(1) +; 32BIT-NEXT: lwz 10, 100(1) +; 32BIT-NEXT: stfd 6, 64(1) +; 32BIT-NEXT: stfd 5, 56(1) +; 32BIT-NEXT: stfd 8, 80(1) +; 32BIT-NEXT: stfd 7, 72(1) +; 32BIT-NEXT: bl .foo1 +; 32BIT-NEXT: nop +; 32BIT-NEXT: addi 1, 1, 128 +; 32BIT-NEXT: lwz 0, 8(1) +; 32BIT-NEXT: mtlr 0 +; 32BIT-NEXT: blr +entry: + %cdbl.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl, i32 0, i32 0), align 8 + %cdbl.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl, i32 0, i32 1), align 8 + %cdbl1.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl1, i32 0, i32 0), align 8 + %cdbl1.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl1, i32 0, i32 1), align 8 + %cdbl2.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl2, i32 0, i32 0), align 8 + %cdbl2.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl2, i32 0, i32 1), align 8 + %cdbl3.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl3, i32 0, i32 0), align 8 + %cdbl3.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl3, i32 0, i32 1), align 8 + %call = tail call { double, double } (double, double, ...) @foo1(double %cdbl.real, double %cdbl.imag, double %cdbl1.real, double %cdbl1.imag, double %cdbl2.real, double %cdbl2.imag, double %cdbl3.real, double %cdbl3.imag) + ret void +} + +; Function Attrs: nofree nosync nounwind +define void @bar2() local_unnamed_addr { +; 32BIT-LABEL: bar2: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: mflr 0 +; 32BIT-NEXT: stw 0, 8(1) +; 32BIT-NEXT: stwu 1, -96(1) +; 32BIT-NEXT: lwz 3, L..C7(2) # @cflt +; 32BIT-NEXT: lwz 5, L..C8(2) # @cflt1 +; 32BIT-NEXT: lwz 7, L..C9(2) # @cflt2 +; 32BIT-NEXT: lwz 9, L..C10(2) # @cflt3 +; 32BIT-NEXT: lfs 1, 0(3) +; 32BIT-NEXT: stfs 1, 64(1) +; 32BIT-NEXT: lfs 2, 4(3) +; 32BIT-NEXT: lwz 3, 64(1) +; 32BIT-NEXT: stfs 2, 80(1) +; 32BIT-NEXT: lfs 3, 0(5) +; 32BIT-NEXT: lwz 4, 80(1) +; 32BIT-NEXT: stfs 3, 68(1) +; 32BIT-NEXT: lfs 4, 4(5) +; 32BIT-NEXT: lwz 5, 68(1) +; 32BIT-NEXT: stfs 4, 84(1) +; 32BIT-NEXT: lfs 5, 0(7) +; 32BIT-NEXT: lwz 6, 84(1) +; 32BIT-NEXT: stfs 5, 72(1) +; 32BIT-NEXT: lfs 6, 4(7) +; 32BIT-NEXT: lwz 7, 72(1) +; 32BIT-NEXT: stfs 6, 88(1) +; 32BIT-NEXT: lfs 7, 0(9) +; 32BIT-NEXT: lwz 8, 88(1) +; 32BIT-NEXT: stfs 7, 76(1) +; 32BIT-NEXT: lfs 8, 4(9) +; 32BIT-NEXT: lwz 9, 76(1) +; 32BIT-NEXT: stfs 8, 92(1) +; 32BIT-NEXT: lwz 10, 92(1) +; 32BIT-NEXT: bl .foo2 +; 32BIT-NEXT: nop +; 32BIT-NEXT: addi 1, 1, 96 +; 32BIT-NEXT: lwz 0, 8(1) +; 32BIT-NEXT: mtlr 0 +; 32BIT-NEXT: blr +entry: + %cflt.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt, i32 0, i32 0), align 4 + %cflt.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt, i32 0, i32 1), align 4 + %cflt1.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt1, i32 0, i32 0), align 4 + %cflt1.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt1, i32 0, i32 1), align 4 + %cflt2.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt2, i32 0, i32 0), align 4 + %cflt2.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt2, i32 0, i32 1), align 4 + %cflt3.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt3, i32 0, i32 0), align 4 + %cflt3.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt3, i32 0, i32 1), align 4 + %call = tail call { float, float } (float, float, ...) @foo2(float %cflt.real, float %cflt.imag, float %cflt1.real, float %cflt1.imag, float %cflt2.real, float %cflt2.imag, float %cflt3.real, float %cflt3.imag) + ret void +} + +; Function Attrs: nofree nosync nounwind +define void @bar3() local_unnamed_addr { +; 32BIT-LABEL: bar3: +; 32BIT: # %bb.0: # %entry +; 32BIT-NEXT: mflr 0 +; 32BIT-NEXT: stw 0, 8(1) +; 32BIT-NEXT: stwu 1, -128(1) +; 32BIT-NEXT: lwz 3, L..C11(2) # @cldbl +; 32BIT-NEXT: lwz 7, L..C12(2) # @cldbl1 +; 32BIT-NEXT: lwz 9, L..C13(2) # @cldbl2 +; 32BIT-NEXT: lwz 10, L..C14(2) # @cldbl3 +; 32BIT-NEXT: lfd 1, 0(3) +; 32BIT-NEXT: stfd 1, 120(1) +; 32BIT-NEXT: lfd 2, 8(3) +; 32BIT-NEXT: lwz 3, 120(1) +; 32BIT-NEXT: lwz 4, 124(1) +; 32BIT-NEXT: stfd 2, 112(1) +; 32BIT-NEXT: lfd 3, 0(7) +; 32BIT-NEXT: lwz 5, 112(1) +; 32BIT-NEXT: lwz 6, 116(1) +; 32BIT-NEXT: stfd 3, 104(1) +; 32BIT-NEXT: lfd 4, 8(7) +; 32BIT-NEXT: lwz 7, 104(1) +; 32BIT-NEXT: lwz 8, 108(1) +; 32BIT-NEXT: stfd 4, 96(1) +; 32BIT-NEXT: lfd 5, 0(9) +; 32BIT-NEXT: lfd 6, 8(9) +; 32BIT-NEXT: lfd 7, 0(10) +; 32BIT-NEXT: lfd 8, 8(10) +; 32BIT-NEXT: lwz 9, 96(1) +; 32BIT-NEXT: lwz 10, 100(1) +; 32BIT-NEXT: stfd 6, 64(1) +; 32BIT-NEXT: stfd 5, 56(1) +; 32BIT-NEXT: stfd 8, 80(1) +; 32BIT-NEXT: stfd 7, 72(1) +; 32BIT-NEXT: bl .foo3 +; 32BIT-NEXT: nop +; 32BIT-NEXT: addi 1, 1, 128 +; 32BIT-NEXT: lwz 0, 8(1) +; 32BIT-NEXT: mtlr 0 +; 32BIT-NEXT: blr +entry: + %cldbl.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl, i32 0, i32 0), align 8 + %cldbl.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl, i32 0, i32 1), align 8 + %cldbl1.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl1, i32 0, i32 0), align 8 + %cldbl1.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl1, i32 0, i32 1), align 8 + %cldbl2.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl2, i32 0, i32 0), align 8 + %cldbl2.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl2, i32 0, i32 1), align 8 + %cldbl3.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl3, i32 0, i32 0), align 8 + %cldbl3.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl3, i32 0, i32 1), align 8 + %call = tail call { double, double } (double, double, ...) @foo3(double %cldbl.real, double %cldbl.imag, double %cldbl1.real, double %cldbl1.imag, double %cldbl2.real, double %cldbl2.imag, double %cldbl3.real, double %cldbl3.imag) + ret void +} diff --git a/llvm/test/CodeGen/PowerPC/aix64-complex-vararg.ll b/llvm/test/CodeGen/PowerPC/aix64-complex-vararg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix64-complex-vararg.ll @@ -0,0 +1,509 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=64BIT %s + +@cdbl = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl1 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl2 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cdbl3 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cflt = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt1 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt2 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cflt3 = local_unnamed_addr global { float, float } zeroinitializer, align 4 +@cldbl = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl1 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl2 = local_unnamed_addr global { double, double } zeroinitializer, align 8 +@cldbl3 = local_unnamed_addr global { double, double } zeroinitializer, align 8 + +define { double, double } @foo1(double %x.coerce0, double %x.coerce1, ...) local_unnamed_addr { +; 64BIT-LABEL: foo1: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: ld 3, L..C0(2) # %const.0 +; 64BIT-NEXT: std 5, 64(1) +; 64BIT-NEXT: std 6, 72(1) +; 64BIT-NEXT: lfd 4, 64(1) +; 64BIT-NEXT: lfd 5, 72(1) +; 64BIT-NEXT: std 7, 80(1) +; 64BIT-NEXT: std 8, 88(1) +; 64BIT-NEXT: lfs 0, 0(3) +; 64BIT-NEXT: std 9, 96(1) +; 64BIT-NEXT: addi 3, 1, 64 +; 64BIT-NEXT: std 10, 104(1) +; 64BIT-NEXT: fadd 3, 1, 0 +; 64BIT-NEXT: fadd 0, 2, 0 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfdu 4, 16(3) +; 64BIT-NEXT: lfd 5, 88(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfd 4, 96(1) +; 64BIT-NEXT: lfd 5, 104(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfd 4, 112(1) +; 64BIT-NEXT: lfd 5, 120(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: fadd 1, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: lfd 2, 128(1) +; 64BIT-NEXT: lfd 3, 136(1) +; 64BIT-NEXT: fadd 1, 1, 2 +; 64BIT-NEXT: fadd 2, 0, 3 +; 64BIT-NEXT: blr +entry: + %arg = alloca i8*, align 8 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %add.r = fadd double %x.coerce0, 0.000000e+00 + %add.i = fadd double %x.coerce1, 0.000000e+00 + %argp.cur = load i8*, i8** %arg, align 8 + %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16 + store i8* %argp.next, i8** %arg, align 8 + %.realp = bitcast i8* %argp.cur to double* + %.real = load double, double* %.realp, align 8 + %.imagp = getelementptr inbounds i8, i8* %argp.cur, i64 8 + %1 = bitcast i8* %.imagp to double* + %.imag = load double, double* %1, align 8 + %add.r4 = fadd double %add.r, %.real + %add.i5 = fadd double %add.i, %.imag + %add.r.1 = fadd double %add.r4, %x.coerce0 + %add.i.1 = fadd double %add.i5, %x.coerce1 + %argp.next.1 = getelementptr inbounds i8, i8* %argp.cur, i64 32 + %.realp.1 = bitcast i8* %argp.next to double* + %.real.1 = load double, double* %.realp.1, align 8 + %.imagp.1 = getelementptr inbounds i8, i8* %argp.cur, i64 24 + %2 = bitcast i8* %.imagp.1 to double* + %.imag.1 = load double, double* %2, align 8 + %add.r4.1 = fadd double %add.r.1, %.real.1 + %add.i5.1 = fadd double %add.i.1, %.imag.1 + %add.r.2 = fadd double %add.r4.1, %x.coerce0 + %add.i.2 = fadd double %add.i5.1, %x.coerce1 + %argp.next.2 = getelementptr inbounds i8, i8* %argp.cur, i64 48 + %.realp.2 = bitcast i8* %argp.next.1 to double* + %.real.2 = load double, double* %.realp.2, align 8 + %.imagp.2 = getelementptr inbounds i8, i8* %argp.cur, i64 40 + %3 = bitcast i8* %.imagp.2 to double* + %.imag.2 = load double, double* %3, align 8 + %add.r4.2 = fadd double %add.r.2, %.real.2 + %add.i5.2 = fadd double %add.i.2, %.imag.2 + %add.r.3 = fadd double %add.r4.2, %x.coerce0 + %add.i.3 = fadd double %add.i5.2, %x.coerce1 + %argp.next.3 = getelementptr inbounds i8, i8* %argp.cur, i64 64 + %.realp.3 = bitcast i8* %argp.next.2 to double* + %.real.3 = load double, double* %.realp.3, align 8 + %.imagp.3 = getelementptr inbounds i8, i8* %argp.cur, i64 56 + %4 = bitcast i8* %.imagp.3 to double* + %.imag.3 = load double, double* %4, align 8 + %add.r4.3 = fadd double %add.r.3, %.real.3 + %add.i5.3 = fadd double %add.i.3, %.imag.3 + %add.r.4 = fadd double %add.r4.3, %x.coerce0 + %add.i.4 = fadd double %add.i5.3, %x.coerce1 + %argp.next.4 = getelementptr inbounds i8, i8* %argp.cur, i64 80 + store i8* %argp.next.4, i8** %arg, align 8 + %.realp.4 = bitcast i8* %argp.next.3 to double* + %.real.4 = load double, double* %.realp.4, align 8 + %.imagp.4 = getelementptr inbounds i8, i8* %argp.cur, i64 72 + %5 = bitcast i8* %.imagp.4 to double* + %.imag.4 = load double, double* %5, align 8 + %add.r4.4 = fadd double %add.r.4, %.real.4 + %add.i5.4 = fadd double %add.i.4, %.imag.4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) + %.fca.0.insert = insertvalue { double, double } undef, double %add.r4.4, 0 + %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i5.4, 1 + ret { double, double } %.fca.1.insert +} + +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) + +declare void @llvm.va_start(i8*) + +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) + +declare void @llvm.va_end(i8*) + +define { float, float } @foo2(float %x.coerce0, float %x.coerce1, ...) local_unnamed_addr { +; 64BIT-LABEL: foo2: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: ld 3, L..C1(2) # %const.0 +; 64BIT-NEXT: std 5, 64(1) +; 64BIT-NEXT: std 6, 72(1) +; 64BIT-NEXT: lfs 4, 68(1) +; 64BIT-NEXT: lfs 5, 76(1) +; 64BIT-NEXT: std 7, 80(1) +; 64BIT-NEXT: std 8, 88(1) +; 64BIT-NEXT: lfs 0, 0(3) +; 64BIT-NEXT: std 9, 96(1) +; 64BIT-NEXT: std 10, 104(1) +; 64BIT-NEXT: fadds 3, 1, 0 +; 64BIT-NEXT: fadds 0, 2, 0 +; 64BIT-NEXT: fadds 3, 3, 4 +; 64BIT-NEXT: fadds 0, 0, 5 +; 64BIT-NEXT: lfs 4, 84(1) +; 64BIT-NEXT: lfs 5, 92(1) +; 64BIT-NEXT: fadds 3, 3, 1 +; 64BIT-NEXT: fadds 0, 0, 2 +; 64BIT-NEXT: fadds 3, 3, 4 +; 64BIT-NEXT: fadds 0, 0, 5 +; 64BIT-NEXT: lfs 4, 100(1) +; 64BIT-NEXT: lfs 5, 108(1) +; 64BIT-NEXT: fadds 3, 3, 1 +; 64BIT-NEXT: fadds 0, 0, 2 +; 64BIT-NEXT: fadds 3, 3, 4 +; 64BIT-NEXT: fadds 0, 0, 5 +; 64BIT-NEXT: lfs 4, 116(1) +; 64BIT-NEXT: lfs 5, 124(1) +; 64BIT-NEXT: fadds 3, 3, 1 +; 64BIT-NEXT: fadds 0, 0, 2 +; 64BIT-NEXT: fadds 3, 3, 4 +; 64BIT-NEXT: fadds 0, 0, 5 +; 64BIT-NEXT: fadds 1, 3, 1 +; 64BIT-NEXT: fadds 0, 0, 2 +; 64BIT-NEXT: lfs 2, 132(1) +; 64BIT-NEXT: lfs 3, 140(1) +; 64BIT-NEXT: fadds 1, 1, 2 +; 64BIT-NEXT: fadds 2, 0, 3 +; 64BIT-NEXT: blr +entry: + %arg = alloca i8*, align 8 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %add.r = fadd float %x.coerce0, 0.000000e+00 + %add.i = fadd float %x.coerce1, 0.000000e+00 + %argp.cur = load i8*, i8** %arg, align 8 + %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16 + store i8* %argp.next, i8** %arg, align 8 + %1 = getelementptr inbounds i8, i8* %argp.cur, i64 4 + %2 = getelementptr inbounds i8, i8* %argp.cur, i64 12 + %3 = bitcast i8* %1 to float* + %4 = bitcast i8* %2 to float* + %.vareal = load float, float* %3, align 4 + %.vaimag = load float, float* %4, align 4 + %add.r6 = fadd float %add.r, %.vareal + %add.i7 = fadd float %add.i, %.vaimag + %add.r.1 = fadd float %add.r6, %x.coerce0 + %add.i.1 = fadd float %add.i7, %x.coerce1 + %5 = getelementptr inbounds i8, i8* %argp.cur, i64 20 + %6 = getelementptr inbounds i8, i8* %argp.cur, i64 28 + %7 = bitcast i8* %5 to float* + %8 = bitcast i8* %6 to float* + %.vareal.1 = load float, float* %7, align 4 + %.vaimag.1 = load float, float* %8, align 4 + %add.r6.1 = fadd float %add.r.1, %.vareal.1 + %add.i7.1 = fadd float %add.i.1, %.vaimag.1 + %add.r.2 = fadd float %add.r6.1, %x.coerce0 + %add.i.2 = fadd float %add.i7.1, %x.coerce1 + %9 = getelementptr inbounds i8, i8* %argp.cur, i64 36 + %10 = getelementptr inbounds i8, i8* %argp.cur, i64 44 + %11 = bitcast i8* %9 to float* + %12 = bitcast i8* %10 to float* + %.vareal.2 = load float, float* %11, align 4 + %.vaimag.2 = load float, float* %12, align 4 + %add.r6.2 = fadd float %add.r.2, %.vareal.2 + %add.i7.2 = fadd float %add.i.2, %.vaimag.2 + %add.r.3 = fadd float %add.r6.2, %x.coerce0 + %add.i.3 = fadd float %add.i7.2, %x.coerce1 + %13 = getelementptr inbounds i8, i8* %argp.cur, i64 52 + %14 = getelementptr inbounds i8, i8* %argp.cur, i64 60 + %15 = bitcast i8* %13 to float* + %16 = bitcast i8* %14 to float* + %.vareal.3 = load float, float* %15, align 4 + %.vaimag.3 = load float, float* %16, align 4 + %add.r6.3 = fadd float %add.r.3, %.vareal.3 + %add.i7.3 = fadd float %add.i.3, %.vaimag.3 + %add.r.4 = fadd float %add.r6.3, %x.coerce0 + %add.i.4 = fadd float %add.i7.3, %x.coerce1 + %argp.next.4 = getelementptr inbounds i8, i8* %argp.cur, i64 80 + store i8* %argp.next.4, i8** %arg, align 8 + %17 = getelementptr inbounds i8, i8* %argp.cur, i64 68 + %18 = getelementptr inbounds i8, i8* %argp.cur, i64 76 + %19 = bitcast i8* %17 to float* + %20 = bitcast i8* %18 to float* + %.vareal.4 = load float, float* %19, align 4 + %.vaimag.4 = load float, float* %20, align 4 + %add.r6.4 = fadd float %add.r.4, %.vareal.4 + %add.i7.4 = fadd float %add.i.4, %.vaimag.4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) + %.fca.0.insert = insertvalue { float, float } undef, float %add.r6.4, 0 + %.fca.1.insert = insertvalue { float, float } %.fca.0.insert, float %add.i7.4, 1 + ret { float, float } %.fca.1.insert +} + +define { double, double } @foo3(double %x.coerce0, double %x.coerce1, ...) local_unnamed_addr { +; 64BIT-LABEL: foo3: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: ld 3, L..C2(2) # %const.0 +; 64BIT-NEXT: std 5, 64(1) +; 64BIT-NEXT: std 6, 72(1) +; 64BIT-NEXT: lfd 4, 64(1) +; 64BIT-NEXT: lfd 5, 72(1) +; 64BIT-NEXT: std 7, 80(1) +; 64BIT-NEXT: std 8, 88(1) +; 64BIT-NEXT: lfs 0, 0(3) +; 64BIT-NEXT: std 9, 96(1) +; 64BIT-NEXT: addi 3, 1, 64 +; 64BIT-NEXT: std 10, 104(1) +; 64BIT-NEXT: fadd 3, 1, 0 +; 64BIT-NEXT: fadd 0, 2, 0 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfdu 4, 16(3) +; 64BIT-NEXT: lfd 5, 88(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfd 4, 96(1) +; 64BIT-NEXT: lfd 5, 104(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: lfd 4, 112(1) +; 64BIT-NEXT: lfd 5, 120(1) +; 64BIT-NEXT: fadd 3, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: fadd 3, 3, 4 +; 64BIT-NEXT: fadd 0, 0, 5 +; 64BIT-NEXT: fadd 1, 3, 1 +; 64BIT-NEXT: fadd 0, 0, 2 +; 64BIT-NEXT: lfd 2, 128(1) +; 64BIT-NEXT: lfd 3, 136(1) +; 64BIT-NEXT: fadd 1, 1, 2 +; 64BIT-NEXT: fadd 2, 0, 3 +; 64BIT-NEXT: blr +entry: + %arg = alloca i8*, align 8 + %0 = bitcast i8** %arg to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) + call void @llvm.va_start(i8* nonnull %0) + %add.r = fadd double %x.coerce0, 0.000000e+00 + %add.i = fadd double %x.coerce1, 0.000000e+00 + %argp.cur = load i8*, i8** %arg, align 8 + %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16 + store i8* %argp.next, i8** %arg, align 8 + %.realp = bitcast i8* %argp.cur to double* + %.real = load double, double* %.realp, align 8 + %.imagp = getelementptr inbounds i8, i8* %argp.cur, i64 8 + %1 = bitcast i8* %.imagp to double* + %.imag = load double, double* %1, align 8 + %add.r4 = fadd double %add.r, %.real + %add.i5 = fadd double %add.i, %.imag + %add.r.1 = fadd double %add.r4, %x.coerce0 + %add.i.1 = fadd double %add.i5, %x.coerce1 + %argp.next.1 = getelementptr inbounds i8, i8* %argp.cur, i64 32 + %.realp.1 = bitcast i8* %argp.next to double* + %.real.1 = load double, double* %.realp.1, align 8 + %.imagp.1 = getelementptr inbounds i8, i8* %argp.cur, i64 24 + %2 = bitcast i8* %.imagp.1 to double* + %.imag.1 = load double, double* %2, align 8 + %add.r4.1 = fadd double %add.r.1, %.real.1 + %add.i5.1 = fadd double %add.i.1, %.imag.1 + %add.r.2 = fadd double %add.r4.1, %x.coerce0 + %add.i.2 = fadd double %add.i5.1, %x.coerce1 + %argp.next.2 = getelementptr inbounds i8, i8* %argp.cur, i64 48 + %.realp.2 = bitcast i8* %argp.next.1 to double* + %.real.2 = load double, double* %.realp.2, align 8 + %.imagp.2 = getelementptr inbounds i8, i8* %argp.cur, i64 40 + %3 = bitcast i8* %.imagp.2 to double* + %.imag.2 = load double, double* %3, align 8 + %add.r4.2 = fadd double %add.r.2, %.real.2 + %add.i5.2 = fadd double %add.i.2, %.imag.2 + %add.r.3 = fadd double %add.r4.2, %x.coerce0 + %add.i.3 = fadd double %add.i5.2, %x.coerce1 + %argp.next.3 = getelementptr inbounds i8, i8* %argp.cur, i64 64 + %.realp.3 = bitcast i8* %argp.next.2 to double* + %.real.3 = load double, double* %.realp.3, align 8 + %.imagp.3 = getelementptr inbounds i8, i8* %argp.cur, i64 56 + %4 = bitcast i8* %.imagp.3 to double* + %.imag.3 = load double, double* %4, align 8 + %add.r4.3 = fadd double %add.r.3, %.real.3 + %add.i5.3 = fadd double %add.i.3, %.imag.3 + %add.r.4 = fadd double %add.r4.3, %x.coerce0 + %add.i.4 = fadd double %add.i5.3, %x.coerce1 + %argp.next.4 = getelementptr inbounds i8, i8* %argp.cur, i64 80 + store i8* %argp.next.4, i8** %arg, align 8 + %.realp.4 = bitcast i8* %argp.next.3 to double* + %.real.4 = load double, double* %.realp.4, align 8 + %.imagp.4 = getelementptr inbounds i8, i8* %argp.cur, i64 72 + %5 = bitcast i8* %.imagp.4 to double* + %.imag.4 = load double, double* %5, align 8 + %add.r4.4 = fadd double %add.r.4, %.real.4 + %add.i5.4 = fadd double %add.i.4, %.imag.4 + call void @llvm.va_end(i8* nonnull %0) + call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) + %.fca.0.insert = insertvalue { double, double } undef, double %add.r4.4, 0 + %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i5.4, 1 + ret { double, double } %.fca.1.insert +} + +define void @bar1() local_unnamed_addr { +; 64BIT-LABEL: bar1: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: mflr 0 +; 64BIT-NEXT: std 0, 16(1) +; 64BIT-NEXT: stdu 1, -176(1) +; 64BIT-NEXT: ld 3, L..C3(2) # @cdbl +; 64BIT-NEXT: ld 5, L..C4(2) # @cdbl1 +; 64BIT-NEXT: ld 7, L..C5(2) # @cdbl2 +; 64BIT-NEXT: ld 9, L..C6(2) # @cdbl3 +; 64BIT-NEXT: lfd 1, 0(3) +; 64BIT-NEXT: stfd 1, 112(1) +; 64BIT-NEXT: lfd 2, 8(3) +; 64BIT-NEXT: ld 3, 112(1) +; 64BIT-NEXT: stfd 2, 144(1) +; 64BIT-NEXT: lfd 3, 0(5) +; 64BIT-NEXT: ld 4, 144(1) +; 64BIT-NEXT: stfd 3, 120(1) +; 64BIT-NEXT: lfd 4, 8(5) +; 64BIT-NEXT: ld 5, 120(1) +; 64BIT-NEXT: stfd 4, 152(1) +; 64BIT-NEXT: lfd 5, 0(7) +; 64BIT-NEXT: ld 6, 152(1) +; 64BIT-NEXT: stfd 5, 128(1) +; 64BIT-NEXT: lfd 6, 8(7) +; 64BIT-NEXT: ld 7, 128(1) +; 64BIT-NEXT: stfd 6, 160(1) +; 64BIT-NEXT: lfd 7, 0(9) +; 64BIT-NEXT: ld 8, 160(1) +; 64BIT-NEXT: stfd 7, 136(1) +; 64BIT-NEXT: lfd 8, 8(9) +; 64BIT-NEXT: ld 9, 136(1) +; 64BIT-NEXT: stfd 8, 168(1) +; 64BIT-NEXT: ld 10, 168(1) +; 64BIT-NEXT: bl .foo1 +; 64BIT-NEXT: nop +; 64BIT-NEXT: addi 1, 1, 176 +; 64BIT-NEXT: ld 0, 16(1) +; 64BIT-NEXT: mtlr 0 +; 64BIT-NEXT: blr +entry: + %cdbl.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl, i64 0, i32 0), align 8 + %cdbl.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl, i64 0, i32 1), align 8 + %cdbl1.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl1, i64 0, i32 0), align 8 + %cdbl1.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl1, i64 0, i32 1), align 8 + %cdbl2.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl2, i64 0, i32 0), align 8 + %cdbl2.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl2, i64 0, i32 1), align 8 + %cdbl3.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl3, i64 0, i32 0), align 8 + %cdbl3.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cdbl3, i64 0, i32 1), align 8 + %call = tail call { double, double } (double, double, ...) @foo1(double %cdbl.real, double %cdbl.imag, double %cdbl1.real, double %cdbl1.imag, double %cdbl2.real, double %cdbl2.imag, double %cdbl3.real, double %cdbl3.imag) + ret void +} + +define void @bar2() local_unnamed_addr { +; 64BIT-LABEL: bar2: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: mflr 0 +; 64BIT-NEXT: std 0, 16(1) +; 64BIT-NEXT: stdu 1, -144(1) +; 64BIT-NEXT: ld 3, L..C7(2) # @cflt +; 64BIT-NEXT: ld 5, L..C8(2) # @cflt1 +; 64BIT-NEXT: ld 7, L..C9(2) # @cflt2 +; 64BIT-NEXT: ld 9, L..C10(2) # @cflt3 +; 64BIT-NEXT: lfs 1, 0(3) +; 64BIT-NEXT: stfs 1, 112(1) +; 64BIT-NEXT: lfs 2, 4(3) +; 64BIT-NEXT: lwz 3, 112(1) +; 64BIT-NEXT: stfs 2, 128(1) +; 64BIT-NEXT: lfs 3, 0(5) +; 64BIT-NEXT: lwz 4, 128(1) +; 64BIT-NEXT: stfs 3, 116(1) +; 64BIT-NEXT: lfs 4, 4(5) +; 64BIT-NEXT: lwz 5, 116(1) +; 64BIT-NEXT: stfs 4, 132(1) +; 64BIT-NEXT: lfs 5, 0(7) +; 64BIT-NEXT: lwz 6, 132(1) +; 64BIT-NEXT: stfs 5, 120(1) +; 64BIT-NEXT: lfs 6, 4(7) +; 64BIT-NEXT: lwz 7, 120(1) +; 64BIT-NEXT: stfs 6, 136(1) +; 64BIT-NEXT: lfs 7, 0(9) +; 64BIT-NEXT: lwz 8, 136(1) +; 64BIT-NEXT: stfs 7, 124(1) +; 64BIT-NEXT: lfs 8, 4(9) +; 64BIT-NEXT: lwz 9, 124(1) +; 64BIT-NEXT: stfs 8, 140(1) +; 64BIT-NEXT: lwz 10, 140(1) +; 64BIT-NEXT: bl .foo2 +; 64BIT-NEXT: nop +; 64BIT-NEXT: addi 1, 1, 144 +; 64BIT-NEXT: ld 0, 16(1) +; 64BIT-NEXT: mtlr 0 +; 64BIT-NEXT: blr +entry: + %cflt.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt, i64 0, i32 0), align 4 + %cflt.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt, i64 0, i32 1), align 4 + %cflt1.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt1, i64 0, i32 0), align 4 + %cflt1.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt1, i64 0, i32 1), align 4 + %cflt2.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt2, i64 0, i32 0), align 4 + %cflt2.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt2, i64 0, i32 1), align 4 + %cflt3.real = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt3, i64 0, i32 0), align 4 + %cflt3.imag = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @cflt3, i64 0, i32 1), align 4 + %call = tail call { float, float } (float, float, ...) @foo2(float %cflt.real, float %cflt.imag, float %cflt1.real, float %cflt1.imag, float %cflt2.real, float %cflt2.imag, float %cflt3.real, float %cflt3.imag) + ret void +} + +define void @bar3() local_unnamed_addr { +; 64BIT-LABEL: bar3: +; 64BIT: # %bb.0: # %entry +; 64BIT-NEXT: mflr 0 +; 64BIT-NEXT: std 0, 16(1) +; 64BIT-NEXT: stdu 1, -176(1) +; 64BIT-NEXT: ld 3, L..C11(2) # @cldbl +; 64BIT-NEXT: ld 5, L..C12(2) # @cldbl1 +; 64BIT-NEXT: ld 7, L..C13(2) # @cldbl2 +; 64BIT-NEXT: ld 9, L..C14(2) # @cldbl3 +; 64BIT-NEXT: lfd 1, 0(3) +; 64BIT-NEXT: stfd 1, 112(1) +; 64BIT-NEXT: lfd 2, 8(3) +; 64BIT-NEXT: ld 3, 112(1) +; 64BIT-NEXT: stfd 2, 144(1) +; 64BIT-NEXT: lfd 3, 0(5) +; 64BIT-NEXT: ld 4, 144(1) +; 64BIT-NEXT: stfd 3, 120(1) +; 64BIT-NEXT: lfd 4, 8(5) +; 64BIT-NEXT: ld 5, 120(1) +; 64BIT-NEXT: stfd 4, 152(1) +; 64BIT-NEXT: lfd 5, 0(7) +; 64BIT-NEXT: ld 6, 152(1) +; 64BIT-NEXT: stfd 5, 128(1) +; 64BIT-NEXT: lfd 6, 8(7) +; 64BIT-NEXT: ld 7, 128(1) +; 64BIT-NEXT: stfd 6, 160(1) +; 64BIT-NEXT: lfd 7, 0(9) +; 64BIT-NEXT: ld 8, 160(1) +; 64BIT-NEXT: stfd 7, 136(1) +; 64BIT-NEXT: lfd 8, 8(9) +; 64BIT-NEXT: ld 9, 136(1) +; 64BIT-NEXT: stfd 8, 168(1) +; 64BIT-NEXT: ld 10, 168(1) +; 64BIT-NEXT: bl .foo3 +; 64BIT-NEXT: nop +; 64BIT-NEXT: addi 1, 1, 176 +; 64BIT-NEXT: ld 0, 16(1) +; 64BIT-NEXT: mtlr 0 +; 64BIT-NEXT: blr +entry: + %cldbl.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl, i64 0, i32 0), align 8 + %cldbl.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl, i64 0, i32 1), align 8 + %cldbl1.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl1, i64 0, i32 0), align 8 + %cldbl1.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl1, i64 0, i32 1), align 8 + %cldbl2.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl2, i64 0, i32 0), align 8 + %cldbl2.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl2, i64 0, i32 1), align 8 + %cldbl3.real = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl3, i64 0, i32 0), align 8 + %cldbl3.imag = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @cldbl3, i64 0, i32 1), align 8 + %call = tail call { double, double } (double, double, ...) @foo3(double %cldbl.real, double %cldbl.imag, double %cldbl1.real, double %cldbl1.imag, double %cldbl2.real, double %cldbl2.imag, double %cldbl3.real, double %cldbl3.imag) + ret void +}