https://gcc.gnu.org/g:d3da1c5219031e93be3da8c0cf2d972612e86509
commit d3da1c5219031e93be3da8c0cf2d972612e86509 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Wed Feb 5 11:45:00 2025 +0100 Annulation modif dump assumed_rank_12.f90 Diff: --- gcc/fortran/trans-array.cc | 126 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 2 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 90eafe7ffe18..531281049646 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -1085,11 +1085,131 @@ field_count (tree type) } -bool +#if 0 +static bool complete_init_p (tree type, vec<constructor_elt, va_gc> *init_values) { return (unsigned) field_count (type) == vec_safe_length (init_values); } +#endif + + +static int +cmp_wi (const void *x, const void *y) +{ + const offset_int *wix = (const offset_int *) x; + const offset_int *wiy = (const offset_int *) y; + + return wi::cmpu (*wix, *wiy); +} + + +static offset_int +get_offset_bits (tree field) +{ + offset_int field_offset = wi::to_offset (DECL_FIELD_OFFSET (field)); + offset_int field_bit_offset = wi::to_offset (DECL_FIELD_BIT_OFFSET (field)); + unsigned long offset_align = DECL_OFFSET_ALIGN (field); + + return field_offset * offset_align + field_bit_offset; +} + + +static bool +check_cleared_low_bits (const offset_int &val, int bitcount) +{ + if (bitcount == 0) + return true; + + offset_int mask = wi::mask <offset_int> (bitcount, false); + if ((val & mask) != 0) + return false; + + return true; +} + + +static bool +right_shift_if_clear (const offset_int &val, int bitcount, offset_int *result) +{ + if (bitcount == 0) + { + *result = val; + return true; + } + + if (!check_cleared_low_bits (val, bitcount)) + return false; + + *result = val >> bitcount; + return true; +} + + +static bool +contiguous_init_p (tree type, tree value) +{ + gcc_assert (TREE_CODE (value) == CONSTRUCTOR); + auto_vec<offset_int> field_offsets; + int count = field_count (type); + field_offsets.reserve (count); + + tree field = TYPE_FIELDS (type); + offset_int expected_offset = 0; + while (field != NULL_TREE) + { + offset_int field_offset_bits = get_offset_bits (field); + offset_int field_offset; + if (!right_shift_if_clear (field_offset_bits, 3, &field_offset)) + return false; + + offset_int type_size = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (field))); + int align = wi::ctz (type_size); + if (!check_cleared_low_bits (field_offset, align)) + return false; + + if (field_offset != expected_offset) + return false; + + expected_offset += type_size; + field_offsets.quick_push (field_offset); + + field = DECL_CHAIN (field); + } + + auto_vec<offset_int> value_offsets; + value_offsets.reserve (count); + + unsigned i; + tree field_init; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (value), i, field, field_init) + { + if (TREE_TYPE (field) != TREE_TYPE (field_init)) + return false; + + offset_int field_offset_bits = get_offset_bits (field); + offset_int field_offset; + if (!right_shift_if_clear (field_offset_bits, 3, &field_offset)) + return false; + + value_offsets.quick_push (field_offset); + } + + value_offsets.qsort (cmp_wi); + + unsigned idx = 0; + offset_int field_off, val_off; + while (field_offsets.iterate (idx, &field_off) + && value_offsets.iterate (idx, &val_off)) + { + if (val_off != field_off) + return false; + + idx++; + } + + return true; +} static bool @@ -1161,7 +1281,9 @@ init_struct (stmtblock_t *block, tree data_ref, init_kind kind, if (TREE_STATIC (data_ref) || !modifiable_p (data_ref)) DECL_INITIAL (data_ref) = value; - else if (TREE_CODE (value) == CONSTRUCTOR) + else if (TREE_CODE (value) == CONSTRUCTOR + && !(TREE_CONSTANT (value) + && contiguous_init_p (type, value))) { unsigned i; tree field, field_init;