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@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits