https://gcc.gnu.org/g:58dbf143f4d724222c754766d4957f5e099244d9
commit 58dbf143f4d724222c754766d4957f5e099244d9 Author: Alexandre Oliva <ol...@gnu.org> Date: Sat Jan 18 00:40:51 2025 -0300 [ifcombine] avoid bitfield refs that could trap [PR118514] Diff: --- gcc/gimple-fold.cc | 13 +++++++++---- gcc/testsuite/gcc.dg/field-merge-23.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 3c971a29ef04..612810c35b08 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -7686,10 +7686,10 @@ 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). */ + || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (inner))) + || compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)), + bp + bs) < 0 || (INTEGRAL_TYPE_P (TREE_TYPE (inner)) && !type_has_mode_precision_p (TREE_TYPE (inner)))) return NULL_TREE; @@ -7859,6 +7859,11 @@ 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-23.c b/gcc/testsuite/gcc.dg/field-merge-23.c new file mode 100644 index 000000000000..96604d43c9de --- /dev/null +++ b/gcc/testsuite/gcc.dg/field-merge-23.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +/* PR tree-optimization/118514 */ + +/* Check that we don't create BIT_FIELD_REFs that could trap, because they are + assumed not to trap and could be pulled out of loops. */ + +int a, c = 1; +unsigned char b[1], d; +int main() { + while (a || !c) { + signed char e = b[1000000000]; + d = e < 0 || b[1000000000] > 1; + if (d) + __builtin_abort (); + } + return 0; +}