On Mon, Mar 22, 2021 at 3:04 AM David Edelsohn via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > The AIX power alignment rules apply the natural alignment of the > "first member" if it is of a floating-point data type (or is an aggregate > whose recursively "first" member or element is such a type). The alignment > associated with these types for subsequent members use an alignment value > where the floating-point data type is considered to have 4-byte alignment. > > GCC had been stripping array type but had not recursively looked > within structs and unions. This also applies to classes and > subclasses and, therefore, becomes more prominent with C++. > > For example, > > struct A { > double x[2]; > int y; > }; > struct B { > int i; > struct A a; > }; > > struct A has double-word alignment when referenced independently, but > word alignment and offset within struct B despite the alignment of > struct A. If struct A were the first member of struct B, struct B > would have double-word alignment. One must search for the innermost > first member to increase the alignment if double and then search for > the innermost first member to reduce the alignment if the TYPE had > double-word alignment solely because the innermost first member was > double. > > This patch recursively looks through the first member to apply the > double-word alignment to the struct / union as a whole and to apply > the word alignment to the struct or union as a member within a struct > or union. > > This is an ABI change for GCCon AIX, but GCC on AIX had not correctly > implemented the AIX ABI and had not been compatible with the IBM XL > compiler. > > If anyone can double-check that the patch walks the fields correctly > and handles the error conditions correctly, it would be appreciated. > > Bootstrapped on powerpc-ibm-aix7.2.3.0. > > Thanks, David > > * config/rs6000/aix.h (ADJUST_FIELD_ALIGN): Call function. > * config/rs6000/rs6000-protos.h: Declare. > * config/rs6000/rs6000.c: Define. > > index 2db50c8007f..7fccb31307b 100644 > --- a/gcc/config/rs6000/aix.h > +++ b/gcc/config/rs6000/aix.h > @@ -223,10 +223,8 @@ > /* This now supports a natural alignment mode. */ > /* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */ > #define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \ > - ((TARGET_ALIGN_NATURAL == 0 \ > - && (TYPE_MODE (strip_array_types (TYPE)) == DFmode \ > - || TYPE_MODE (strip_array_types (TYPE)) == DCmode)) \ > - ? MIN ((COMPUTED), 32) \ > + (TARGET_ALIGN_NATURAL == 0 \ > + ? rs6000_special_adjust_field_align (TYPE, COMPUTED) > \ > : (COMPUTED)) > > /* AIX increases natural record alignment to doubleword if the first > diff --git a/gcc/config/rs6000/rs6000-protos.h > b/gcc/config/rs6000/rs6000-protos.h > index 203660b0a78..c44fd3d0263 100644 > --- a/gcc/config/rs6000/rs6000-protos.h > +++ b/gcc/config/rs6000/rs6000-protos.h > @@ -227,6 +227,7 @@ address_is_prefixed (rtx addr, > #ifdef TREE_CODE > extern unsigned int rs6000_data_alignment (tree, unsigned int, enum > data_align) > ; > extern bool rs6000_special_adjust_field_align_p (tree, unsigned int); > +extern unsigned int rs6000_special_adjust_field_align (tree, unsigned int); > extern unsigned int rs6000_special_round_type_align (tree, unsigned int, > unsigned int); > extern unsigned int darwin_rs6000_special_round_type_align (tree, unsigned > int, > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > index 712dd1c460b..eed51e8d4a2 100644 > --- a/gcc/config/rs6000/rs6000.c > +++ b/gcc/config/rs6000/rs6000.c > @@ -7856,6 +7856,41 @@ rs6000_special_adjust_field_align_p (tree type, > unsigned > int computed) > return false; > } > > +/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */ > + > +unsigned int > +rs6000_special_adjust_field_align (tree type, unsigned int computed) > +{ > + /* If RECORD or UNION, recursively find the first field. */ > + while (TREE_CODE (type) == RECORD_TYPE > + || TREE_CODE (type) == UNION_TYPE > + || TREE_CODE (type) == QUAL_UNION_TYPE)
RECORD_OR_UNION_TYPE_P (type) > + { > + tree field = TYPE_FIELDS (type); > + > + /* Skip all non field decls */ > + while (field != NULL > + && (TREE_CODE (field) != FIELD_DECL > + || DECL_FIELD_ABI_IGNORED (field))) > + field = DECL_CHAIN (field); > + > + if (field != NULL && field != type) when is the field (a FIELD_DECL) ever pointer equal to the containing record type? Unless you ment to check for sth specific I suggest to drop field != type. > + type = TREE_TYPE (field); > + else > + break; > + } > + > + /* Strip arrays. */ > + while (TREE_CODE (type) == ARRAY_TYPE) > + type = TREE_TYPE (type); > + > + if (type != error_mark_node > + && (TYPE_MODE (type) == DFmode || TYPE_MODE (type) == DCmode)) > + computed = MIN (computed, 32); > + > + return computed; > +} > + > /* AIX increases natural record alignment to doubleword if the first > field is an FP double while the FP fields remain word aligned. */ > @@ -7864,25 +7899,33 @@ rs6000_special_round_type_align (tree type,unsigned > int > computed, > unsigned int specified) > { > unsigned int align = MAX (computed, specified); > - tree field = TYPE_FIELDS (type); > > - /* Skip all non field decls */ > - while (field != NULL > - && (TREE_CODE (field) != FIELD_DECL > - || DECL_FIELD_ABI_IGNORED (field))) > - field = DECL_CHAIN (field); > - > - if (field != NULL && field != type) > + /* If RECORD or UNION, recursively find the first field. */ > + while (TREE_CODE (type) == RECORD_TYPE > + || TREE_CODE (type) == UNION_TYPE > + || TREE_CODE (type) == QUAL_UNION_TYPE) same as above > { > - type = TREE_TYPE (field); > - while (TREE_CODE (type) == ARRAY_TYPE) > - type = TREE_TYPE (type); > + tree field = TYPE_FIELDS (type); > + > + /* Skip all non field decls */ > + while (field != NULL > + && (TREE_CODE (field) != FIELD_DECL > + || DECL_FIELD_ABI_IGNORED (field))) > + field = DECL_CHAIN (field); > > - if (type != error_mark_node > - && (TYPE_MODE (type) == DFmode || TYPE_MODE (type) == DCmode)) > - align = MAX (align, 64); > + if (field != NULL && field != type) > + type = TREE_TYPE (field); > + else > + break; > } > > + while (TREE_CODE (type) == ARRAY_TYPE) > + type = TREE_TYPE (type); > + > + if (type != error_mark_node > + && (TYPE_MODE (type) == DFmode || TYPE_MODE (type) == DCmode)) > + align = MAX (align, 64); it looks like the changes are duplicate and could see some factoring. Richard. > + > + > return align; > }