On Jan 24, 2025, Richard Biener <richard.guent...@gmail.com> wrote:

> Hmm.  I think when an original ref could trap that should be the
> insertion point (or the original ref should post-dominate the insertion 
> point).

I suppose we could do that, but...  intuitively, it doesn't feel safe to
move a nontrapping load down to combine it with a trapping load either.

> It's fine when an originally may-trap reference becomes not trapping
> (and it really cannot trap).  Introducing new (may-)traps is never OK.

I don't really see how a may-trap reference to a certain range of bits
could possibly become non-trapping by merely reissuing it, so I can't
respond intelligently to your assessment.

> So, can we split the patch to the case with the testcase at hand and
> consider the assert and the extra tree_could_trap_p checks separately?

The approved patch, with the testcase and the simplest fix, is already
in.  I've rebased the additional defensive checks and interface changes
into the following, but I don't have any pressing need of getting them
in: I don't know how to trigger any of the issues tested for.


If decode_field_reference finds a load that accesses past the inner
object's size, bail out.

If loads we're attempting to combine don't have the same trapping
status, bail out, to avoid replacing the wrong load and enabling loads
to be moved that shouldn't.

Regstrapped on x86_64-linux-gnu.  Should I put this in?


for  gcc/ChangeLog

        PR tree-optimization/118514
        * gimple-fold.cc (decode_field_reference): Refuse to consider
        merging out-of-bounds BIT_FIELD_REFs.
        (fold_truth_andor_for_ifcombine): Check that combinable loads
        have the same trapping status.
        * 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.
---
 gcc/gimple-fold.cc |   16 ++++++++++------
 gcc/tree-eh.cc     |   25 +++++++++++++------------
 gcc/tree-eh.h      |    1 +
 3 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 45485782cdf91..24aada4bc8fee 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;
@@ -8228,8 +8226,12 @@ fold_truth_andor_for_ifcombine (enum tree_code code, 
tree truth_type,
       std::swap (rl_loc, rr_loc);
     }
 
+  /* Check that the loads that we're trying to combine have the same vuse and
+     same trapping status.  */
   if ((ll_load && rl_load)
-      ? gimple_vuse (ll_load) != gimple_vuse (rl_load)
+      ? (gimple_vuse (ll_load) != gimple_vuse (rl_load)
+        || (tree_could_trap_p (gimple_assign_rhs1 (ll_load))
+            != tree_could_trap_p (gimple_assign_rhs1 (rl_load))))
       : (!ll_load != !rl_load))
     return 0;
 
@@ -8282,7 +8284,9 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree 
truth_type,
   else if (lr_reversep != rr_reversep
           || ! operand_equal_p (lr_inner, rr_inner, 0)
           || ((lr_load && rr_load)
-              ? gimple_vuse (lr_load) != gimple_vuse (rr_load)
+              ? (gimple_vuse (lr_load) != gimple_vuse (rr_load)
+                 || (tree_could_trap_p (gimple_assign_rhs1 (lr_load))
+                     != tree_could_trap_p (gimple_assign_rhs1 (rr_load))))
               : (!lr_load != !rr_load)))
     return 0;
 
diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc
index 27a4b2b5b1665..68008cea588a7 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 69fe193f1b82f..1fe6de80c42e7 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 *);



-- 
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