[llvm-commits] [llvm-gcc-4.2] r50107 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386.cpp testsuite/gcc.target/x86_64/abi/test_struct_returning.c

Devang Patel dpatel at apple.com
Tue Apr 22 14:03:42 PDT 2008


Author: dpatel
Date: Tue Apr 22 16:03:42 2008
New Revision: 50107

URL: http://llvm.org/viewvc/llvm-project?rev=50107&view=rev
Log:
Return { float, float, float } as ret <4 x float>, float


Modified:
    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
    llvm-gcc-4.2/trunk/gcc/testsuite/gcc.target/x86_64/abi/test_struct_returning.c

Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp?rev=50107&r1=50106&r2=50107&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp Tue Apr 22 16:03:42 2008
@@ -922,6 +922,7 @@
 // of type TY should be returned using multiple value return instruction.
 static bool llvm_suitable_multiple_ret_value_type(const Type *Ty,
                                                   tree TreeType) {
+
   if (!TARGET_64BIT)
     return false;
 
@@ -1013,7 +1014,16 @@
     ElementTypes.push_back(Type::X86_FP80Ty);
     return StructType::get(ElementTypes, STy->isPacked());
   } 
-    
+
+  if (NumElements == 3
+      && STy->getElementType(0)->getTypeID() == Type::FloatTyID
+      && STy->getElementType(1)->getTypeID() == Type::FloatTyID
+      && STy->getElementType(2)->getTypeID() == Type::FloatTyID) {
+    ElementTypes.push_back(VectorType::get(Type::FloatTy, 4));
+    ElementTypes.push_back(Type::FloatTy);
+    return StructType::get(ElementTypes, STy->isPacked());
+  }
+
   for (unsigned i = 0; i < NumElements; ++i) {
     const Type *T = STy->getElementType(i);
     
@@ -1031,12 +1041,12 @@
     if (ATy->getElementType()->isFloatingPoint()) {
       switch (size) {
       case 2:
-        // use { <2 x float> } for struct { float[2]; }
-        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 2));
+        // use { <4 x float> } for struct { float[2]; }
+        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 4));
         break;
       case 3:
-        // use { <2 x float>, float } for struct { float[3]; }
-        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 2));
+        // use { <4 x float>, float } for struct { float[3]; }
+        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 4));
         ElementTypes.push_back(ATy->getElementType());
         break;
       case 4:
@@ -1072,6 +1082,30 @@
   unsigned NumElements = RetSTy->getNumElements();
   unsigned RNO = 0;
   unsigned SNO = 0;
