[llvm] r372957 - [MIPS GlobalISel] Lower aggregate structure return arguments

Petar Avramovic via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 26 03:48:07 PDT 2019


Author: petar.avramovic
Date: Thu Sep 26 03:48:07 2019
New Revision: 372957

URL: http://llvm.org/viewvc/llvm-project?rev=372957&view=rev
Log:
[MIPS GlobalISel] Lower aggregate structure return arguments

Implement aggregate structure split to simpler types in splitToValueTypes.
splitToValueTypes is used for return values.
According to MipsABIInfo from clang/lib/CodeGen/TargetInfo.cpp,
aggregate structure arguments for O32 always get simplified and thus
will remain unsupported by the MIPS GlobalISel for the time being.
For O32, aggregate structures can be encountered only for complex number
returns e.g. 'complex float' or 'complex double' from <complex.h>.

Differential Revision: https://reviews.llvm.org/D67963

Added:
    llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/aggregate_struct_return.ll
    llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/aggregate_struct_return.ll
Modified:
    llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp
    llvm/trunk/lib/Target/Mips/MipsCallLowering.h

Modified: llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp?rev=372957&r1=372956&r2=372957&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp Thu Sep 26 03:48:07 2019
@@ -358,7 +358,7 @@ bool OutgoingValueHandler::handleSplit(S
   return true;
 }
 
-static bool isSupportedType(Type *T) {
+static bool isSupportedArgumentType(Type *T) {
   if (T->isIntegerTy())
     return true;
   if (T->isPointerTy())
@@ -368,6 +368,18 @@ static bool isSupportedType(Type *T) {
   return false;
 }
 
+static bool isSupportedReturnType(Type *T) {
+  if (T->isIntegerTy())
+    return true;
+  if (T->isPointerTy())
+    return true;
+  if (T->isFloatingPointTy())
+    return true;
+  if (T->isAggregateType())
+    return true;
+  return false;
+}
+
 static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT,
                                              const ISD::ArgFlagsTy &Flags) {
   // > does not mean loss of information as type RegisterVT can't hold type VT,
@@ -404,7 +416,7 @@ bool MipsCallLowering::lowerReturn(Machi
 
   MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
 
-  if (Val != nullptr && !isSupportedType(Val->getType()))
+  if (Val != nullptr && !isSupportedReturnType(Val->getType()))
     return false;
 
   if (!VRegs.empty()) {
@@ -412,21 +424,13 @@ bool MipsCallLowering::lowerReturn(Machi
     const Function &F = MF.getFunction();
     const DataLayout &DL = MF.getDataLayout();
     const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
-    LLVMContext &Ctx = Val->getType()->getContext();
-
-    SmallVector<EVT, 4> SplitEVTs;
-    ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
-    assert(VRegs.size() == SplitEVTs.size() &&
-           "For each split Type there should be exactly one VReg.");
 
     SmallVector<ArgInfo, 8> RetInfos;
     SmallVector<unsigned, 8> OrigArgIndices;
 
-    for (unsigned i = 0; i < SplitEVTs.size(); ++i) {
-      ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)};
-      setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F);
-      splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices);
-    }
+    ArgInfo ArgRetInfo(VRegs, Val->getType());
+    setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
+    splitToValueTypes(DL, ArgRetInfo, 0, RetInfos, OrigArgIndices);
 
     SmallVector<ISD::OutputArg, 8> Outs;
     subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs);
@@ -455,7 +459,7 @@ bool MipsCallLowering::lowerFormalArgume
     return true;
 
   for (auto &Arg : F.args()) {
-    if (!isSupportedType(Arg.getType()))
+    if (!isSupportedArgumentType(Arg.getType()))
       return false;
   }
 
@@ -469,7 +473,8 @@ bool MipsCallLowering::lowerFormalArgume
   for (auto &Arg : F.args()) {
     ArgInfo AInfo(VRegs[i], Arg.getType());
     setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
-    splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
+    ArgInfos.push_back(AInfo);
+    OrigArgIndices.push_back(i);
     ++i;
   }
 
