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 *);

Reply via email to