https://gcc.gnu.org/g:8c59c0b700c58df2692471166fcfb1012a4d432b
commit 8c59c0b700c58df2692471166fcfb1012a4d432b Author: Alexandre Oliva <ol...@adacore.com> Date: Fri Feb 7 04:14:52 2025 -0300 [ifcombine] avoid creating out-of-bounds BIT_FIELD_REFs [PR118514] If decode_field_reference finds a load that accesses past the inner object's size, bail out. Drop the too-strict assert. for gcc/ChangeLog PR tree-optimization/118514 PR tree-optimization/118706 * gimple-fold.cc (decode_field_reference): Refuse to consider merging out-of-bounds BIT_FIELD_REFs. (make_bit_field_load): Drop too-strict assert. * tree-eh.cc (bit_field_ref_in_bounds_p): Rename to... (access_in_bounds_of_type_p): ... this. Change interface, export. (tree_could_trap_p): Adjust. * tree-eh.h (access_in_bounds_of_type_p): Declare. for gcc/testsuite/ChangeLog PR tree-optimization/118514 PR tree-optimization/118706 * gcc.dg/field-merge-25.c: New. Diff: --- gcc/gimple-fold.cc | 11 ++--------- gcc/testsuite/gcc.dg/field-merge-25.c | 15 +++++++++++++++ gcc/tree-eh.cc | 25 +++++++++++++------------ gcc/tree-eh.h | 1 + 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 45485782cdf9..29191685a43c 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -7686,10 +7686,8 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT *pbitsize, || bs <= shiftrt || offset != 0 || TREE_CODE (inner) == PLACEHOLDER_EXPR - /* Reject out-of-bound accesses (PR79731). */ - || (! AGGREGATE_TYPE_P (TREE_TYPE (inner)) - && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)), - bp + bs) < 0) + /* Reject out-of-bound accesses (PR79731, PR118514). */ + || !access_in_bounds_of_type_p (TREE_TYPE (inner), bs, bp) || (INTEGRAL_TYPE_P (TREE_TYPE (inner)) && !type_has_mode_precision_p (TREE_TYPE (inner)))) return NULL_TREE; @@ -7859,11 +7857,6 @@ make_bit_field_load (location_t loc, tree inner, tree orig_inner, tree type, gimple *new_stmt = gsi_stmt (i); if (gimple_has_mem_ops (new_stmt)) gimple_set_vuse (new_stmt, reaching_vuse); - gcc_checking_assert (! (gimple_assign_load_p (point) - && gimple_assign_load_p (new_stmt)) - || (tree_could_trap_p (gimple_assign_rhs1 (point)) - == tree_could_trap_p (gimple_assign_rhs1 - (new_stmt)))); } gimple_stmt_iterator gsi = gsi_for_stmt (point); diff --git a/gcc/testsuite/gcc.dg/field-merge-25.c b/gcc/testsuite/gcc.dg/field-merge-25.c new file mode 100644 index 000000000000..e769b0ae7b84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/field-merge-25.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-fre" } */ + +/* PR tree-optimization/118706 */ + +int a[1][1][3], b; +int main() { + int c = -1; + while (b) { + if (a[c][c][6]) + break; + if (a[0][0][0]) + break; + } +} diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc index 7015189a2de8..a4d59954c059 100644 --- a/gcc/tree-eh.cc +++ b/gcc/tree-eh.cc @@ -2646,24 +2646,22 @@ range_in_array_bounds_p (tree ref) return true; } -/* Return true iff EXPR, a BIT_FIELD_REF, accesses a bit range that is known to - be in bounds for the referred operand type. */ +/* Return true iff a BIT_FIELD_REF <(TYPE)???, SIZE, OFFSET> would access a bit + range that is known to be in bounds for TYPE. */ -static bool -bit_field_ref_in_bounds_p (tree expr) +bool +access_in_bounds_of_type_p (tree type, poly_uint64 size, poly_uint64 offset) { - tree size_tree; - poly_uint64 size_max, min, wid, max; + tree type_size_tree; + poly_uint64 type_size_max, min = offset, wid = size, max; - size_tree = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0))); - if (!size_tree || !poly_int_tree_p (size_tree, &size_max)) + type_size_tree = TYPE_SIZE (type); + if (!type_size_tree || !poly_int_tree_p (type_size_tree, &type_size_max)) return false; - min = bit_field_offset (expr); - wid = bit_field_size (expr); max = min + wid; if (maybe_lt (max, min) - || maybe_lt (size_max, max)) + || maybe_lt (type_size_max, max)) return false; return true; @@ -2712,7 +2710,10 @@ tree_could_trap_p (tree expr) switch (code) { case BIT_FIELD_REF: - if (DECL_P (TREE_OPERAND (expr, 0)) && !bit_field_ref_in_bounds_p (expr)) + if (DECL_P (TREE_OPERAND (expr, 0)) + && !access_in_bounds_of_type_p (TREE_TYPE (TREE_OPERAND (expr, 0)), + bit_field_size (expr), + bit_field_offset (expr))) return true; /* Fall through. */ diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h index 69fe193f1b82..1fe6de80c42e 100644 --- a/gcc/tree-eh.h +++ b/gcc/tree-eh.h @@ -36,6 +36,7 @@ extern void redirect_eh_dispatch_edge (geh_dispatch *, edge, basic_block); extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool, bool, tree, bool *); extern bool operation_could_trap_p (enum tree_code, bool, bool, tree); +extern bool access_in_bounds_of_type_p (tree, poly_uint64, poly_uint64); extern bool tree_could_trap_p (tree); extern tree rewrite_to_non_trapping_overflow (tree); extern bool stmt_could_throw_p (function *, gimple *);