On Mon, Mar 22, 2021 at 3:04 AM David Edelsohn via Gcc-patches
<[email protected]> 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;
> }