@@ -536,7 +541,7 @@ bool MipsCallLowering::lowerCall(Machine
     return false;
 
   for (auto &Arg : Info.OrigArgs) {
-    if (!isSupportedType(Arg.Ty))
+    if (!isSupportedArgumentType(Arg.Ty))
       return false;
     if (Arg.Flags[0].isByVal())
       return false;
@@ -544,11 +549,12 @@ bool MipsCallLowering::lowerCall(Machine
       return false;
   }
 
-  if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedType(Info.OrigRet.Ty))
+  if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))
     return false;
 
   MachineFunction &MF = MIRBuilder.getMF();
   const Function &F = MF.getFunction();
+  const DataLayout &DL = MF.getDataLayout();
   const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
   const MipsTargetMachine &TM =
       static_cast<const MipsTargetMachine &>(MF.getTarget());
@@ -588,7 +594,8 @@ bool MipsCallLowering::lowerCall(Machine
     Entry.Ty = Arg.Ty;
     FuncOrigArgs.push_back(Entry);
 
-    splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices);
+    ArgInfos.push_back(Arg);
+    OrigArgIndices.push_back(i);
     ++i;
   }
 
@@ -639,7 +646,7 @@ bool MipsCallLowering::lowerCall(Machine
     ArgInfos.clear();
     SmallVector<unsigned, 8> OrigRetIndices;
 
-    splitToValueTypes(Info.OrigRet, 0, ArgInfos, OrigRetIndices);
+    splitToValueTypes(DL, Info.OrigRet, 0, ArgInfos, OrigRetIndices);
 
     SmallVector<ISD::InputArg, 8> Ins;
     subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins);
@@ -693,12 +700,21 @@ void MipsCallLowering::subTargetRegTypeF
 }
 
 void MipsCallLowering::splitToValueTypes(
-    const ArgInfo &OrigArg, unsigned OriginalIndex,
+    const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex,
     SmallVectorImpl<ArgInfo> &SplitArgs,
     SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
 
-  // TODO : perform structure and array split. For now we only deal with
-  // types that pass isSupportedType check.
-  SplitArgs.push_back(OrigArg);
-  SplitArgsOrigIndices.push_back(OriginalIndex);
+  SmallVector<EVT, 4> SplitEVTs;
+  SmallVector<Register, 4> SplitVRegs;
+  const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
+  LLVMContext &Ctx = OrigArg.Ty->getContext();
+
+  ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitEVTs);
+
+  for (unsigned i = 0; i < SplitEVTs.size(); ++i) {
+    ArgInfo Info = ArgInfo{OrigArg.Regs[i], SplitEVTs[i].getTypeForEVT(Ctx)};
+    Info.Flags = OrigArg.Flags;
+    SplitArgs.push_back(Info);
+    SplitArgsOrigIndices.push_back(OriginalIndex);
+  }
 }

Modified: llvm/trunk/lib/Target/Mips/MipsCallLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsCallLowering.h?rev=372957&r1=372956&r2=372957&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsCallLowering.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsCallLowering.h Thu Sep 26 03:48:07 2019
@@ -82,7 +82,8 @@ private:
 
   /// Split structures and arrays, save original argument indices since
   /// Mips calling convention needs info about original argument type.
