[llvm-commits] [llvm-gcc-4.2] r85539 - in /llvm-gcc-4.2/trunk/gcc: config/arm/llvm-arm-target.h config/arm/llvm-arm.cpp config/i386/llvm-i386-target.h llvm-abi.h llvm-types.cpp

Bob Wilson bob.wilson at apple.com
Thu Oct 29 16:59:13 PDT 2009


I tried a trivial test case, return int32x4x2_t, and it didn't work.   
I fixed it up enough to handle that, but I'm going to leave it up to  
you to test it more thoroughly.

Thanks again for contributing this.

On Oct 29, 2009, at 4:49 PM, Sandeep Patel wrote:

> Oh, hey, thanks. I was planning to sort out your earlier requests, but
> haven't had solid time in a few days to do so.
>
> deep
>
> On Thu, Oct 29, 2009 at 11:35 PM, Bob Wilson <bob.wilson at apple.com>  
> wrote:
>> Author: bwilson
>> Date: Thu Oct 29 18:35:11 2009
>> New Revision: 85539
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=85539&view=rev
>> Log:
>> Fix ARM AAPCS-VFP return of homogeneous aggregates.  Patch by  
>> Sandeep Patel.
>>
>> Modified:
>>    llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h
>>    llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp
>>    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
>>    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
>>    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
>>
>> Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h?rev=85539&r1=85538&r2=85539&view=diff
>>
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> =====================================================================
>> --- llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h (original)
>> +++ llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h Thu Oct 29  
>> 18:35:11 2009
>> @@ -25,17 +25,17 @@
>>    specification says that varargs functions must use the base  
>> standard
>>    instead of the VFP hard float variant. We check for that with
>>    (isVoid || hasArgList). */
>> -#define TARGET_ADJUST_LLVM_CC(CC,  
>> type)                                \
>> -  {                                                            \
>> -    if (TARGET_AAPCS_BASED)                                    \
>> -      CC = ((TARGET_VFP && TARGET_HARD_FLOAT_ABI &&            \
>> -             ((TYPE_ARG_TYPES(type) == 0) ||                   \
>> -              (TREE_VALUE(tree_last(TYPE_ARG_TYPES(type))) ==  \
>> -               void_type_node))) ?                             \
>> -           CallingConv::ARM_AAPCS_VFP :                        \
>> -           CallingConv::ARM_AAPCS);                            \
>> -    else                                                       \
>> -      CC = CallingConv::ARM_APCS;                              \
>> +#define TARGET_ADJUST_LLVM_CC(CC, type)                       \
>> +  {                                                           \
>> +    if (TARGET_AAPCS_BASED)                                   \
>> +      CC = ((TARGET_VFP && TARGET_HARD_FLOAT_ABI &&           \
>> +             ((TYPE_ARG_TYPES(type) == 0) ||                  \
>> +              (TREE_VALUE(tree_last(TYPE_ARG_TYPES(type))) == \
>> +               void_type_node))) ?                            \
>> +      CallingConv::ARM_AAPCS_VFP :                            \
>> +      CallingConv::ARM_AAPCS);                                \
>> +    else                                                      \
>> +      CC = CallingConv::ARM_APCS;                             \
>>   }
>>
>>  #ifdef LLVM_ABI_H
>> @@ -45,7 +45,7 @@
>>                                              CallingConv::ID&,
>>                                              std::vector<const  
>> Type*>&);
>>
>> -#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, CC,  
>> E)         \
>> +#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, CC, E)    \
>>    llvm_arm_should_pass_aggregate_in_mixed_regs((T), (TY), (CC), (E))
>>
>>  extern
>> @@ -53,9 +53,35 @@
>>                                                  std::vector<const  
>> Type*>&,
>>                                                  bool,  
>> CallingConv::ID&);
>>
>> -#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE, ISR,  
>> CC)                \
>> +#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE, ISR, CC)   \
>>    llvm_arm_aggregate_partially_passed_in_regs((E), (SE), (ISR),  
>> (CC))
>>
>> +extern const Type *llvm_arm_aggr_type_for_struct_return(tree type,
>> +                                                         
>> CallingConv::ID &CC);
>> +
>> +/* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
>> +  returned as an aggregate, otherwise return NULL. */
>> +#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X, CC) \
>> +    llvm_arm_aggr_type_for_struct_return((X), (CC))
>> +
>> +extern void llvm_arm_extract_multiple_return_value(Value *Src,  
>> Value *Dest,
>> +                                                   bool isVolatile,
>> +                                                   LLVMBuilder &B);
>> +
>> +/* LLVM_EXTRACT_MULTIPLE_RETURN_VALUE - Extract multiple return  
>> value from
>> +  SRC and assign it to DEST. */
>> +#define LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Src,Dest,V,B)       \
>> +    llvm_arm_extract_multiple_return_value((Src),(Dest),(V),(B))
>> +
>> +extern
>> +bool llvm_arm_should_pass_or_return_aggregate_in_regs(tree TreeType,
>> +                                                       
>> CallingConv::ID &CC);
>> +
>> +/* LLVM_SHOULD_NOT_USE_SHADOW_RETURN = Return true is the given  
>> type should
>> +  not be returned via a shadow parameter with the given calling  
>> conventions. */
>> +#define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \
>> +    llvm_arm_should_pass_or_return_aggregate_in_regs((X), (CC))
>> +
>>  #endif /* LLVM_ABI_H */
>>  #endif /* ENABLE_LLVM */
>>  /* LLVM LOCAL end (ENTIRE FILE!)  */
>>
>> Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp?rev=85539&r1=85538&r2=85539&view=diff
>>
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> =====================================================================
>> --- llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp (original)
>> +++ llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp Thu Oct 29  
>> 18:35:11 2009
>> @@ -2524,24 +2524,14 @@
>>  llvm_arm_should_pass_aggregate_in_mixed_regs(tree TreeType, const  
>> Type *Ty,
>>                                              CallingConv::ID &CC,
>>                                              std::vector<const  
>> Type*> &Elts) {
>> -  // Homogeneous aggregates are an AAPCS-VFP feature.
>> -  if ((CC != CallingConv::ARM_AAPCS_VFP) ||
>> -      !(TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT_ABI))
>> +  if (!llvm_arm_should_pass_or_return_aggregate_in_regs(TreeType,  
>> CC))
>>     return false;
>>
>> -  // Alas, we can't use LLVM Types to figure this out because we  
>> need to
>> -  // examine unions closely.  We'll have to walk the GCC TreeType.
>> -  int fdt_counts[ARM_FDT_MAX] = { 0 };
>> -  bool result = false;
>> -  result = vfp_arg_homogeneous_aggregate_p(TYPE_MODE(TreeType),  
>> TreeType,
>> -                                           fdt_counts);
>> -
>>   // Walk Ty and push LLVM types corresponding to register types onto
>>   // Elts.
>> -  if (result)
>> -    push_elts(Ty, Elts);
>> +  push_elts(Ty, Elts);
>>
>> -  return result;
>> +  return true;
>>  }
>>
>>  static bool alloc_next_spr(bool *SPRs)
>> @@ -2645,4 +2635,124 @@
>>   return false;                            // it all fit in  
>> registers!
>>  }
>>
>> +// Return LLVM Type if TYPE can be returned as an aggregate,
>> +// otherwise return NULL.
>> +const Type *llvm_arm_aggr_type_for_struct_return(tree TreeType,
>> +                                                 CallingConv::ID  
>> &CC) {
>> +  if (!llvm_arm_should_pass_or_return_aggregate_in_regs(TreeType,  
>> CC))
>> +    return NULL;
>> +
>> +  // Walk Ty and push LLVM types corresponding to register types  
>> onto
>> +  // Elts.
>> +  std::vector<const Type*> Elts;
>> +  const Type *Ty = ConvertType(TreeType);
>> +  push_elts(Ty, Elts);
>> +
>> +  return StructType::get(Context, Elts, false);
>> +}
>> +
>> +// llvm_arm_extract_mrv_array_element - Helper function that helps  
>> extract
>> +// an array element from multiple return value.
>> +//
>> +// Here, SRC is returning multiple values. DEST's DESTFIELDNO  
>> field is an array.
>> +// Extract SRCFIELDNO's ELEMENO value and store it in DEST's  
>> FIELDNO field's
>> +// ELEMENTNO.
>> +//
>> +static void llvm_arm_extract_mrv_array_element(Value *Src, Value  
>> *Dest,
>> +                                               unsigned SrcFieldNo,
>> +                                               unsigned SrcElemNo,
>> +                                               unsigned DestFieldNo,
>> +                                               unsigned DestElemNo,
>> +                                               LLVMBuilder &Builder,
>> +                                               bool isVolatile) {
>> +  Value *EVI = Builder.CreateExtractValue(Src, SrcFieldNo,  
>> "mrv_gr");
>> +  const StructType *STy = cast<StructType>(Src->getType());
>> +  llvm::Value *Idxs[3];
>> +  Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
>> +  Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context),  
>> DestFieldNo);
>> +  Idxs[2] = ConstantInt::get(llvm::Type::getInt32Ty(Context),  
>> DestElemNo);
>> +  Value *GEP = Builder.CreateGEP(Dest, Idxs, Idxs+3, "mrv_gep");
>> +  if (isa<VectorType>(STy->getElementType(SrcFieldNo))) {
>> +    Value *ElemIndex = ConstantInt::get(Type::getInt32Ty(Context),  
>> SrcElemNo);
>> +    Value *EVIElem = Builder.CreateExtractElement(EVI, ElemIndex,  
>> "mrv");
>> +    Builder.CreateStore(EVIElem, GEP, isVolatile);
>> +  } else {
>> +    Builder.CreateStore(EVI, GEP, isVolatile);
>> +  }
>> +}
>> +
>> +// llvm_arm_extract_multiple_return_value - Extract multiple  
>> values returned
>> +// by SRC and store them in DEST. It is expected that SRC and
>> +// DEST types are StructType, but they may not match.
>> +void llvm_arm_extract_multiple_return_value(Value *Src, Value *Dest,
>> +                                            bool isVolatile,
>> +                                            LLVMBuilder &Builder) {
>> +
>> +  const StructType *STy = cast<StructType>(Src->getType());
>> +  unsigned NumElements = STy->getNumElements();
>> +
>> +  const PointerType *PTy = cast<PointerType>(Dest->getType());
>> +  const StructType *DestTy = cast<StructType>(PTy->getElementType 
>> ());
>> +
>> +  unsigned SNO = 0;
>> +  unsigned DNO = 0;
>> +
>> +  while (SNO < NumElements) {
>> +
>> +    const Type *DestElemType = DestTy->getElementType(DNO);
>> +
>> +    // Directly access first class values.
>> +    if (DestElemType->isSingleValueType()) {
>> +      Value *GEP = Builder.CreateStructGEP(Dest, DNO, "mrv_gep");
>> +      Value *EVI = Builder.CreateExtractValue(Src, SNO, "mrv_gr");
>> +      Builder.CreateStore(EVI, GEP, isVolatile);
>> +      ++DNO; ++SNO;
>> +      continue;
>> +    }
>> +
>> +    // Access array elements individually. Note, Src and Dest type  
>> may
>> +    // not match. For example { <2 x float>, float } and { float 
>> [3]; }
>> +    const ArrayType *ATy = cast<ArrayType>(DestElemType);
>> +    unsigned ArraySize = ATy->getNumElements();
>> +    unsigned DElemNo = 0; // DestTy's DNO field's element number
>> +    while (DElemNo < ArraySize) {
>> +      unsigned i = 0;
>> +      unsigned Size = 1;
>> +
>> +      if (const VectorType *SElemTy =
>> +          dyn_cast<VectorType>(STy->getElementType(SNO))) {
>> +        Size = SElemTy->getNumElements();
>> +      }
>> +      while (i < Size) {
>> +        llvm_arm_extract_mrv_array_element(Src, Dest, SNO, i++,
>> +                                           DNO, DElemNo++,
>> +                                           Builder, isVolatile);
>> +      }
>> +      // Consumed this src field. Try next one.
>> +      ++SNO;
>> +    }
>> +    // Finished building current dest field.
>> +    ++DNO;
>> +  }
>> +}
>> +
>> +// Target hook for llvm-abi.h for  
>> LLVM_SHOULD_NOT_USE_SHADOW_RETURN and is
>> +// also a utility function used for other target hooks in this  
>> file. Returns
>> +// true if the aggregate should be passed or returned in registers.
>> +bool llvm_arm_should_pass_or_return_aggregate_in_regs(tree TreeType,
>> +                                                       
>> CallingConv::ID &CC) {
>> +  // Homogeneous aggregates are an AAPCS-VFP feature.
>> +  if ((CC != CallingConv::ARM_AAPCS_VFP) ||
>> +      !(TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT_ABI))
>> +    return false;
>> +
>> +  // Alas, we can't use LLVM Types to figure this out because we  
>> need to
>> +  // examine unions closely.  We'll have to walk the GCC TreeType.
>> +  int fdt_counts[ARM_FDT_MAX] = { 0 };
>> +  bool result = false;
>> +  result = vfp_arg_homogeneous_aggregate_p(TYPE_MODE(TreeType),  
>> TreeType,
>> +                                           fdt_counts);
>> +  return result;
>> +}
>> +
>>  /* LLVM LOCAL end (ENTIRE FILE!)  */
>>
>> Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h?rev=85539&r1=85538&r2=85539&view=diff
>>
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> =====================================================================
>> --- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h (original)
>> +++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h Thu Oct  
>> 29 18:35:11 2009
>> @@ -139,7 +139,7 @@
>>
>>  /* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
>>    returned as an aggregate, otherwise return NULL. */
>> -#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X) \
>> +#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X, CC) \
>>   llvm_x86_aggr_type_for_struct_return(X)
>>
>>  extern void llvm_x86_extract_multiple_return_value(Value *Src,  
>> Value *Dest,
>>
>> Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=85539&r1=85538&r2=85539&view=diff
>>
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> =====================================================================
>> --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
>> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Thu Oct 29 18:35:11 2009
>> @@ -126,15 +126,24 @@
>>  false
>>  #endif
>>
>> +// LLVM_SHOULD_NOT_USE_SHADOW_RETURN - A hook to allow aggregates  
>> to be
>> +// returned in registers.
>> +#ifndef LLVM_SHOULD_NOT_USE_SHADOW_RETURN
>> +#define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \
>> + false
>> +#endif
>> +
>>  // doNotUseShadowReturn - Return true if the specified GCC type
>>  // should not be returned using a pointer to struct parameter.
>> -static inline bool doNotUseShadowReturn(tree type, tree fndecl) {
>> +static inline bool doNotUseShadowReturn(tree type, tree fndecl,
>> +                                        CallingConv::ID CC) {
>>   if (!TYPE_SIZE(type))
>>     return false;
>>   if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST)
>>     return false;
>>   // LLVM says do not use shadow argument.
>> -  if (LLVM_SHOULD_NOT_RETURN_COMPLEX_IN_MEMORY(type))
>> +  if (LLVM_SHOULD_NOT_RETURN_COMPLEX_IN_MEMORY(type) ||
>> +     LLVM_SHOULD_NOT_USE_SHADOW_RETURN(type, CC))
>>     return true;
>>   // GCC says use shadow argument.
>>   if (aggregate_value_p(type, fndecl))
>> @@ -396,7 +405,7 @@
>>     } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
>>       // Return scalar values normally.
>>       C.HandleScalarResult(Ty);
>> -    } else if (doNotUseShadowReturn(type, fn)) {
>> +    } else if (doNotUseShadowReturn(type, fn, C.getCallingConv())) {
>>       tree SingleElt = LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR 
>> (type);
>>       if (SingleElt && TYPE_SIZE(SingleElt) &&
>>           TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST &&
>> @@ -406,7 +415,8 @@
>>       } else {
>>         // Otherwise return as an integer value large enough to  
>> hold the entire
>>         // aggregate.
>> -        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN 
>> (type))
>> +        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN 
>> (type,
>> +                                    C.getCallingConv()))
>>           C.HandleAggregateResultAsAggregate(AggrTy);
>>         else if (const Type* ScalarTy =
>>                     LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type,  
>> &Offset))
>> @@ -752,7 +762,7 @@
>>     } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
>>       // Return scalar values normally.
>>       C.HandleScalarResult(Ty);
>> -    } else if (doNotUseShadowReturn(type, fn)) {
>> +    } else if (doNotUseShadowReturn(type, fn, C.getCallingConv())) {
>>       tree SingleElt = LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR 
>> (type);
>>       if (SingleElt && TYPE_SIZE(SingleElt) &&
>>           TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST &&
>> @@ -762,7 +772,8 @@
>>       } else {
>>         // Otherwise return as an integer value large enough to  
>> hold the entire
>>         // aggregate.
>> -        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN 
>> (type))
>> +        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN 
>> (type,
>> +                                    C.getCallingConv()))
>>           C.HandleAggregateResultAsAggregate(AggrTy);
>>         else if (const Type* ScalarTy =
>>                     LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type,  
>> &Offset))
>>
>> Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=85539&r1=85538&r2=85539&view=diff
>>
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> = 
>> =====================================================================
>> --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
>> +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Thu Oct 29 18:35:11 2009
>> @@ -1052,16 +1052,16 @@
>>   tree ReturnType = TREE_TYPE(type);
>>   std::vector<PATypeHolder> ArgTys;
>>   PATypeHolder RetTy(Type::getVoidTy(Context));
>> -
>> +
>>   FunctionTypeConversion Client(RetTy, ArgTys, CallingConv, true / 
>> *K&R*/);
>>   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
>> -
>> -  // Builtins are always prototyped, so this isn't one.
>> -  ABIConverter.HandleReturnType(ReturnType, current_function_decl,  
>> false);
>>
>>  #ifdef TARGET_ADJUST_LLVM_CC
>> -    TARGET_ADJUST_LLVM_CC(CallingConv, type);
>> +  TARGET_ADJUST_LLVM_CC(CallingConv, type);
>>  #endif
>> +
>> +  // Builtins are always prototyped, so this isn't one.
>> +  ABIConverter.HandleReturnType(ReturnType, current_function_decl,  
>> false);
>>
>>   SmallVector<AttributeWithIndex, 8> Attrs;
>>
>> @@ -1118,15 +1118,15 @@
>>   bool isVarArg = false;
>>   FunctionTypeConversion Client(RetTy, ArgTypes, CallingConv, false/ 
>> *not K&R*/);
>>   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
>> -
>> -  ABIConverter.HandleReturnType(TREE_TYPE(type),  
>> current_function_decl,
>> -                                decl ? DECL_BUILT_IN(decl) : false);
>> -
>> +
>>   // Allow the target to set the CC for things like fastcall etc.
>>  #ifdef TARGET_ADJUST_LLVM_CC
>>   TARGET_ADJUST_LLVM_CC(CallingConv, type);
>>  #endif
>>
>> +  ABIConverter.HandleReturnType(TREE_TYPE(type),  
>> current_function_decl,
>> +                                decl ? DECL_BUILT_IN(decl) : false);
>> +
>>   // Compute attributes for return type (and function attributes).
>>   SmallVector<AttributeWithIndex, 8> Attrs;
>>   Attributes FnAttributes = Attribute::None;
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>




More information about the llvm-commits mailing list