[llvm-commits] [llvm-gcc-4.2] r46412 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h llvm-convert.cpp

Dale Johannesen dalej at apple.com
Sun Jan 27 10:09:24 PST 2008


On Jan 26, 2008, at 11:18 PM, Chris Lattner wrote:

> Author: lattner
> Date: Sun Jan 27 01:18:20 2008
> New Revision: 46412
>
> URL: http://llvm.org/viewvc/llvm-project?rev=46412&view=rev
> Log:
> Change x86-32 aggregate passing code to pass many aggregates "by  
> pieces"
> instead of passing them with byval.  This allows us to get  
> significantly
> better code without affecting the ABI (because x86-32 passes stuff  
> on the
> stack).  Most significantly, we pass _Complex as a two scalar fp  
> values
> now.  For example, before we compiled ccosf to:

Not everything is passed on the stack with -msseregparm, which doesn't  
work now but should.  In that mode a _Complex is not passed the same  
as two scalars.

> _ccosf:
> 	pushl	%ebp
> 	movl	%esp, %ebp
> 	pushl	%edi
> 	pushl	%esi
> 	subl	$16, %esp
> 	movss	12(%ebp), %xmm0
> 	xorps	LCPI1_0, %xmm0
> 	movss	8(%ebp), %xmm1
> 	movss	%xmm0, -16(%ebp)
> 	movss	%xmm1, -12(%ebp)
> 	leal	-16(%ebp), %esi
> 	movl	$2, %ecx
> 	movl	%esp, %edi
> 	rep;movsl
> 	call	_ccoshf
> 	addl	$16, %esp
> 	popl	%esi
> 	popl	%edi
> 	popl	%ebp
> 	ret
>
> now we get:
>
> _ccosf:
> 	pushl	%ebp
> 	movl	%esp, %ebp
> 	subl	$8, %esp
> 	movss	8(%ebp), %xmm0
> 	movss	%xmm0, 4(%esp)
> 	movss	12(%ebp), %xmm0
> 	xorps	LCPI1_0, %xmm0
> 	movss	%xmm0, (%esp)
> 	call	_ccoshf
> 	addl	$8, %esp
> 	popl	%ebp
> 	ret
>
> Evan, please review this.  Thanks!
>
>
> Modified:
>    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
>    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
>    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
>    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
>
> 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=46412&r1=46411&r2=46412&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 Sun Jan 27  
> 01:18:20 2008
> @@ -62,20 +62,24 @@
>     }                                                           \
>   }
>
> -extern bool llvm_x86_should_pass_aggregate_in_memory(tree);
> +#ifdef LLVM_ABI_H
> +extern bool llvm_x86_should_pass_aggregate_in_memory(tree, const  
> Type *);
>
> -#define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X)          \
> -  llvm_x86_should_pass_aggregate_in_memory(X)
> +#define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X, TY)      \
> +  llvm_x86_should_pass_aggregate_in_memory(X, TY)
>
>
> -#ifdef LLVM_ABI_H
> extern bool
> -llvm_x86_64_should_pass_aggregate_in_mixed_regs(tree,
> +llvm_x86_64_should_pass_aggregate_in_mixed_regs(tree, const Type *Ty,
> +                                                std::vector<const  
> Type*>&);
> +extern bool
> +llvm_x86_32_should_pass_aggregate_in_mixed_regs(tree, const Type *Ty,
>                                                 std::vector<const  
> Type*>&);
>
> -#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, E)          \
> -  (TARGET_64BIT &&                                              \
> -   llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (E)))
> +#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY,  
> E)            \
> +   
> (TARGET_64BIT ?                                                     \
> +   llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (TY),  
> (E)) :  \
> +   llvm_x86_32_should_pass_aggregate_in_mixed_regs((T), (TY), (E)))
> #endif /* LLVM_ABI_H */
>
> /* LLVM LOCAL end (ENTIRE FILE!)  */
>
> 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=46412&r1=46411&r2=46412&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 Sun Jan 27  
> 01:18:20 2008
> @@ -691,7 +691,7 @@
>
> /* Target hook for llvm-abi.h. It returns true if an aggregate of the
>    specified type should be passed in memory. */
> -bool llvm_x86_should_pass_aggregate_in_memory(tree TreeType) {
> +bool llvm_x86_should_pass_aggregate_in_memory(tree TreeType, const  
> Type *Ty) {
>   enum machine_mode Mode = ix86_getNaturalModeForType(TreeType);
>   HOST_WIDE_INT Bytes =
>     (Mode == BLKmode) ? int_size_in_bytes(TreeType) : (int)  
> GET_MODE_SIZE(Mode);
> @@ -706,8 +706,10 @@
>     if (llvm_x86_is_all_integer_types(Ty))
>       return false;
>   }
> -  if (!TARGET_64BIT)
> -    return true;
> +  if (!TARGET_64BIT) {
> +    std::vector<const Type*> Elts;
> +    return ! 
> llvm_x86_32_should_pass_aggregate_in_mixed_regs(TreeType, Ty, Elts);
> +  }
>   return llvm_x86_64_should_pass_aggregate_in_memory(TreeType, Mode);
> }
>
> @@ -716,7 +718,7 @@
>    It also returns a vector of types that correspond to the  
> registers used
>    for parameter passing. This is only called for x86-64. */
> bool
> -llvm_x86_64_should_pass_aggregate_in_mixed_regs(tree TreeType,
> +llvm_x86_64_should_pass_aggregate_in_mixed_regs(tree TreeType,  
> const Type *Ty,
>                                                 std::vector<const  
> Type*> &Elts){
>   enum x86_64_reg_class Class[MAX_CLASSES];
>   enum machine_mode Mode = ix86_getNaturalModeForType(TreeType);
> @@ -799,4 +801,45 @@
>   return true;
> }
>
> +/* 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
> + for parameter passing. This is only called for x86-32. */
> +bool
> +llvm_x86_32_should_pass_aggregate_in_mixed_regs(tree TreeType,  
> const Type *Ty,
> +                                                std::vector<const  
> Type*> &Elts){
> +  // If this is a small fixed size type, investigate it.
> +  HOST_WIDE_INT SrcSize = int_size_in_bytes(TreeType);
> +  if (SrcSize <= 0 || SrcSize > 128)
> +    return false;
> +
> +  // X86-32 passes aggregates on the stack.  If this is an  
> extremely simple
> +  // aggregate whose elements would be passed the same if passed as  
> scalars,
> +  // pass them that way in order to promote SROA on the caller and  
> callee side.
> +  // Note that we can't support passing all structs this way.  For  
> example,
> +  // {i16, i16} should be passed in on 32-bit unit, which is not  
> how "i16, i16"
> +  // would be passed as stand-alone arguments.
> +  const StructType *STy = dyn_cast<StructType>(Ty);
> +  if (!STy || STy->isPacked()) return false;
> +
> +  for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
> +    const Type *EltTy = STy->getElementType(i);
> +    // 32 and 64-bit integers are fine, as are float, double, and  
> long double.
> +    if (EltTy == Type::Int32Ty ||
> +        EltTy == Type::Int64Ty ||
> +        EltTy->isFloatingPoint() ||
> +        isa<PointerType>(EltTy)) {
> +      Elts.push_back(EltTy);
> +      continue;
> +    }
> +
> +    // TODO: Vectors are also ok to pass if they don't require  
> extra alignment.
> +    // TODO: We can also pass structs like {i8, i32}.
> +
> +    Elts.clear();
> +    return false;
> +  }
> +
> +  return true;
> +}
> /* LLVM LOCAL end (ENTIRE FILE!)  */
>
> 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=46412&r1=46411&r2=46412&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Sun Jan 27 01:18:20 2008
> @@ -124,7 +124,7 @@
> // value should be passed by value, i.e. passing its address with  
> the byval
> // attribute bit set. The default is false.
> #ifndef LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR
> -#define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X) \
> +#define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X, TY) \
>     false
> #endif
>
> @@ -133,7 +133,7 @@
> // registers. The routine should also return by reference a vector  
> of the
> // types of the registers being used. The default is false.
> #ifndef LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS
> -#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, E) \
> +#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E) \
>     false
> #endif
>
> @@ -212,55 +212,52 @@
>   /// their fields.
>   void HandleArgument(tree type, uint16_t *Attributes = NULL) {
>     const Type *Ty = ConvertType(type);
> -
> +    std::vector<const Type*> Elts;
>     if (isPassedByInvisibleReference(type)) { // variable size -> by- 
> ref.
>       C.HandleScalarArgument(PointerType::getUnqual(Ty), type);
>     } else if (Ty->isFirstClassType()) {
>       C.HandleScalarArgument(Ty, type);
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type)) {
> +    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,  
> Elts)) {
> +      PassInMixedRegisters(type, Ty, Elts);
> +    } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type,  
> Ty)) {
>       C.HandleByValArgument(Ty, type);
>       if (Attributes)
>         *Attributes |= ParamAttr::ByVal;
> -    } else {
> -      std::vector<const Type*> Elts;
> -      if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Elts)) {
> -        PassInMixedRegisters(type, Ty, Elts);
> -      } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
> -        PassInIntegerRegisters(type, Ty);
> -      } else if (isAggregateOfSizeZero(type)) {
> -        // Zero sized aggregate, just drop it!
> -        ;
> -      } else if (TREE_CODE(type) == RECORD_TYPE) {
> -        for (tree Field = TYPE_FIELDS(type); Field; Field =  
> TREE_CHAIN(Field))
> -          if (TREE_CODE(Field) == FIELD_DECL) {
> -            unsigned FNo = GetFieldIndex(Field);
> -            assert(FNo != ~0U && "Case not handled yet!");
> -
> -            C.EnterField(FNo, Ty);
> -            HandleArgument(getDeclaredType(Field));
> -            C.ExitField();
> -          }
> -      } else if (TREE_CODE(type) == COMPLEX_TYPE) {
> -        C.EnterField(0, Ty);
> -        HandleArgument(TREE_TYPE(type));
> -        C.ExitField();
> -        C.EnterField(1, Ty);
> -        HandleArgument(TREE_TYPE(type));
> -        C.ExitField();
> -      } else if ((TREE_CODE(type) == UNION_TYPE) ||
> -                 (TREE_CODE(type) == QUAL_UNION_TYPE)) {
> -        HandleUnion(type);
> -      } else if (TREE_CODE(type) == ARRAY_TYPE) {
> -        const ArrayType *ATy = cast<ArrayType>(Ty);
> -        for (unsigned i = 0, e = ATy->getNumElements(); i != e; + 
> +i) {
> -          C.EnterField(i, Ty);
> -          HandleArgument(TREE_TYPE(type));
> +    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
> +      PassInIntegerRegisters(type, Ty);
> +    } else if (isAggregateOfSizeZero(type)) {
> +      // Zero sized aggregate, just drop it!
> +      ;
> +    } else if (TREE_CODE(type) == RECORD_TYPE) {
> +      for (tree Field = TYPE_FIELDS(type); Field; Field =  
> TREE_CHAIN(Field))
> +        if (TREE_CODE(Field) == FIELD_DECL) {
> +          unsigned FNo = GetFieldIndex(Field);
> +          assert(FNo != ~0U && "Case not handled yet!");
> +
> +          C.EnterField(FNo, Ty);
> +          HandleArgument(getDeclaredType(Field));
>           C.ExitField();
>         }
> -      } else {
> -        assert(0 && "unknown aggregate type!");
> -        abort();
> +    } else if (TREE_CODE(type) == COMPLEX_TYPE) {
> +      C.EnterField(0, Ty);
> +      HandleArgument(TREE_TYPE(type));
> +      C.ExitField();
> +      C.EnterField(1, Ty);
> +      HandleArgument(TREE_TYPE(type));
> +      C.ExitField();
> +    } else if ((TREE_CODE(type) == UNION_TYPE) ||
> +               (TREE_CODE(type) == QUAL_UNION_TYPE)) {
> +      HandleUnion(type);
> +    } else if (TREE_CODE(type) == ARRAY_TYPE) {
> +      const ArrayType *ATy = cast<ArrayType>(Ty);
> +      for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
> +        C.EnterField(i, Ty);
> +        HandleArgument(TREE_TYPE(type));
> +        C.ExitField();
>       }
> +    } else {
> +      assert(0 && "unknown aggregate type!");
> +      abort();
>     }
>   }
>
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=46412&r1=46411&r2=46412&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Sun Jan 27 01:18:20 2008
> @@ -682,7 +682,7 @@
>     const Type *ArgTy = ConvertType(TREE_TYPE(Args));
>     if (isPassedByInvisibleReference(TREE_TYPE(Args)) ||
>         (!ArgTy->isFirstClassType() &&
> -          
> LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(TREE_TYPE(Args)))) {
> +          
> LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(TREE_TYPE(Args),  
> ArgTy))) {
>       // If the value is passed by 'invisible reference' or 'byval  
> reference',
>       // the l-value for the argument IS the argument itself.
>       SET_DECL_LLVM(Args, AI);
>
>
> _______________________________________________
> 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