-  void splitToValueTypes(const ArgInfo &OrigArg, unsigned OriginalIndex,
+  void splitToValueTypes(const DataLayout &DL, const ArgInfo &OrigArg,
+                         unsigned OriginalIndex,
                          SmallVectorImpl<ArgInfo> &SplitArgs,
                          SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const;
 };

Added: llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/aggregate_struct_return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/aggregate_struct_return.ll?rev=372957&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/aggregate_struct_return.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/aggregate_struct_return.ll Thu Sep 26 03:48:07 2019
@@ -0,0 +1,132 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+
+define { float, float } @add_complex_float({ float, float }* %a, { float, float }* %b) {
+  ; MIPS32-LABEL: name: add_complex_float
+  ; MIPS32: bb.1.entry:
+  ; MIPS32:   liveins: $a0, $a1
+  ; MIPS32:   [[COPY:%[0-9]+]]:_(p0) = COPY $a0
+  ; MIPS32:   [[COPY1:%[0-9]+]]:_(p0) = COPY $a1
+  ; MIPS32:   [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+  ; MIPS32:   [[COPY2:%[0-9]+]]:_(p0) = COPY [[COPY]](p0)
+  ; MIPS32:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY2]](p0) :: (load 4 from %ir..realp)
+  ; MIPS32:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; MIPS32:   [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s32)
+  ; MIPS32:   [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[GEP]](p0) :: (load 4 from %ir..imagp)
+  ; MIPS32:   [[COPY3:%[0-9]+]]:_(p0) = COPY [[COPY1]](p0)
+  ; MIPS32:   [[LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[COPY3]](p0) :: (load 4 from %ir..realp1)
+  ; MIPS32:   [[GEP1:%[0-9]+]]:_(p0) = G_GEP [[COPY1]], [[C]](s32)
+  ; MIPS32:   [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP1]](p0) :: (load 4 from %ir..imagp3)
+  ; MIPS32:   [[FADD:%[0-9]+]]:_(s32) = G_FADD [[LOAD]], [[LOAD2]]
+  ; MIPS32:   [[FADD1:%[0-9]+]]:_(s32) = G_FADD [[LOAD1]], [[LOAD3]]
+  ; MIPS32:   $f0 = COPY [[FADD]](s32)
+  ; MIPS32:   $f2 = COPY [[FADD1]](s32)
+  ; MIPS32:   RetRA implicit $f0, implicit $f2
+entry:
+  %.realp = getelementptr inbounds { float, float }, { float, float }* %a, i32 0, i32 0
+  %.real = load float, float* %.realp, align 4
+  %.imagp = getelementptr inbounds { float, float }, { float, float }* %a, i32 0, i32 1
+  %.imag = load float, float* %.imagp, align 4
+  %.realp1 = getelementptr inbounds { float, float }, { float, float }* %b, i32 0, i32 0
+  %.real2 = load float, float* %.realp1, align 4
+  %.imagp3 = getelementptr inbounds { float, float }, { float, float }* %b, i32 0, i32 1
+  %.imag4 = load float, float* %.imagp3, align 4
+  %add.r = fadd float %.real, %.real2
+  %add.i = fadd float %.imag, %.imag4
+  %.fca.0.insert = insertvalue { float, float } undef, float %add.r, 0
+  %.fca.1.insert = insertvalue { float, float } %.fca.0.insert, float %add.i, 1
+  ret { float, float } %.fca.1.insert
+}
+
+define { double, double } @add_complex_double({ double, double }* %a, { double, double }* %b) {
+  ; MIPS32-LABEL: name: add_complex_double
+  ; MIPS32: bb.1.entry:
+  ; MIPS32:   liveins: $a0, $a1
+  ; MIPS32:   [[COPY:%[0-9]+]]:_(p0) = COPY $a0
+  ; MIPS32:   [[COPY1:%[0-9]+]]:_(p0) = COPY $a1
+  ; MIPS32:   [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
+  ; MIPS32:   [[COPY2:%[0-9]+]]:_(p0) = COPY [[COPY]](p0)
+  ; MIPS32:   [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY2]](p0) :: (load 8 from %ir..realp)
+  ; MIPS32:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+  ; MIPS32:   [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s32)
+  ; MIPS32:   [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8 from %ir..imagp)
+  ; MIPS32:   [[COPY3:%[0-9]+]]:_(p0) = COPY [[COPY1]](p0)
+  ; MIPS32:   [[LOAD2:%[0-9]+]]:_(s64) = G_LOAD [[COPY3]](p0) :: (load 8 from %ir..realp1)
+  ; MIPS32:   [[GEP1:%[0-9]+]]:_(p0) = G_GEP [[COPY1]], [[C]](s32)
+  ; MIPS32:   [[LOAD3:%[0-9]+]]:_(s64) = G_LOAD [[GEP1]](p0) :: (load 8 from %ir..imagp3)
+  ; MIPS32:   [[FADD:%[0-9]+]]:_(s64) = G_FADD [[LOAD]], [[LOAD2]]
+  ; MIPS32:   [[FADD1:%[0-9]+]]:_(s64) = G_FADD [[LOAD1]], [[LOAD3]]
+  ; MIPS32:   $d0 = COPY [[FADD]](s64)
+  ; MIPS32:   $d1 = COPY [[FADD1]](s64)
+  ; MIPS32:   RetRA implicit $d0, implicit $d1
+entry:
+  %.realp = getelementptr inbounds { double, double }, { double, double }* %a, i32 0, i32 0
+  %.real = load double, double* %.realp, align 8
+  %.imagp = getelementptr inbounds { double, double }, { double, double }* %a, i32 0, i32 1
+  %.imag = load double, double* %.imagp, align 8
+  %.realp1 = getelementptr inbounds { double, double }, { double, double }* %b, i32 0, i32 0
+  %.real2 = load double, double* %.realp1, align 8
+  %.imagp3 = getelementptr inbounds { double, double }, { double, double }* %b, i32 0, i32 1
+  %.imag4 = load double, double* %.imagp3, align 8
+  %add.r = fadd double %.real, %.real2
+  %add.i = fadd double %.imag, %.imag4
+  %.fca.0.insert = insertvalue { double, double } undef, double %add.r, 0
+  %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i, 1
+  ret { double, double } %.fca.1.insert
+}
+
+declare { float, float } @ret_complex_float()
+define void @call_ret_complex_float({ float, float }* %z) {
+  ; MIPS32-LABEL: name: call_ret_complex_float
+  ; MIPS32: bb.1.entry:
+  ; MIPS32:   liveins: $a0
+  ; MIPS32:   [[COPY:%[0-9]+]]:_(p0) = COPY $a0
+  ; MIPS32:   ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32:   JAL @ret_complex_float, csr_o32, implicit-def $ra, implicit-def $sp, implicit-def $f0, implicit-def $f2
+  ; MIPS32:   [[COPY1:%[0-9]+]]:_(s32) = COPY $f0
+  ; MIPS32:   [[COPY2:%[0-9]+]]:_(s32) = COPY $f2
+  ; MIPS32:   ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32:   [[COPY3:%[0-9]+]]:_(p0) = COPY [[COPY]](p0)
+  ; MIPS32:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; MIPS32:   [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s32)
+  ; MIPS32:   G_STORE [[COPY1]](s32), [[COPY3]](p0) :: (store 4 into %ir..realp)
+  ; MIPS32:   G_STORE [[COPY2]](s32), [[GEP]](p0) :: (store 4 into %ir..imagp)
+  ; MIPS32:   RetRA
+entry:
+  %call = call { float, float } @ret_complex_float()
+  %0 = extractvalue { float, float } %call, 0
+  %1 = extractvalue { float, float } %call, 1
+  %.realp = getelementptr inbounds { float, float }, { float, float }* %z, i32 0, i32 0
+  %.imagp = getelementptr inbounds { float, float }, { float, float }* %z, i32 0, i32 1
+  store float %0, float* %.realp, align 4
+  store float %1, float* %.imagp, align 4
+  ret void
+}
+
+declare { double, double } @ret_complex_double()
+define void @call_ret_complex_double({ double, double }* %z) {
+  ; MIPS32-LABEL: name: call_ret_complex_double
+  ; MIPS32: bb.1.entry:
+  ; MIPS32:   liveins: $a0
+  ; MIPS32:   [[COPY:%[0-9]+]]:_(p0) = COPY $a0
+  ; MIPS32:   ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32:   JAL @ret_complex_double, csr_o32, implicit-def $ra, implicit-def $sp, implicit-def $d0, implicit-def $d1
+  ; MIPS32:   [[COPY1:%[0-9]+]]:_(s64) = COPY $d0
+  ; MIPS32:   [[COPY2:%[0-9]+]]:_(s64) = COPY $d1
+  ; MIPS32:   ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32:   [[COPY3:%[0-9]+]]:_(p0) = COPY [[COPY]](p0)
+  ; MIPS32:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+  ; MIPS32:   [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s32)
+  ; MIPS32:   G_STORE [[COPY1]](s64), [[COPY3]](p0) :: (store 8 into %ir..realp)
+  ; MIPS32:   G_STORE [[COPY2]](s64), [[GEP]](p0) :: (store 8 into %ir..imagp)
+  ; MIPS32:   RetRA
+entry:
+  %call = call { double, double } @ret_complex_double()
+  %0 = extractvalue { double, double } %call, 0
+  %1 = extractvalue { double, double } %call, 1
+  %.realp = getelementptr inbounds { double, double }, { double, double }* %z, i32 0, i32 0
+  %.imagp = getelementptr inbounds { double, double }, { double, double }* %z, i32 0, i32 1
+  store double %0, double* %.realp, align 8
+  store double %1, double* %.imagp, align 8
+  ret void
+}

