[llvm-commits] [llvm-gcc-4.2] r49829 - /llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp

Devang Patel dpatel at apple.com
Wed Apr 16 16:28:44 PDT 2008


Author: dpatel
Date: Wed Apr 16 18:28:44 2008
New Revision: 49829

URL: http://llvm.org/viewvc/llvm-project?rev=49829&view=rev
Log:
Do not use llvm_x86_64_should_pass_aggregate_in_mixed_regs() while handling
struct return.

And some code cleanup.

Modified:
    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp

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=49829&r1=49828&r2=49829&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 Wed Apr 16 18:28:44 2008
@@ -744,32 +744,6 @@
   return llvm_x86_64_should_pass_aggregate_in_memory(TreeType, Mode);
 }
 
-/* llvm_x86_64_type_needs_multiple_regs - Return number of register classes
-   need by TREETYPE. Return 0 if TREETYPE does not need multiple registers. 
-   This helper routine is used to determine LLVM type of the function 
-   arguments as well as return values.  */
-static int
-llvm_x86_64_type_needs_multiple_regs(enum machine_mode Mode, tree TreeType,
-                                     enum x86_64_reg_class Class[MAX_CLASSES]) {
-  int NumClasses = ix86_ClassifyArgument(Mode, TreeType, Class, 0);
-  if (!NumClasses)
-    return 0;
-
-  for (int i = 0; i < NumClasses; ++i) {
-    switch (Class[i]) {
-    case X86_64_X87_CLASS:
-    case X86_64_X87UP_CLASS:
-    case X86_64_COMPLEX_X87_CLASS:
-      return 0;
-    case X86_64_NO_CLASS:
-      return 0;
-    default:
-      break;
-    }
-  }
-  return NumClasses;
-}
-
 /* Target hook for llvm-abi.h. It returns true if an aggregate of the
    specified type should be passed in a number of registers of mixed types.
    It also returns a vector of types that correspond to the registers used
@@ -781,7 +755,7 @@
   enum machine_mode Mode = ix86_getNaturalModeForType(TreeType);
   HOST_WIDE_INT Bytes =
     (Mode == BLKmode) ? int_size_in_bytes(TreeType) : (int) GET_MODE_SIZE(Mode);
-  int NumClasses = llvm_x86_64_type_needs_multiple_regs(Mode, TreeType, Class);
+  int NumClasses = ix86_ClassifyArgument(Mode, TreeType, Class, 0);
   if (!NumClasses)
     return false;
  
@@ -844,18 +818,11 @@
           Elts.push_back(Type::DoubleTy);
           Bytes -= 16;
         } else if (Class[i+1] == X86_64_SSEDF_CLASS && Bytes == 16) {
-          // struct {float f[2]; double d; } should be returned in SSE registers.
           Elts.push_back(VectorType::get(Type::FloatTy, 2));
           Elts.push_back(Type::DoubleTy);
         } else if (Class[i+1] == X86_64_INTEGER_CLASS) {
-          // struct { float f[2]; char c; } should be returned in SSE(low)
-          // and INT (high).
-          const Type *Ty = ConvertType(TreeType);
-          if (const StructType *STy = dyn_cast<StructType>(Ty)) {
-            Elts.push_back(VectorType::get(Type::FloatTy, 2));
-            Elts.push_back(STy->getElementType(1));
-          } else
-            assert(0 && "Not yet handled!");
+          Elts.push_back(VectorType::get(Type::FloatTy, 2));
+          Elts.push_back(Type::Int64Ty);
         } else
           assert(0 && "Not yet handled!");
         ++i; // Already handled the next one.
@@ -936,8 +903,7 @@
 // llvm_suitable_multiple_ret_value_type - Return TRUE if return value 
 // of type TY should be returned using multiple value return instruction.
 static bool llvm_suitable_multiple_ret_value_type(const Type *Ty,
-                                                  tree TreeType,
-                                                  std::vector<const Type *>&Elts) {
+                                                  tree TreeType) {
   //NOTE: Work in progress. Do not open the flood gate yet.
   return false; 
 
@@ -948,28 +914,40 @@
   if (!STy)
     return false;
 
-  //Let gcc specific routine answer the question.
+  // llvm only accepts first class types for multiple values in ret instruction.
+  bool foundNonInt = false;
+  bool foundInt = false;
+  unsigned STyElements = STy->getNumElements();
+  for (unsigned i = 0; i < STyElements; ++i) { 
+    const Type *ETy = STy->getElementType(i);
+    if (const ArrayType *ATy = dyn_cast<ArrayType>(ETy))
+      ETy = ATy->getElementType();
+    if (!ETy->isFirstClassType())
+      return false;
+    if (!ETy->isInteger())
+      foundNonInt = true;
+    else
+      foundInt = true;
+  }
+  // FIXME. llvm x86-64 code generator does not handle all cases of
+  // multiple value return. Remove this when the code generator restriction 
+  // is removed.
+  if (!foundNonInt)
+    return false;
+
+  // Let gcc specific routine answer the question.
   enum x86_64_reg_class Class[MAX_CLASSES];
   enum machine_mode Mode = ix86_getNaturalModeForType(TreeType);
-  if (llvm_x86_64_type_needs_multiple_regs(Mode, TreeType, Class)) {
-
-    llvm_x86_64_should_pass_aggregate_in_mixed_regs(TreeType, Ty, Elts);
-    assert (!Elts.empty() && "Unable to handle aggregate return type!");
-    // If it is a singleton structure, e.g. { long double ld;} then use the type
-    // directly.
-    if (Elts.size() == 1)
-      return true;
-    
-    bool foundFloat = false;
-    for (unsigned i = 0; i < Elts.size(); ++i) 
-      if (Elts[i]->isFloatingPoint()
-          || Elts[i]->getTypeID() == Type::VectorTyID)
-        foundFloat = true;
+  int NumClasses = ix86_ClassifyArgument(Mode, TreeType, Class, 0);
+  if (NumClasses == 0)
+    return false;
 
-    return foundFloat;
-  }
+  // FIXME: llvm x86-64 code generator is not able to handle return {i8, float}
+  if (NumClasses == 1 && foundInt)
+    return false;
 
-  return false;
+  // Otherwise, use of multiple value return is OK.
+  return true;
 }
 
 // llvm_x86_scalar_type_for_struct_return - Return LLVM type if TYPE
@@ -987,12 +965,8 @@
     return Type::Int32Ty;
 
   // Check if Ty should be returned using multiple value return instruction.
-  std::vector<const Type *>Elts;
-  if (llvm_suitable_multiple_ret_value_type(Ty, type, Elts)) {
-    if (Elts.size() == 1)
-      return Elts[0];
+  if (llvm_suitable_multiple_ret_value_type(Ty, type))
     return NULL;
-  }
 
   if (Size <= 8)
     return Type::Int64Ty;
@@ -1004,11 +978,11 @@
   return NULL;
 }
 
-// Return LLVM Type if TYPE can be returned as an aggregate, otherwise return NULL.
+// Return LLVM Type if TYPE can be returned as an aggregate, 
+// otherwise return NULL.
 const Type *llvm_x86_aggr_type_for_struct_return(tree type) {
   const Type *Ty = ConvertType(type);
-  std::vector<const Type *>Elts;
-  if (!llvm_suitable_multiple_ret_value_type(Ty, type, Elts))
+  if (!llvm_suitable_multiple_ret_value_type(Ty, type))
     return NULL;
 
   const StructType *STy = cast<StructType>(Ty);
@@ -1042,7 +1016,8 @@
         break;
       case 4:
         // use { <4  x float> } for struct { float[4]; }
-        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 4));
+        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 2));
+        ElementTypes.push_back(VectorType::get(ATy->getElementType(), 2));
         break;
       default:
         assert (0 && "Unexpected floating point array size!");
@@ -1052,34 +1027,37 @@
         ElementTypes.push_back(ATy->getElementType());
     }
   }
-  
   return StructType::get(ElementTypes, STy->isPacked());
 }
 
-
 // llvm_x86_build_mrv_array_element - This is a helper function used by
-// llvm_x6_build_multiple_return_value. This function builds a vector
-// from the array fields of RetVal.
+// llvm_x6_build_multiple_return_value. 
 static Value *llvm_x86_build_mrv_array_element(const Type *STyFieldTy,
                                                Value *RetVal,
                                                unsigned FieldNo,
-                                               unsigned ArraySize,
-                                               IRBuilder &Builder) {
+                                               IRBuilder &Builder,
+                                               unsigned ArrayElemNo = 0) {
   llvm::Value *Idxs[3];
   Idxs[0] = ConstantInt::get(llvm::Type::Int32Ty, 0);
   Idxs[1] = ConstantInt::get(llvm::Type::Int32Ty, FieldNo);
-
-  Value *R1 = UndefValue::get(STyFieldTy);
-
-  for (unsigned i = 0; i < ArraySize; ++i) {
-    Idxs[2] = ConstantInt::get(llvm::Type::Int32Ty, i);
+  if (const VectorType *VTy = dyn_cast<VectorType>(STyFieldTy)) {
+    // Source field is a vector. Use insertelement.
+    Value *R1 = UndefValue::get(STyFieldTy);
+    unsigned ArraySize = VTy->getNumElements();
+    for (unsigned i = ArrayElemNo; i < ArraySize; ++i) {
+      Idxs[2] = ConstantInt::get(llvm::Type::Int32Ty, i);
+      Value *GEP = Builder.CreateGEP(RetVal, Idxs, Idxs+3, "mrv_gep");
+      Value *ElemVal = Builder.CreateLoad(GEP, "mrv");
+      R1 = Builder.CreateInsertElement(R1, ElemVal, 
+                                       ConstantInt::get(llvm::Type::Int32Ty, i), 
+                                       "mrv");
+    }
+    return R1;
+  } else {
+    Idxs[2] = ConstantInt::get(llvm::Type::Int32Ty, ArrayElemNo);
     Value *GEP = Builder.CreateGEP(RetVal, Idxs, Idxs+3, "mrv_gep");
-    Value *ElemVal = Builder.CreateLoad(GEP, "mrv");
-    R1 = Builder.CreateInsertElement(R1, ElemVal, 
-                                     ConstantInt::get(llvm::Type::Int32Ty, i), 
-                                     "mrv");
+    return Builder.CreateLoad(GEP, "mrv");
   }
-  return R1;
 }
 
 // llvm_x86_build_multiple_return_value - Function FN returns multiple value
@@ -1097,38 +1075,44 @@
   // may not match. For example, when STy is { <2 x float> } the RetSTy is
   // { float[2]; }
   unsigned NumElements = RetSTy->getNumElements();
-  for (unsigned RNO = 0, SNO = 0; RNO < NumElements; ++RNO, ++SNO) {
-    const Type *ElemType = RetSTy->getElementType(RNO);
+  unsigned RNO = 0;
+  unsigned SNO = 0;
+  while (RNO < NumElements) {
+    const Type *ElemType = RetSTy->getElementType(RNO);    
     if (ElemType->isFirstClassType()) {
       Value *GEP = Builder.CreateStructGEP(RetVal, RNO, "mrv_idx");
       Value *ElemVal = Builder.CreateLoad(GEP, "mrv");
       RetVals.push_back(ElemVal);
-    } else {
-      const ArrayType *ATy = cast<ArrayType>(ElemType);
-      unsigned ArraySize = ATy->getNumElements();
-      const VectorType *SElemTy = cast<VectorType>(STy->getElementType(SNO));
-      unsigned Size = SElemTy->getNumElements();
-      assert (ArraySize >= Size && "Invalid multiple return value type!");
-      Value *R = llvm_x86_build_mrv_array_element(SElemTy, RetVal, RNO,
-                                                  Size, Builder);
-      RetVals.push_back(R);
-      if (ArraySize > Size) {
-        assert (ArraySize == Size + 1 && "Unable to build multiple return value!");
-        // Build remaining values.
-        const Type *NextTy = STy->getElementType(SNO + 1);
-        if (NextTy->getTypeID() == Type::FloatTyID) {
-          Value *Idxs[3];
-          Idxs[0] = ConstantInt::get(llvm::Type::Int32Ty, 0);
-          Idxs[1] = ConstantInt::get(llvm::Type::Int32Ty, RNO);
-          Idxs[2] = ConstantInt::get(llvm::Type::Int32Ty, Size + 1);
-          Value *GEP3 = Builder.CreateGEP(RetVal, Idxs, Idxs+3, "mrv_gep");
-          Value *ElemVal3 = Builder.CreateLoad(GEP3, "mrv");
-          RetVals.push_back(ElemVal3);
-          SNO++;
-        } else 
-          assert ( 0 && "Unable to build multiple return value!");
+      ++RNO;
+      ++SNO;
+      continue;
+    }
+
+    const ArrayType *ATy = cast<ArrayType>(ElemType);
+    unsigned ArraySize = ATy->getNumElements();
+    unsigned AElemNo = 0;
+    while (AElemNo < ArraySize) {
+      const Type *SElemTy =  STy->getElementType(SNO);
+      if (const VectorType *SVElemTy = dyn_cast<VectorType>(SElemTy)) {
+        // Build array elements from a vector.
+        unsigned VSize = SVElemTy->getNumElements();
+        assert (ArraySize - AElemNo >= VSize 
+                && "Invalid multiple return value type!");
+        Value *R = llvm_x86_build_mrv_array_element(SVElemTy, RetVal, RNO,
+                                                    Builder, AElemNo);
+        RetVals.push_back(R);
+        AElemNo += VSize;
+      } else {
+        Value *R = llvm_x86_build_mrv_array_element(SElemTy, RetVal, RNO,
+                                                    Builder, AElemNo);
+        RetVals.push_back(R);
+        ++AElemNo;
       }
+      // Next Src field.
+      ++SNO;
     }
+    // Finished building this array field.
+    RNO++;
   }
 }
 
@@ -1193,24 +1177,24 @@
     // not match. For example { <2 x float>, float } and { float[3]; }
     const ArrayType *ATy = cast<ArrayType>(DestElemType);
     unsigned ArraySize = ATy->getNumElements();
-    for (unsigned di = 0, si = 0; di < ArraySize; ++di, ++si) {
-      llvm_x86_extract_mrv_array_element(Src, Dest, SNO, si, DNO, di, 
-                                         Builder, isVolatile);
-      if (const VectorType *SElemTy = 
-          dyn_cast<VectorType>(STy->getElementType(SNO))) {
-        unsigned NumVElem = SElemTy->getNumElements();
-        if (NumVElem == si + 1) {
-          // If extracted all elments from current Src field then 
-          // move to next field.
-          si = 0;
-          ++SNO;
-        }
+    unsigned DElemNo = 0; // DestTy's DNO field's element number
+    while (DElemNo < ArraySize) {
+      const VectorType *SElemTy = dyn_cast<VectorType>(STy->getElementType(SNO));
+      if (!SElemTy) {
+        llvm_x86_extract_mrv_array_element(Src, Dest, SNO, 0, DNO, DElemNo, 
+                                           Builder, isVolatile);
+        ++DElemNo;
       } else {
-        // Copied content from current source field, so move to next field.
-        ++SNO;
+        for (unsigned i = 0; i < SElemTy->getNumElements(); ++i) {
+          llvm_x86_extract_mrv_array_element(Src, Dest, SNO, i, DNO, DElemNo, 
+                                             Builder, isVolatile);
+          ++DElemNo;
+        }
       }
+      // Consumed this src field. Try next one.
+      ++SNO;
     }
-    // Process next DNO element.
+    // Finished building current dest field. 
     ++DNO;
   }
 }





More information about the llvm-commits mailing list