Unlike other access patterns, BIT_FIELD_REFs aren't regarded as
possibly-trapping out of referencing out-of-bounds bits.

So, if decode_field_reference finds a load that could trap, but whose
inner object can't, bail out if it accesses past the inner object's
size.

This may drop some ifcombine optimizations in VLAs, that could be safe
if we managed to reuse the same pre-existing load for both compares, but
those get optimized later (as in the new testcase).  The cases of most
interest are those that merge separate fields, and they necessarily
involve new BIT_FIELD_REFs loads.

Regstrapped on x86_64-linux-gnu.  Ok to install?


for  gcc/ChangeLog

        PR tree-optimization/118514
        * gimple-fold.cc (decode_field_reference): Refuse to consider
        BIT_FIELD_REF of non-trapping object if the original load
        could trap for being out-of-bounds.
        (make_bit_field_ref): Check that replacement loads could trap
        as much as the original loads.

for  gcc/testsuite/ChangeLog

        PR tree-optimization/118514
        * gcc.dg/field-merge-23.c: New.
---
 gcc/gimple-fold.cc                    |   19 +++++++++++++++----
 gcc/testsuite/gcc.dg/field-merge-23.c |   19 +++++++++++++++++++
 2 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/field-merge-23.c

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 3c971a29ef045..41b21ecd58a32 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7686,10 +7686,16 @@ 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).  BIT_FIELD_REFs aren't flagged
+        as tree_could_trap_p just because of out-of-range bits, so don't even
+        try to optimize loads that could trap if they access out-of-range bits
+        of an object that could not trap (PR118514).  */
+      || ((! AGGREGATE_TYPE_P (TREE_TYPE (inner))
+          || (load && tree_could_trap_p (gimple_assign_rhs1 (load))
+              & !tree_could_trap_p (inner)))
+         && (!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 +7865,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 0000000000000..96604d43c9dec
--- /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;
+}

-- 
Alexandre Oliva, happy hacker            https://FSFLA.org/blogs/lxo/
   Free Software Activist                   GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity
Excluding neuro-others for not behaving ""normal"" is *not* inclusive

Reply via email to