Added: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/aggregate_struct_return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/aggregate_struct_return.ll?rev=372957&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/aggregate_struct_return.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/aggregate_struct_return.ll Thu Sep 26 03:48:07 2019
@@ -0,0 +1,114 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  -O0 -mtriple=mipsel-linux-gnu -global-isel  -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
+
+define { float, float } @add_complex_float({ float, float }* %a, { float, float }* %b) {
+; MIPS32-LABEL: add_complex_float:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    lwc1 $f0, 0($4)
+; MIPS32-NEXT:    lwc1 $f1, 4($4)
+; MIPS32-NEXT:    lwc1 $f2, 0($5)
+; MIPS32-NEXT:    lwc1 $f3, 4($5)
+; MIPS32-NEXT:    add.s $f0, $f0, $f2
+; MIPS32-NEXT:    add.s $f2, $f1, $f3
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %.realp = getelementptr inbounds { float, float }, { float, float }* %a, i32 0, i32 0
+  %.real = load float, float* %.realp, align 4
+  %.imagp = getelementptr inbounds { float, float }, { float, float }* %a, i32 0, i32 1
+  %.imag = load float, float* %.imagp, align 4
+  %.realp1 = getelementptr inbounds { float, float }, { float, float }* %b, i32 0, i32 0
+  %.real2 = load float, float* %.realp1, align 4
+  %.imagp3 = getelementptr inbounds { float, float }, { float, float }* %b, i32 0, i32 1
+  %.imag4 = load float, float* %.imagp3, align 4
+  %add.r = fadd float %.real, %.real2
+  %add.i = fadd float %.imag, %.imag4
+  %.fca.0.insert = insertvalue { float, float } undef, float %add.r, 0
+  %.fca.1.insert = insertvalue { float, float } %.fca.0.insert, float %add.i, 1
+  ret { float, float } %.fca.1.insert
+}
+
+define { double, double } @add_complex_double({ double, double }* %a, { double, double }* %b) {
+; MIPS32-LABEL: add_complex_double:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    ldc1 $f0, 0($4)
+; MIPS32-NEXT:    ldc1 $f2, 8($4)
+; MIPS32-NEXT:    ldc1 $f4, 0($5)
+; MIPS32-NEXT:    ldc1 $f6, 8($5)
+; MIPS32-NEXT:    add.d $f0, $f0, $f4
+; MIPS32-NEXT:    add.d $f2, $f2, $f6
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %.realp = getelementptr inbounds { double, double }, { double, double }* %a, i32 0, i32 0
+  %.real = load double, double* %.realp, align 8
+  %.imagp = getelementptr inbounds { double, double }, { double, double }* %a, i32 0, i32 1
+  %.imag = load double, double* %.imagp, align 8
+  %.realp1 = getelementptr inbounds { double, double }, { double, double }* %b, i32 0, i32 0
+  %.real2 = load double, double* %.realp1, align 8
+  %.imagp3 = getelementptr inbounds { double, double }, { double, double }* %b, i32 0, i32 1
+  %.imag4 = load double, double* %.imagp3, align 8
+  %add.r = fadd double %.real, %.real2
+  %add.i = fadd double %.imag, %.imag4
+  %.fca.0.insert = insertvalue { double, double } undef, double %add.r, 0
+  %.fca.1.insert = insertvalue { double, double } %.fca.0.insert, double %add.i, 1
+  ret { double, double } %.fca.1.insert
+}
+
+declare { float, float } @ret_complex_float()
+define void @call_ret_complex_float({ float, float }* %z) {
+; MIPS32-LABEL: call_ret_complex_float:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    addiu $sp, $sp, -24
+; MIPS32-NEXT:    .cfi_def_cfa_offset 24
+; MIPS32-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT:    .cfi_offset 31, -4
+; MIPS32-NEXT:    sw $4, 16($sp) # 4-byte Folded Spill
+; MIPS32-NEXT:    jal ret_complex_float
+; MIPS32-NEXT:    nop
+; MIPS32-NEXT:    lw $1, 16($sp) # 4-byte Folded Reload
+; MIPS32-NEXT:    swc1 $f0, 0($1)
+; MIPS32-NEXT:    swc1 $f2, 4($1)
+; MIPS32-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT:    addiu $sp, $sp, 24
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %call = call { float, float } @ret_complex_float()
+  %0 = extractvalue { float, float } %call, 0
+  %1 = extractvalue { float, float } %call, 1
+  %.realp = getelementptr inbounds { float, float }, { float, float }* %z, i32 0, i32 0
+  %.imagp = getelementptr inbounds { float, float }, { float, float }* %z, i32 0, i32 1
+  store float %0, float* %.realp, align 4
+  store float %1, float* %.imagp, align 4
+  ret void
+}
+
+declare { double, double } @ret_complex_double()
+define void @call_ret_complex_double({ double, double }* %z) {
+; MIPS32-LABEL: call_ret_complex_double:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    addiu $sp, $sp, -24
+; MIPS32-NEXT:    .cfi_def_cfa_offset 24
+; MIPS32-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT:    .cfi_offset 31, -4
+; MIPS32-NEXT:    sw $4, 16($sp) # 4-byte Folded Spill
+; MIPS32-NEXT:    jal ret_complex_double
+; MIPS32-NEXT:    nop
+; MIPS32-NEXT:    lw $1, 16($sp) # 4-byte Folded Reload
+; MIPS32-NEXT:    sdc1 $f0, 0($1)
+; MIPS32-NEXT:    sdc1 $f2, 8($1)
+; MIPS32-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT:    addiu $sp, $sp, 24
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %call = call { double, double } @ret_complex_double()
+  %0 = extractvalue { double, double } %call, 0
+  %1 = extractvalue { double, double } %call, 1
+  %.realp = getelementptr inbounds { double, double }, { double, double }* %z, i32 0, i32 0
+  %.imagp = getelementptr inbounds { double, double }, { double, double }* %z, i32 0, i32 1
+  store double %0, double* %.realp, align 8
+  store double %1, double* %.imagp, align 8
+  ret void
+}




More information about the llvm-commits mailing list