[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