+
+  if (NumElements == 3
+      && RetSTy->getElementType(0)->getTypeID() == Type::FloatTyID
+      && RetSTy->getElementType(1)->getTypeID() == Type::FloatTyID
+      && RetSTy->getElementType(2)->getTypeID() == Type::FloatTyID) {
+    Value *GEP0 = Builder.CreateStructGEP(RetVal, 0, "mrv_idx");
+    Value *ElemVal0 = Builder.CreateLoad(GEP0, "mrv");
+    Value *GEP1 = Builder.CreateStructGEP(RetVal, 1, "mrv_idx");
+    Value *ElemVal1 = Builder.CreateLoad(GEP1, "mrv");
+    Value *GEP2 = Builder.CreateStructGEP(RetVal, 2, "mrv_idx");
+    Value *ElemVal2 = Builder.CreateLoad(GEP2, "mrv");
+
+    Value *R = Constant::getNullValue(STy->getElementType(0));
+    R = Builder.CreateInsertElement(R, ElemVal0, 
+                                    ConstantInt::get(llvm::Type::Int32Ty, 0),
+                                    "mrv.f.");
+    R = Builder.CreateInsertElement(R, ElemVal1, 
+                                    ConstantInt::get(llvm::Type::Int32Ty, 1),
+                                    "mrv.f.");
+    RetVals.push_back(R);
+    RetVals.push_back(ElemVal2);
+    return;
+  }
+
   while (RNO < NumElements) {
     const Type *ElemType = RetSTy->getElementType(RNO);    
     if (ElemType->isFirstClassType()) {
@@ -1081,7 +1115,8 @@
       ++RNO;
       ++SNO;
       continue;
-    } 
+    }
+ 
     // Special treatement for _Complex.
     if (const StructType *ComplexType = dyn_cast<StructType>(ElemType)) {
       llvm::Value *Idxs[3];
@@ -1188,6 +1223,32 @@
   const StructType *DestTy = cast<StructType>(PTy->getElementType());
   unsigned SNO = 0;
   unsigned DNO = 0;
+
+  if (DestTy->getNumElements() == 3
+      && DestTy->getElementType(0)->getTypeID() == Type::FloatTyID
+      && DestTy->getElementType(1)->getTypeID() == Type::FloatTyID
+      && DestTy->getElementType(2)->getTypeID() == Type::FloatTyID) {
+    // DestTy is { float, float, float }
+    // STy is { <4 x float>, float > }
+
+    GetResultInst *GR = Builder.CreateGetResult(Src, 0, "mrv_gr");
+
+    Value *E0Index = ConstantInt::get(Type::Int32Ty, 0);
+    Value *GR0 = Builder.CreateExtractElement(GR, E0Index, "mrv.v");
+    Value *GEP0 = Builder.CreateStructGEP(Dest, 0, "mrv_gep");
+    Builder.CreateStore(GR0, GEP0, isVolatile);
+
+    Value *E1Index = ConstantInt::get(Type::Int32Ty, 1);
+    Value *GR1 = Builder.CreateExtractElement(GR, E1Index, "mrv.v");
+    Value *GEP1 = Builder.CreateStructGEP(Dest, 1, "mrv_gep");
+    Builder.CreateStore(GR1, GEP1, isVolatile);
+
+    Value *GEP2 = Builder.CreateStructGEP(Dest, 2, "mrv_gep");
+    GetResultInst *GR2 = Builder.CreateGetResult(Src, 1, "mrv_gr");
+    Builder.CreateStore(GR2, GEP2, isVolatile);
+    return;
+  }
+
   while (SNO < NumElements) {
 
     const Type *DestElemType = DestTy->getElementType(DNO);

Modified: llvm-gcc-4.2/trunk/gcc/testsuite/gcc.target/x86_64/abi/test_struct_returning.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/testsuite/gcc.target/x86_64/abi/test_struct_returning.c?rev=50107&r1=50106&r2=50107&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/testsuite/gcc.target/x86_64/abi/test_struct_returning.c (original)
+++ llvm-gcc-4.2/trunk/gcc/testsuite/gcc.target/x86_64/abi/test_struct_returning.c Tue Apr 22 16:03:42 2008
@@ -28,7 +28,10 @@
   MEM,
   INT_SSE,
   SSE_INT,
-  SSE_F_V
+  /* LLVM LOCAL begin */
+  SSE_F_V,
+  SSE_F_V3
+  /* LLVM LOCAL end */
 } Type;
 
 /* Structures which should be returned in INTEGER.  */
@@ -165,6 +168,10 @@
 #define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
 struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
 D(600,float f[4], SSE_F_V, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+/* LLVM LOCAL begin */
+D(601,float f[3], SSE_F_V3, s.f[0] = s.f[1] = s.f[2] = 42)
+D(602,float f0;float f1; float f2, SSE_F_V3, s.f0 = s.f1 = s.f2 = 42)
+/* LLVM LOCAL end */
 #undef D
 
 void clear_all (void)
@@ -181,6 +188,8 @@
     case SSE_F: assert (xmm0f[0] == 42); break;
     case SSE_D: assert (xmm0d[0] == 42); break;
     case SSE_F_V: assert (xmm0f[0] == 42 && xmm0f[1]==42 && xmm1f[0] == 42 && xmm1f[1] == 42); break;
+      /* LLVM LOCAL */
+    case SSE_F_V3: assert (xmm0f[0] == 42 && xmm0f[1]==42 && xmm1f[0] == 42); break;
     case X87: assert (x87_regs[0]._ldouble == 42); break;
     case INT_SSE: check_300(); break;
     case SSE_INT: check_400(); break;
@@ -222,7 +231,9 @@
   D(530)
 
   D(600)
-  if (num_failed)
+  /* LLVM LOCAL */
+  D(601) D(602)
+ if (num_failed)
     abort ();
 
   return 0;





More information about the llvm-commits mailing list