]> granicus.if.org Git - clang/commitdiff
Kill off the 'coerce' ABI passing form. Now 'direct' and 'extend' always
authorChris Lattner <sabre@nondot.org>
Thu, 29 Jul 2010 06:26:06 +0000 (06:26 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 29 Jul 2010 06:26:06 +0000 (06:26 +0000)
have a "coerce to" type which often matches the default lowering of Clang
type to LLVM IR type, but the coerce case can be handled by making them
not be the same.

This simplifies things and fixes issues where X86-64 abi lowering would
return coerce after making preferred types exactly match up.  This caused
us to compile:

typedef float v4f32 __attribute__((__vector_size__(16)));
v4f32 foo(v4f32 X) {
  return X+X;
}

into this code at -O0:

define <4 x float> @foo(<4 x float> %X.coerce) nounwind {
entry:
  %retval = alloca <4 x float>, align 16          ; <<4 x float>*> [#uses=2]
  %coerce = alloca <4 x float>, align 16          ; <<4 x float>*> [#uses=2]
  %X.addr = alloca <4 x float>, align 16          ; <<4 x float>*> [#uses=3]
  store <4 x float> %X.coerce, <4 x float>* %coerce
  %X = load <4 x float>* %coerce                  ; <<4 x float>> [#uses=1]
  store <4 x float> %X, <4 x float>* %X.addr
  %tmp = load <4 x float>* %X.addr                ; <<4 x float>> [#uses=1]
  %tmp1 = load <4 x float>* %X.addr               ; <<4 x float>> [#uses=1]
  %add = fadd <4 x float> %tmp, %tmp1             ; <<4 x float>> [#uses=1]
  store <4 x float> %add, <4 x float>* %retval
  %0 = load <4 x float>* %retval                  ; <<4 x float>> [#uses=1]
  ret <4 x float> %0
}

Now we get:

define <4 x float> @foo(<4 x float> %X) nounwind {
entry:
  %X.addr = alloca <4 x float>, align 16          ; <<4 x float>*> [#uses=3]
  store <4 x float> %X, <4 x float>* %X.addr
  %tmp = load <4 x float>* %X.addr                ; <<4 x float>> [#uses=1]
  %tmp1 = load <4 x float>* %X.addr               ; <<4 x float>> [#uses=1]
  %add = fadd <4 x float> %tmp, %tmp1             ; <<4 x float>> [#uses=1]
  ret <4 x float> %add
}

This implements rdar://8248065

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109733 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/ABIInfo.h
lib/CodeGen/CGCall.cpp
lib/CodeGen/CodeGenTypes.h
lib/CodeGen/TargetInfo.cpp
test/CodeGen/x86_64-arguments.c
test/CodeGenCXX/x86_64-arguments.cpp

index 30f99c31e3df66b6cbb2751194f25c44a4727f2a..642fddb5c8dd8651bd94a036dda4b25cee1942fb 100644 (file)
@@ -38,17 +38,13 @@ namespace clang {
   class ABIArgInfo {
   public:
     enum Kind {
-      Direct,    /// Pass the argument directly using the normal
-                 /// converted LLVM type. Complex and structure types
-                 /// are passed using first class aggregates.
+      Direct,    /// Pass the argument directly using the normal converted LLVM
+                 /// type, or by coercing to another specified type
+                 /// (stored in 'CoerceToType').
 
       Extend,    /// Valid only for integer argument types. Same as 'direct'
                  /// but also emit a zero/sign extension attribute.
 
-      Coerce,    /// Only valid for aggregate return types, the argument
-                 /// should be accessed by coercion to a provided type.
-      
-      
       Indirect,  /// Pass the argument indirectly via a hidden pointer
                  /// with the specified alignment (0 indicates default
                  /// alignment).
@@ -79,8 +75,8 @@ namespace clang {
   public:
     ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
 
-    static ABIArgInfo getDirect() {
-      return ABIArgInfo(Direct);
+    static ABIArgInfo getDirect(const llvm::Type *T = 0) {
+      return ABIArgInfo(Direct, T);
     }
     static ABIArgInfo getExtend() {
       return ABIArgInfo(Extend);
@@ -88,9 +84,6 @@ namespace clang {
     static ABIArgInfo getIgnore() {
       return ABIArgInfo(Ignore);
     }
-    static ABIArgInfo getCoerce(const llvm::Type *T) {
-      return ABIArgInfo(Coerce, T);
-    }
     static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) {
       return ABIArgInfo(Indirect, 0, Alignment, ByVal);
     }
@@ -102,16 +95,23 @@ namespace clang {
     bool isDirect() const { return TheKind == Direct; }
     bool isExtend() const { return TheKind == Extend; }
     bool isIgnore() const { return TheKind == Ignore; }
-    bool isCoerce() const { return TheKind == Coerce; }
     bool isIndirect() const { return TheKind == Indirect; }
     bool isExpand() const { return TheKind == Expand; }
 
-    // Coerce accessors
+    bool canHaveCoerceToType() const {
+      return TheKind == Direct || TheKind == Extend;
+    }
+    
+    // Direct/Extend accessors
     const llvm::Type *getCoerceToType() const {
-      assert(TheKind == Coerce && "Invalid kind!");
+      assert(canHaveCoerceToType() && "Invalid kind!");
       return TypeData;
     }
-
+    
+    void setCoerceToType(const llvm::Type *T) {
+      assert(canHaveCoerceToType() && "Invalid kind!");
+      TypeData = T;
+    }
     // Indirect accessors
     unsigned getIndirectAlign() const {
       assert(TheKind == Indirect && "Invalid kind!");
index f0e107973c1938a5728887b852ce4d43015ec97b..94cfd98d07d81d13b401f61d8459db2f3c848ab2 100644 (file)
@@ -245,6 +245,18 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
 
   // Compute ABI information.
   getABIInfo().computeInfo(*FI);
+  
+  // Loop over all of the computed argument and return value info.  If any of
+  // them are direct or extend without a specified coerce type, specify the
+  // default now.
+  ABIArgInfo &RetInfo = FI->getReturnInfo();
+  if (RetInfo.canHaveCoerceToType() && RetInfo.getCoerceToType() == 0)
+    RetInfo.setCoerceToType(ConvertTypeRecursive(FI->getReturnType()));
+  
+  for (CGFunctionInfo::arg_iterator I = FI->arg_begin(), E = FI->arg_end();
+       I != E; ++I)
+    if (I->info.canHaveCoerceToType() && I->info.getCoerceToType() == 0)
+      I->info.setCoerceToType(ConvertTypeRecursive(I->type));
 
   // If this is a top-level call and ConvertTypeRecursive hit unresolved pointer
   // types, resolve them now.  These pointers may point to this function, which
@@ -592,7 +604,7 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
 
   case ABIArgInfo::Extend:
   case ABIArgInfo::Direct:
-    ResultType = ConvertType(RetTy, IsRecursive);
+    ResultType = RetAI.getCoerceToType();
     break;
 
   case ABIArgInfo::Indirect: {
@@ -606,10 +618,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
   case ABIArgInfo::Ignore:
     ResultType = llvm::Type::getVoidTy(getLLVMContext());
     break;
-
-  case ABIArgInfo::Coerce:
-    ResultType = RetAI.getCoerceToType();
-    break;
   }
 
   for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
@@ -620,7 +628,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
     case ABIArgInfo::Ignore:
       break;
 
-    case ABIArgInfo::Coerce: {
+    case ABIArgInfo::Indirect: {
+      // indirect arguments are always on the stack, which is addr space #0.
+      const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
+      ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
+      break;
+    }
+
+    case ABIArgInfo::Extend:
+    case ABIArgInfo::Direct:
       // If the coerce-to type is a first class aggregate, flatten it.  Either
       // way is semantically identical, but fast-isel and the optimizer
       // generally likes scalar values better than FCAs.
@@ -632,19 +648,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
         ArgTys.push_back(ArgTy);
       }
       break;
-    }
-
-    case ABIArgInfo::Indirect: {
-      // indirect arguments are always on the stack, which is addr space #0.
-      const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
-      ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
-      break;
-    }
-
-    case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct:
-      ArgTys.push_back(ConvertType(it->type, IsRecursive));
-      break;
 
     case ABIArgInfo::Expand:
       GetExpandedTypes(it->type, ArgTys, IsRecursive);
@@ -713,8 +716,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
      RetAttrs |= llvm::Attribute::SExt;
    else if (RetTy->hasUnsignedIntegerRepresentation())
      RetAttrs |= llvm::Attribute::ZExt;
-   // FALLTHROUGH
+    break;
   case ABIArgInfo::Direct:
+  case ABIArgInfo::Ignore:
     break;
 
   case ABIArgInfo::Indirect:
@@ -726,10 +730,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
                    llvm::Attribute::ReadNone);
     break;
 
-  case ABIArgInfo::Ignore:
-  case ABIArgInfo::Coerce:
-    break;
-
   case ABIArgInfo::Expand:
     assert(0 && "Invalid ABI kind for return argument");
   }
@@ -752,42 +752,37 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
     // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
     // have the corresponding parameter variable.  It doesn't make
     // sense to do it here because parameters are so fucked up.
-
     switch (AI.getKind()) {
-    case ABIArgInfo::Coerce:
-      if (const llvm::StructType *STy =
-          dyn_cast<llvm::StructType>(AI.getCoerceToType()))
-        Index += STy->getNumElements();
-      else
-        ++Index;
-      continue;  // Skip index increment.
-
-    case ABIArgInfo::Indirect:
-      if (AI.getIndirectByVal())
-        Attributes |= llvm::Attribute::ByVal;
-
-      Attributes |=
-        llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
-      // byval disables readnone and readonly.
-      FuncAttrs &= ~(llvm::Attribute::ReadOnly |
-                     llvm::Attribute::ReadNone);
-      break;
-
     case ABIArgInfo::Extend:
       if (ParamType->isSignedIntegerType())
         Attributes |= llvm::Attribute::SExt;
       else if (ParamType->isUnsignedIntegerType())
         Attributes |= llvm::Attribute::ZExt;
-     // FALLS THROUGH
+      // FALL THROUGH
     case ABIArgInfo::Direct:
       if (RegParm > 0 &&
           (ParamType->isIntegerType() || ParamType->isPointerType())) {
         RegParm -=
-          (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
+        (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
         if (RegParm >= 0)
           Attributes |= llvm::Attribute::InReg;
       }
       // FIXME: handle sseregparm someday...
+        
+      if (const llvm::StructType *STy =
+            dyn_cast<llvm::StructType>(AI.getCoerceToType()))
+        Index += STy->getNumElements()-1;  // 1 will be added below.
+      break;
+
+    case ABIArgInfo::Indirect:
+      if (AI.getIndirectByVal())
+        Attributes |= llvm::Attribute::ByVal;
+
+      Attributes |=
+        llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
+      // byval disables readnone and readonly.
+      FuncAttrs &= ~(llvm::Attribute::ReadOnly |
+                     llvm::Attribute::ReadNone);
       break;
 
     case ABIArgInfo::Ignore:
@@ -871,15 +866,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
 
     case ABIArgInfo::Extend:
     case ABIArgInfo::Direct: {
-      assert(AI != Fn->arg_end() && "Argument mismatch!");
-      llvm::Value *V = AI;
-      if (hasAggregateLLVMType(Ty)) {
-        // Create a temporary alloca to hold the argument; the rest of
-        // codegen expects to access aggregates & complex values by
-        // reference.
-        V = CreateMemTemp(Ty);
-        Builder.CreateStore(AI, V);
-      } else {
+      // If we have the trivial case, handle it with no muss and fuss.
+      if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
+          ArgI.getCoerceToType() == ConvertType(Ty)) {
+        assert(AI != Fn->arg_end() && "Argument mismatch!");
+        llvm::Value *V = AI;
+        
         if (Arg->getType().isRestrictQualified())
           AI->addAttr(llvm::Attribute::NoAlias);
 
@@ -888,40 +880,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
           // "void a(x) short x; {..."
           V = EmitScalarConversion(V, Ty, Arg->getType());
         }
+        EmitParmDecl(*Arg, V);
+        break;
       }
-      EmitParmDecl(*Arg, V);
-      break;
-    }
 
-    case ABIArgInfo::Expand: {
-      // If this structure was expanded into multiple arguments then
-      // we need to create a temporary and reconstruct it from the
-      // arguments.
-      llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
-      // FIXME: What are the right qualifiers here?
-      llvm::Function::arg_iterator End =
-        ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
-      EmitParmDecl(*Arg, Temp);
-
-      // Name the arguments used in expansion and increment AI.
-      unsigned Index = 0;
-      for (; AI != End; ++AI, ++Index)
-        AI->setName(Arg->getName() + "." + llvm::Twine(Index));
-      continue;
-    }
-
-    case ABIArgInfo::Ignore:
-      // Initialize the local variable appropriately.
-      if (hasAggregateLLVMType(Ty)) {
-        EmitParmDecl(*Arg, CreateMemTemp(Ty));
-      } else {
-        EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
-      }
-
-      // Skip increment, no matching LLVM parameter.
-      continue;
-
-    case ABIArgInfo::Coerce: {
       llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce");
       
       // The alignment we need to use is the max of the requested alignment for
@@ -968,6 +930,33 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
       EmitParmDecl(*Arg, V);
       continue;  // Skip ++AI increment, already done.
     }
+
+    case ABIArgInfo::Expand: {
+      // If this structure was expanded into multiple arguments then
+      // we need to create a temporary and reconstruct it from the
+      // arguments.
+      llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
+      // FIXME: What are the right qualifiers here?
+      llvm::Function::arg_iterator End =
+        ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
+      EmitParmDecl(*Arg, Temp);
+
+      // Name the arguments used in expansion and increment AI.
+      unsigned Index = 0;
+      for (; AI != End; ++AI, ++Index)
+        AI->setName(Arg->getName() + "." + llvm::Twine(Index));
+      continue;
+    }
+
+    case ABIArgInfo::Ignore:
+      // Initialize the local variable appropriately.
+      if (hasAggregateLLVMType(Ty))
+        EmitParmDecl(*Arg, CreateMemTemp(Ty));
+      else
+        EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
+
+      // Skip increment, no matching LLVM parameter.
+      continue;
     }
 
     ++AI;
@@ -1001,38 +990,39 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
     break;
 
   case ABIArgInfo::Extend:
-  case ABIArgInfo::Direct: {
-    // The internal return value temp always will have pointer-to-return-type
-    // type, just do a load.
-      
-    // If the instruction right before the insertion point is a store to the
-    // return value, we can elide the load, zap the store, and usually zap the
-    // alloca.
-    llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
-    llvm::StoreInst *SI = 0;
-    if (InsertBB->empty() || 
-        !(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
-        SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
-      RV = Builder.CreateLoad(ReturnValue);
-    } else {
-      // Get the stored value and nuke the now-dead store.
-      RetDbgLoc = SI->getDebugLoc();
-      RV = SI->getValueOperand();
-      SI->eraseFromParent();
-      
-      // If that was the only use of the return value, nuke it as well now.
-      if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
-        cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
-        ReturnValue = 0;
+  case ABIArgInfo::Direct:
+    
+    if (RetAI.getCoerceToType() == ConvertType(RetTy)) {
+      // The internal return value temp always will have pointer-to-return-type
+      // type, just do a load.
+        
+      // If the instruction right before the insertion point is a store to the
+      // return value, we can elide the load, zap the store, and usually zap the
+      // alloca.
+      llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
+      llvm::StoreInst *SI = 0;
+      if (InsertBB->empty() || 
+          !(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
+          SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
+        RV = Builder.CreateLoad(ReturnValue);
+      } else {
+        // Get the stored value and nuke the now-dead store.
+        RetDbgLoc = SI->getDebugLoc();
+        RV = SI->getValueOperand();
+        SI->eraseFromParent();
+        
+        // If that was the only use of the return value, nuke it as well now.
+        if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
+          cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
+          ReturnValue = 0;
+        }
       }
+    } else {
+      RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
     }
     break;
-  }
-  case ABIArgInfo::Ignore:
-    break;
 
-  case ABIArgInfo::Coerce:
-    RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
+  case ABIArgInfo::Ignore:
     break;
 
   case ABIArgInfo::Expand:
@@ -1145,24 +1135,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
       }
       break;
 
-    case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct:
-      if (RV.isScalar()) {
-        Args.push_back(RV.getScalarVal());
-      } else if (RV.isComplex()) {
-        llvm::Value *Tmp = llvm::UndefValue::get(ConvertType(I->second));
-        Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().first, 0);
-        Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().second, 1);
-        Args.push_back(Tmp);
-      } else {
-        Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
-      }
-      break;
-
     case ABIArgInfo::Ignore:
       break;
+        
+    case ABIArgInfo::Extend:
+    case ABIArgInfo::Direct: {
+      if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
+          ArgInfo.getCoerceToType() == ConvertType(info_it->type)) {
+        if (RV.isScalar())
+          Args.push_back(RV.getScalarVal());
+        else
+          Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
+        break;
+      }
 
-    case ABIArgInfo::Coerce: {
       // FIXME: Avoid the conversion through memory if possible.
       llvm::Value *SrcPtr;
       if (RV.isScalar()) {
@@ -1286,32 +1272,33 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
       return RValue::getAggregate(Args[0]);
     return RValue::get(EmitLoadOfScalar(Args[0], false, RetTy));
 
-  case ABIArgInfo::Extend:
-  case ABIArgInfo::Direct:
-    if (RetTy->isAnyComplexType()) {
-      llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
-      llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
-      return RValue::getComplex(std::make_pair(Real, Imag));
-    }
-    if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
-      llvm::Value *DestPtr = ReturnValue.getValue();
-      bool DestIsVolatile = ReturnValue.isVolatile();
-
-      if (!DestPtr) {
-        DestPtr = CreateMemTemp(RetTy, "agg.tmp");
-        DestIsVolatile = false;
-      }
-      Builder.CreateStore(CI, DestPtr, DestIsVolatile);
-      return RValue::getAggregate(DestPtr);
-    }
-    return RValue::get(CI);
-
   case ABIArgInfo::Ignore:
     // If we are ignoring an argument that had a result, make sure to
     // construct the appropriate return value for our caller.
     return GetUndefRValue(RetTy);
+    
+  case ABIArgInfo::Extend:
+  case ABIArgInfo::Direct: {
+    if (RetAI.getCoerceToType() == ConvertType(RetTy)) {
+      if (RetTy->isAnyComplexType()) {
+        llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
+        llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
+        return RValue::getComplex(std::make_pair(Real, Imag));
+      }
+      if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+        llvm::Value *DestPtr = ReturnValue.getValue();
+        bool DestIsVolatile = ReturnValue.isVolatile();
 
-  case ABIArgInfo::Coerce: {
+        if (!DestPtr) {
+          DestPtr = CreateMemTemp(RetTy, "agg.tmp");
+          DestIsVolatile = false;
+        }
+        Builder.CreateStore(CI, DestPtr, DestIsVolatile);
+        return RValue::getAggregate(DestPtr);
+      }
+      return RValue::get(CI);
+    }
+      
     llvm::Value *DestPtr = ReturnValue.getValue();
     bool DestIsVolatile = ReturnValue.isVolatile();
     
index c7f48e6c9dd429778c1223216e30fbf555b1cd01..54019f924397aaf4113afcdbc0968af30b96a0a0 100644 (file)
 #ifndef CLANG_CODEGEN_CODEGENTYPES_H
 #define CLANG_CODEGEN_CODEGENTYPES_H
 
+#include "CGCall.h"
+#include "GlobalDecl.h"
 #include "llvm/Module.h"
 #include "llvm/ADT/DenseMap.h"
 #include <vector>
 
-#include "CGCall.h"
-#include "GlobalDecl.h"
-
 namespace llvm {
   class FunctionType;
   class Module;
index e8e4c5c4622c75ea828f7e59a2ff74c77f585c4e..0f0dc0f888acc87ed8c1956afb063017e01445d2 100644 (file)
@@ -56,7 +56,11 @@ void ABIArgInfo::dump() const {
   OS << "(ABIArgInfo Kind=";
   switch (TheKind) {
   case Direct:
-    OS << "Direct";
+    OS << "Direct Type=";
+    if (const llvm::Type *Ty = getCoerceToType())
+      Ty->print(OS);
+    else
+      OS << "null";
     break;
   case Extend:
     OS << "Extend";
@@ -64,10 +68,6 @@ void ABIArgInfo::dump() const {
   case Ignore:
     OS << "Ignore";
     break;
-  case Coerce:
-    OS << "Coerce Type=";
-    getCoerceToType()->print(OS);
-    break;
   case Indirect:
     OS << "Indirect Align=" << getIndirectAlign()
        << " Byal=" << getIndirectByVal();
@@ -451,14 +451,14 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
       // registers and we need to make sure to pick a type the LLVM
       // backend will like.
       if (Size == 128)
-        return ABIArgInfo::getCoerce(llvm::VectorType::get(
+        return ABIArgInfo::getDirect(llvm::VectorType::get(
                   llvm::Type::getInt64Ty(getVMContext()), 2));
 
       // Always return in register if it fits in a general purpose
       // register, or if it is 64 bits and has a single element.
       if ((Size == 8 || Size == 16 || Size == 32) ||
           (Size == 64 && VT->getNumElements() == 1))
-        return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),
+        return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
                                                             Size));
 
       return ABIArgInfo::getIndirect(0);
@@ -491,7 +491,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
           // bit-fields can adjust that to be larger than the single
           // element type.
           uint64_t Size = getContext().getTypeSize(RetTy);
-          return ABIArgInfo::getCoerce(
+          return ABIArgInfo::getDirect(
             llvm::IntegerType::get(getVMContext(), (unsigned)Size));
         }
         
@@ -499,20 +499,20 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
           assert(getContext().getTypeSize(RetTy) ==
                  getContext().getTypeSize(SeltTy) &&
                  "Unexpect single element structure size!");
-          return ABIArgInfo::getCoerce(llvm::Type::getFloatTy(getVMContext()));
+          return ABIArgInfo::getDirect(llvm::Type::getFloatTy(getVMContext()));
         }
         
         if (BT->getKind() == BuiltinType::Double) {
           assert(getContext().getTypeSize(RetTy) ==
                  getContext().getTypeSize(SeltTy) &&
                  "Unexpect single element structure size!");
-          return ABIArgInfo::getCoerce(llvm::Type::getDoubleTy(getVMContext()));
+          return ABIArgInfo::getDirect(llvm::Type::getDoubleTy(getVMContext()));
         }
       } else if (SeltTy->isPointerType()) {
         // FIXME: It would be really nice if this could come out as the proper
         // pointer type.
         const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(getVMContext());
-        return ABIArgInfo::getCoerce(PtrTy);
+        return ABIArgInfo::getDirect(PtrTy);
       } else if (SeltTy->isVectorType()) {
         // 64- and 128-bit vectors are never returned in a
         // register when inside a structure.
@@ -528,7 +528,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
     // in a register.
     if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) {
       uint64_t Size = getContext().getTypeSize(RetTy);
-      return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),Size));
+      return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
     }
 
     return ABIArgInfo::getIndirect(0);
@@ -1139,7 +1139,7 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
       CoerceTo = llvm::Type::getFloatTy(CoerceTo->getContext());
   }
 
-  return ABIArgInfo::getCoerce(CoerceTo);
+  return ABIArgInfo::getDirect(CoerceTo);
 }
 
 ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
@@ -1195,8 +1195,6 @@ const llvm::Type *X86_64ABIInfo::Get16ByteVectorType(QualType Ty) const {
     STy = dyn_cast<llvm::StructType>(IRType);
   }
   
-  
-  
   // If the preferred type is a 16-byte vector, prefer to pass it.
   if (const llvm::VectorType *VT = dyn_cast<llvm::VectorType>(IRType)){
     const llvm::Type *EltTy = VT->getElementType();
@@ -1622,7 +1620,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
                            "reg_save_area");
   if (neededInt && neededSSE) {
     // FIXME: Cleanup.
-    assert(AI.isCoerce() && "Unexpected ABI info for mixed regs");
+    assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
     const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
     llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
     assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
@@ -1948,7 +1946,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
   LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs));
   const llvm::Type* STy = llvm::StructType::get(getVMContext(), LLVMFields,
                                                 true);
-  return ABIArgInfo::getCoerce(STy);
+  return ABIArgInfo::getDirect(STy);
 }
 
 static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
@@ -2064,7 +2062,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
     // FIXME: Consider using 2 x vector types if the back end handles them
     // correctly.
     if (RetTy->isAnyComplexType())
-      return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),
+      return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
                                               getContext().getTypeSize(RetTy)));
 
     // Integer like structures are returned in r0.
@@ -2072,10 +2070,10 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
       // Return in the smallest viable integer type.
       uint64_t Size = getContext().getTypeSize(RetTy);
       if (Size <= 8)
-        return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(getVMContext()));
+        return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
       if (Size <= 16)
-        return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(getVMContext()));
-      return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(getVMContext()));
+        return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+      return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
     }
 
     // Otherwise return in memory.
@@ -2093,10 +2091,10 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
   if (Size <= 32) {
     // Return in the smallest viable integer type.
     if (Size <= 8)
-      return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(getVMContext()));
+      return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
     if (Size <= 16)
-      return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(getVMContext()));
-    return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(getVMContext()));
+      return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+    return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
   }
 
   return ABIArgInfo::getIndirect(0);
index 04447c12d9c1fa16e223221bf8ac63a3a29c3ebc..3bda8875c814181e0610b9a5a49f9b8e181d236c 100644 (file)
@@ -152,10 +152,16 @@ struct f23S f24(struct f23S *X, struct f24s *P2) {
   // CHECK: define %struct.f24s @f24(%struct.f23S* %X, %struct.f24s* %P2)
 }
 
+// rdar://8248065
 typedef float v4f32 __attribute__((__vector_size__(16)));
-
 v4f32 f25(v4f32 X) {
-  // CHECK: define <4 x float> @f25(<4 x float> %X.coerce)
+  // CHECK: define <4 x float> @f25(<4 x float> %X)
+  // CHECK-NOT: alloca
+  // CHECK: %X.addr = alloca <4 x float>
+  // CHECK-NOT: alloca
+  // CHECK: store <4 x float> %X, <4 x float>* %X.addr
+  // CHECK-NOT: store
+  // CHECK: ret <4 x float>
   return X+X;
 }
 
index df0c78ad941eee034d1dfbe8f71546afb2fb4671..6c42bb817095de37b09794be9e14ed2b6bc2daf8 100644 (file)
@@ -23,7 +23,7 @@ struct s3_0 {};
 struct s3_1 { struct s3_0 a; long b; };
 void f3(struct s3_1 x) {}
 
-// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a.coerce)
+// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a)
 // CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1)
 struct s4 {};
 typedef int s4::* s4_mdp;