Message ID | 20120815235059.GA12536@intel.com |
---|---|
State | New |
Headers | show |
On Thu, Aug 16, 2012 at 1:50 AM, H.J. Lu <hongjiu.lu@intel.com> wrote: > Hi, > > This patch replaces MEMBER_TYPE_FORCES_BLK with a target hook. I > also pass the type to the target hook in addition to field, which will > be used by i386 backend for > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20020 > > This patch doesn't change code generation. Tested on Linux/x86-64. I > also tested cross compilers to ia64-hpux, powerpc-linux and xtensa-linux > up to cc1. OK to install? Isn't the type just always DECL_FIELD_CONTEXT (field)? Btw, with C++ you no longer need ATTRIBUTE_UNUSED, just give the parameter no name. Richard. > Thanks. > > > H.J. > --- > 2012-08-15 H.J. Lu <hongjiu.lu@intel.com> > > * stor-layout.c (compute_record_mode): Replace > MEMBER_TYPE_FORCES_BLK with targetm.member_type_forces_blk. > (layout_type): Likewise. > > * system.h: Poison MEMBER_TYPE_FORCES_BLK. > > * target.def (member_type_forces_blk): New target hook. > > * targhooks.c (default_member_type_forces_blk): New. > * targhooks.h (default_member_type_forces_blk): Likewise. > > * doc/tm.texi.in (MEMBER_TYPE_FORCES_BLK): Renamed to ... > (TARGET_MEMBER_TYPE_FORCES_BLK): This. > * doc/tm.texi: Regenerated. > > * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Removed. > > * config/ia64/ia64.c (ia64_member_type_forces_blk): New > function. > (TARGET_MEMBER_TYPE_FORCES_BLK): New macro. > > * config/rs6000/rs6000.c (TARGET_MEMBER_TYPE_FORCES_BLK): New > macro. > (rs6000_member_type_forces_blk): New function. > > * config/rs6000/rs6000.h (MEMBER_TYPE_FORCES_BLK): Removed. > > * config/xtensa/xtensa.c (xtensa_member_type_forces_blk): New > function. > (TARGET_MEMBER_TYPE_FORCES_BLK): New macro. > > * config/xtensa/xtensa.h (MEMBER_TYPE_FORCES_BLK): Removed. > > diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h > index ad106b4..d9ae109 100644 > --- a/gcc/config/ia64/hpux.h > +++ b/gcc/config/ia64/hpux.h > @@ -115,9 +115,6 @@ do { \ > #define TARGET_DEFAULT \ > (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32) > > -/* ??? Might not be needed anymore. */ > -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode) > - > /* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call, > but that doesn't put out the @function type information which causes > shared library problems. */ > diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c > index c7fb559..f3585b1 100644 > --- a/gcc/config/ia64/ia64.c > +++ b/gcc/config/ia64/ia64.c > @@ -319,6 +319,8 @@ static const char *ia64_invalid_binary_op (int, const_tree, const_tree); > static enum machine_mode ia64_c_mode_for_suffix (char); > static void ia64_trampoline_init (rtx, tree, rtx); > static void ia64_override_options_after_change (void); > +static bool ia64_member_type_forces_blk (const_tree, const_tree, > + enum machine_mode); > > static tree ia64_builtin_decl (unsigned, bool); > > @@ -570,6 +572,9 @@ static const struct attribute_spec ia64_attribute_table[] = > #undef TARGET_GET_RAW_ARG_MODE > #define TARGET_GET_RAW_ARG_MODE ia64_get_reg_raw_mode > > +#undef TARGET_MEMBER_TYPE_FORCES_BLK > +#define TARGET_MEMBER_TYPE_FORCES_BLK ia64_member_type_forces_blk > + > #undef TARGET_GIMPLIFY_VA_ARG_EXPR > #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg > > @@ -11153,6 +11158,17 @@ ia64_get_reg_raw_mode (int regno) > return default_get_reg_raw_mode(regno); > } > > +/* Implement TARGET_MEMBER_TYPE_FORCES_BLK. ??? Might not be needed > + anymore. */ > + > +bool > +ia64_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, > + const_tree field ATTRIBUTE_UNUSED, > + enum machine_mode mode) > +{ > + return TARGET_HPUX && mode == TFmode; > +} > + > /* Always default to .text section until HP-UX linker is fixed. */ > > ATTRIBUTE_UNUSED static section * > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > index 34948fb..5b2d9f0 100644 > --- a/gcc/config/rs6000/rs6000.c > +++ b/gcc/config/rs6000/rs6000.c > @@ -1302,6 +1302,9 @@ static const struct attribute_spec rs6000_attribute_table[] = > #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA > #define TARGET_INIT_DWARF_REG_SIZES_EXTRA rs6000_init_dwarf_reg_sizes_extra > > +#undef TARGET_MEMBER_TYPE_FORCES_BLK > +#define TARGET_MEMBER_TYPE_FORCES_BLK rs6000_member_type_forces_blk > + > /* On rs6000, function arguments are promoted, as are function return > values. */ > #undef TARGET_PROMOTE_FUNCTION_MODE > @@ -7287,6 +7290,27 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) > emit_set: > emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); > } > + > +/* Return true if TYPE containing FIELD should be accessed using > + `BLKMODE'. > + > + For the SPE, simd types are V2SI, and gcc can be tempted to put the > + entire thing in a DI and use subregs to access the internals. > + store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the > + back-end. Because a single GPR can hold a V2SI, but not a DI, the > + best thing to do is set structs to BLKmode and avoid Severe Tire > + Damage. > + > + On e500 v2, DF and DI modes suffer from the same anomaly. DF can > + fit into 1, whereas DI still needs two. */ > + > +static bool > +rs6000_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, > + const_tree field, enum machine_mode mode) > +{ > + return ((TARGET_SPE && TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE) > + || (TARGET_E500_DOUBLE && mode == DFmode)); > +} > > /* Nonzero if we can use a floating-point register to pass this arg. */ > #define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \ > diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h > index ec62fc6..ab26f7f 100644 > --- a/gcc/config/rs6000/rs6000.h > +++ b/gcc/config/rs6000/rs6000.h > @@ -701,22 +701,6 @@ extern unsigned rs6000_pointer_size; > /* Every structure's size must be a multiple of this. */ > #define STRUCTURE_SIZE_BOUNDARY 8 > > -/* Return 1 if a structure or array containing FIELD should be > - accessed using `BLKMODE'. > - > - For the SPE, simd types are V2SI, and gcc can be tempted to put the > - entire thing in a DI and use subregs to access the internals. > - store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the > - back-end. Because a single GPR can hold a V2SI, but not a DI, the > - best thing to do is set structs to BLKmode and avoid Severe Tire > - Damage. > - > - On e500 v2, DF and DI modes suffer from the same anomaly. DF can > - fit into 1, whereas DI still needs two. */ > -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ > - ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \ > - || (TARGET_E500_DOUBLE && (MODE) == DFmode)) > - > /* A bit-field declared as `int' forces `int' alignment for the struct. */ > #define PCC_BITFIELD_TYPE_MATTERS 1 > > diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c > index fa38008..1d69881 100644 > --- a/gcc/config/xtensa/xtensa.c > +++ b/gcc/config/xtensa/xtensa.c > @@ -175,6 +175,9 @@ static reg_class_t xtensa_secondary_reload (bool, rtx, reg_class_t, > static bool constantpool_address_p (const_rtx addr); > static bool xtensa_legitimate_constant_p (enum machine_mode, rtx); > > +static bool xtensa_member_type_forces_blk (const_tree, const_tree, > + enum machine_mode mode); > + > static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = > REG_ALLOC_ORDER; > > @@ -210,6 +213,9 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = > #undef TARGET_ADDRESS_COST > #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 > > +#undef TARGET_MEMBER_TYPE_FORCES_BLK > +#define TARGET_MEMBER_TYPE_FORCES_BLK xtensa_member_type_forces_blk > + > #undef TARGET_BUILD_BUILTIN_VA_LIST > #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list > > @@ -2738,6 +2744,20 @@ xtensa_return_addr (int count, rtx frame) > return result; > } > > +/* Disable the use of word-sized or smaller complex modes for structures, > + and for function arguments in particular, where they cause problems with > + register a7. The xtensa_copy_incoming_a7 function assumes that there is > + a single reference to an argument in a7, but with small complex modes the > + real and imaginary components may be extracted separately, leading to two > + uses of the register, only one of which would be replaced. */ > + > +static bool > +xtensa_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, > + const_tree field ATTRIBUTE_UNUSED, > + enum machine_mode mode) > +{ > + return mode == CQImode || mode == CHImode; > +} > > /* Create the va_list data type. > > diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h > index b1a24c6..50e221a 100644 > --- a/gcc/config/xtensa/xtensa.h > +++ b/gcc/config/xtensa/xtensa.h > @@ -165,15 +165,6 @@ extern unsigned xtensa_current_frame_size; > bitfields and the structures that contain them. */ > #define PCC_BITFIELD_TYPE_MATTERS 1 > > -/* Disable the use of word-sized or smaller complex modes for structures, > - and for function arguments in particular, where they cause problems with > - register a7. The xtensa_copy_incoming_a7 function assumes that there is > - a single reference to an argument in a7, but with small complex modes the > - real and imaginary components may be extracted separately, leading to two > - uses of the register, only one of which would be replaced. */ > -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ > - ((MODE) == CQImode || (MODE) == CHImode) > - > /* Align string constants and constructors to at least a word boundary. > The typical use of this macro is to increase alignment for string > constants to be word aligned so that 'strcpy' calls that copy > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > index 2a2d500..81371de 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -1262,9 +1262,9 @@ these accesses should use the bitfield container type. > The default is @code{!TARGET_STRICT_ALIGN}. > @end deftypefn > > -@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode}) > -Return 1 if a structure or array containing @var{field} should be accessed using > -@code{BLKMODE}. > +@deftypefn {Target Hook} bool TARGET_MEMBER_TYPE_FORCES_BLK (const_tree @var{type}, const_tree @var{field}, enum machine_mode @var{mode}) > +Return true if a structure, union or array @var{type} with @var{mode} > +containing @var{field} should be accessed using @code{BLKMODE}. > > If @var{field} is the only field in the structure, @var{mode} is its > mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the > @@ -1272,7 +1272,7 @@ case where structures of one field would require the structure's mode to > retain the field's mode. > > Normally, this is not needed. > -@end defmac > +@end deftypefn > > @defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified}) > Define this macro as an expression for the alignment of a type (given > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in > index e7d9cec..2888a95 100644 > --- a/gcc/doc/tm.texi.in > +++ b/gcc/doc/tm.texi.in > @@ -1240,9 +1240,9 @@ these accesses should use the bitfield container type. > The default is @code{!TARGET_STRICT_ALIGN}. > @end deftypefn > > -@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode}) > -Return 1 if a structure or array containing @var{field} should be accessed using > -@code{BLKMODE}. > +@hook TARGET_MEMBER_TYPE_FORCES_BLK > +Return true if a structure, union or array @var{type} with @var{mode} > +containing @var{field} should be accessed using @code{BLKMODE}. > > If @var{field} is the only field in the structure, @var{mode} is its > mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the > @@ -1250,7 +1250,7 @@ case where structures of one field would require the structure's mode to > retain the field's mode. > > Normally, this is not needed. > -@end defmac > +@end deftypefn > > @defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified}) > Define this macro as an expression for the alignment of a type (given > diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c > index 53554a9..5679258 100644 > --- a/gcc/stor-layout.c > +++ b/gcc/stor-layout.c > @@ -1627,13 +1627,10 @@ compute_record_mode (tree type) > if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))) > mode = DECL_MODE (field); > > -#ifdef MEMBER_TYPE_FORCES_BLK > - /* With some targets, eg. c4x, it is sub-optimal > - to access an aligned BLKmode structure as a scalar. */ > - > - if (MEMBER_TYPE_FORCES_BLK (field, mode)) > + /* With some targets, it is sub-optimal to access an aligned > + BLKmode structure as a scalar. */ > + if (targetm.member_type_forces_blk (type, field, mode)) > return; > -#endif /* MEMBER_TYPE_FORCES_BLK */ > } > > /* If we only have one real field; use its mode if that mode's size > @@ -2270,9 +2267,7 @@ layout_type (tree type) > TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element); > SET_TYPE_MODE (type, BLKmode); > if (TYPE_SIZE (type) != 0 > -#ifdef MEMBER_TYPE_FORCES_BLK > - && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode) > -#endif > + && ! targetm.member_type_forces_blk (type, type, VOIDmode) > /* BLKmode elements force BLKmode aggregate; > else extract/store fields may lose. */ > && (TYPE_MODE (TREE_TYPE (type)) != BLKmode > diff --git a/gcc/system.h b/gcc/system.h > index 9e7d503..48c9c89 100644 > --- a/gcc/system.h > +++ b/gcc/system.h > @@ -808,7 +808,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; > CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME \ > HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT \ > OUTPUT_ADDR_CONST_EXTRA SMALL_REGISTER_CLASSES ASM_OUTPUT_IDENT \ > - ASM_BYTE_OP > + ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK > > /* Target macros only used for code built for the target, that have > moved to libgcc-tm.h or have never been present elsewhere. */ > diff --git a/gcc/target.def b/gcc/target.def > index 5ac6d48..1bd5533 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -2332,6 +2332,14 @@ DEFHOOK > tree, (tree type, tree expr), > hook_tree_tree_tree_null) > > +/* True if TYPE with MODE containing FIELD should be accessed using > + BLKmode. */ > +DEFHOOK > +(member_type_forces_blk, > + "", > + bool, (const_tree type, const_tree field, enum machine_mode mode), > + default_member_type_forces_blk) > + > /* Return the class for a secondary reload, and fill in extra information. */ > DEFHOOK > (secondary_reload, > diff --git a/gcc/targhooks.c b/gcc/targhooks.c > index 52a9912..a28c421 100644 > --- a/gcc/targhooks.c > +++ b/gcc/targhooks.c > @@ -1513,4 +1513,14 @@ default_pch_valid_p (const void *data_p, size_t len) > return NULL; > } > > +/* Default version of member_type_forces_blk. */ > + > +bool > +default_member_type_forces_blk (const_tree ARG_UNUSED (type), > + const_tree ARG_UNUSED (field), > + enum machine_mode ARG_UNUSED (mode)) > +{ > + return false; > +} > + > #include "gt-targhooks.h" > diff --git a/gcc/targhooks.h b/gcc/targhooks.h > index f1cc403..ac49c82 100644 > --- a/gcc/targhooks.h > +++ b/gcc/targhooks.h > @@ -189,3 +189,5 @@ extern const char *default_pch_valid_p (const void *, size_t); > > extern void default_asm_output_ident_directive (const char*); > > +extern bool default_member_type_forces_blk (const_tree, const_tree, > + enum machine_mode);
diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h index ad106b4..d9ae109 100644 --- a/gcc/config/ia64/hpux.h +++ b/gcc/config/ia64/hpux.h @@ -115,9 +115,6 @@ do { \ #define TARGET_DEFAULT \ (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32) -/* ??? Might not be needed anymore. */ -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode) - /* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call, but that doesn't put out the @function type information which causes shared library problems. */ diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index c7fb559..f3585b1 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -319,6 +319,8 @@ static const char *ia64_invalid_binary_op (int, const_tree, const_tree); static enum machine_mode ia64_c_mode_for_suffix (char); static void ia64_trampoline_init (rtx, tree, rtx); static void ia64_override_options_after_change (void); +static bool ia64_member_type_forces_blk (const_tree, const_tree, + enum machine_mode); static tree ia64_builtin_decl (unsigned, bool); @@ -570,6 +572,9 @@ static const struct attribute_spec ia64_attribute_table[] = #undef TARGET_GET_RAW_ARG_MODE #define TARGET_GET_RAW_ARG_MODE ia64_get_reg_raw_mode +#undef TARGET_MEMBER_TYPE_FORCES_BLK +#define TARGET_MEMBER_TYPE_FORCES_BLK ia64_member_type_forces_blk + #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg @@ -11153,6 +11158,17 @@ ia64_get_reg_raw_mode (int regno) return default_get_reg_raw_mode(regno); } +/* Implement TARGET_MEMBER_TYPE_FORCES_BLK. ??? Might not be needed + anymore. */ + +bool +ia64_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, + const_tree field ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + return TARGET_HPUX && mode == TFmode; +} + /* Always default to .text section until HP-UX linker is fixed. */ ATTRIBUTE_UNUSED static section * diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 34948fb..5b2d9f0 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1302,6 +1302,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA #define TARGET_INIT_DWARF_REG_SIZES_EXTRA rs6000_init_dwarf_reg_sizes_extra +#undef TARGET_MEMBER_TYPE_FORCES_BLK +#define TARGET_MEMBER_TYPE_FORCES_BLK rs6000_member_type_forces_blk + /* On rs6000, function arguments are promoted, as are function return values. */ #undef TARGET_PROMOTE_FUNCTION_MODE @@ -7287,6 +7290,27 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) emit_set: emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); } + +/* Return true if TYPE containing FIELD should be accessed using + `BLKMODE'. + + For the SPE, simd types are V2SI, and gcc can be tempted to put the + entire thing in a DI and use subregs to access the internals. + store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the + back-end. Because a single GPR can hold a V2SI, but not a DI, the + best thing to do is set structs to BLKmode and avoid Severe Tire + Damage. + + On e500 v2, DF and DI modes suffer from the same anomaly. DF can + fit into 1, whereas DI still needs two. */ + +static bool +rs6000_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, + const_tree field, enum machine_mode mode) +{ + return ((TARGET_SPE && TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE) + || (TARGET_E500_DOUBLE && mode == DFmode)); +} /* Nonzero if we can use a floating-point register to pass this arg. */ #define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index ec62fc6..ab26f7f 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -701,22 +701,6 @@ extern unsigned rs6000_pointer_size; /* Every structure's size must be a multiple of this. */ #define STRUCTURE_SIZE_BOUNDARY 8 -/* Return 1 if a structure or array containing FIELD should be - accessed using `BLKMODE'. - - For the SPE, simd types are V2SI, and gcc can be tempted to put the - entire thing in a DI and use subregs to access the internals. - store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the - back-end. Because a single GPR can hold a V2SI, but not a DI, the - best thing to do is set structs to BLKmode and avoid Severe Tire - Damage. - - On e500 v2, DF and DI modes suffer from the same anomaly. DF can - fit into 1, whereas DI still needs two. */ -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ - ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \ - || (TARGET_E500_DOUBLE && (MODE) == DFmode)) - /* A bit-field declared as `int' forces `int' alignment for the struct. */ #define PCC_BITFIELD_TYPE_MATTERS 1 diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index fa38008..1d69881 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -175,6 +175,9 @@ static reg_class_t xtensa_secondary_reload (bool, rtx, reg_class_t, static bool constantpool_address_p (const_rtx addr); static bool xtensa_legitimate_constant_p (enum machine_mode, rtx); +static bool xtensa_member_type_forces_blk (const_tree, const_tree, + enum machine_mode mode); + static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER; @@ -210,6 +213,9 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 +#undef TARGET_MEMBER_TYPE_FORCES_BLK +#define TARGET_MEMBER_TYPE_FORCES_BLK xtensa_member_type_forces_blk + #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list @@ -2738,6 +2744,20 @@ xtensa_return_addr (int count, rtx frame) return result; } +/* Disable the use of word-sized or smaller complex modes for structures, + and for function arguments in particular, where they cause problems with + register a7. The xtensa_copy_incoming_a7 function assumes that there is + a single reference to an argument in a7, but with small complex modes the + real and imaginary components may be extracted separately, leading to two + uses of the register, only one of which would be replaced. */ + +static bool +xtensa_member_type_forces_blk (const_tree type ATTRIBUTE_UNUSED, + const_tree field ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + return mode == CQImode || mode == CHImode; +} /* Create the va_list data type. diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index b1a24c6..50e221a 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -165,15 +165,6 @@ extern unsigned xtensa_current_frame_size; bitfields and the structures that contain them. */ #define PCC_BITFIELD_TYPE_MATTERS 1 -/* Disable the use of word-sized or smaller complex modes for structures, - and for function arguments in particular, where they cause problems with - register a7. The xtensa_copy_incoming_a7 function assumes that there is - a single reference to an argument in a7, but with small complex modes the - real and imaginary components may be extracted separately, leading to two - uses of the register, only one of which would be replaced. */ -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ - ((MODE) == CQImode || (MODE) == CHImode) - /* Align string constants and constructors to at least a word boundary. The typical use of this macro is to increase alignment for string constants to be word aligned so that 'strcpy' calls that copy diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2a2d500..81371de 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1262,9 +1262,9 @@ these accesses should use the bitfield container type. The default is @code{!TARGET_STRICT_ALIGN}. @end deftypefn -@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode}) -Return 1 if a structure or array containing @var{field} should be accessed using -@code{BLKMODE}. +@deftypefn {Target Hook} bool TARGET_MEMBER_TYPE_FORCES_BLK (const_tree @var{type}, const_tree @var{field}, enum machine_mode @var{mode}) +Return true if a structure, union or array @var{type} with @var{mode} +containing @var{field} should be accessed using @code{BLKMODE}. If @var{field} is the only field in the structure, @var{mode} is its mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the @@ -1272,7 +1272,7 @@ case where structures of one field would require the structure's mode to retain the field's mode. Normally, this is not needed. -@end defmac +@end deftypefn @defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified}) Define this macro as an expression for the alignment of a type (given diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index e7d9cec..2888a95 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -1240,9 +1240,9 @@ these accesses should use the bitfield container type. The default is @code{!TARGET_STRICT_ALIGN}. @end deftypefn -@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode}) -Return 1 if a structure or array containing @var{field} should be accessed using -@code{BLKMODE}. +@hook TARGET_MEMBER_TYPE_FORCES_BLK +Return true if a structure, union or array @var{type} with @var{mode} +containing @var{field} should be accessed using @code{BLKMODE}. If @var{field} is the only field in the structure, @var{mode} is its mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the @@ -1250,7 +1250,7 @@ case where structures of one field would require the structure's mode to retain the field's mode. Normally, this is not needed. -@end defmac +@end deftypefn @defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified}) Define this macro as an expression for the alignment of a type (given diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 53554a9..5679258 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1627,13 +1627,10 @@ compute_record_mode (tree type) if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))) mode = DECL_MODE (field); -#ifdef MEMBER_TYPE_FORCES_BLK - /* With some targets, eg. c4x, it is sub-optimal - to access an aligned BLKmode structure as a scalar. */ - - if (MEMBER_TYPE_FORCES_BLK (field, mode)) + /* With some targets, it is sub-optimal to access an aligned + BLKmode structure as a scalar. */ + if (targetm.member_type_forces_blk (type, field, mode)) return; -#endif /* MEMBER_TYPE_FORCES_BLK */ } /* If we only have one real field; use its mode if that mode's size @@ -2270,9 +2267,7 @@ layout_type (tree type) TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element); SET_TYPE_MODE (type, BLKmode); if (TYPE_SIZE (type) != 0 -#ifdef MEMBER_TYPE_FORCES_BLK - && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode) -#endif + && ! targetm.member_type_forces_blk (type, type, VOIDmode) /* BLKmode elements force BLKmode aggregate; else extract/store fields may lose. */ && (TYPE_MODE (TREE_TYPE (type)) != BLKmode diff --git a/gcc/system.h b/gcc/system.h index 9e7d503..48c9c89 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -808,7 +808,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME \ HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT \ OUTPUT_ADDR_CONST_EXTRA SMALL_REGISTER_CLASSES ASM_OUTPUT_IDENT \ - ASM_BYTE_OP + ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK /* Target macros only used for code built for the target, that have moved to libgcc-tm.h or have never been present elsewhere. */ diff --git a/gcc/target.def b/gcc/target.def index 5ac6d48..1bd5533 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2332,6 +2332,14 @@ DEFHOOK tree, (tree type, tree expr), hook_tree_tree_tree_null) +/* True if TYPE with MODE containing FIELD should be accessed using + BLKmode. */ +DEFHOOK +(member_type_forces_blk, + "", + bool, (const_tree type, const_tree field, enum machine_mode mode), + default_member_type_forces_blk) + /* Return the class for a secondary reload, and fill in extra information. */ DEFHOOK (secondary_reload, diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 52a9912..a28c421 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1513,4 +1513,14 @@ default_pch_valid_p (const void *data_p, size_t len) return NULL; } +/* Default version of member_type_forces_blk. */ + +bool +default_member_type_forces_blk (const_tree ARG_UNUSED (type), + const_tree ARG_UNUSED (field), + enum machine_mode ARG_UNUSED (mode)) +{ + return false; +} + #include "gt-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index f1cc403..ac49c82 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -189,3 +189,5 @@ extern const char *default_pch_valid_p (const void *, size_t); extern void default_asm_output_ident_directive (const char*); +extern bool default_member_type_forces_blk (const_tree, const_tree, + enum machine_mode);