]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[ifcombine] avoid creating out-of-bounds BIT_FIELD_REFs [PR118514]
authorAlexandre Oliva <oliva@adacore.com>
Fri, 7 Feb 2025 11:30:47 +0000 (08:30 -0300)
committerAlexandre Oliva <oliva@gnu.org>
Fri, 7 Feb 2025 11:30:47 +0000 (08:30 -0300)
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.

gcc/gimple-fold.cc
gcc/testsuite/gcc.dg/field-merge-25.c [new file with mode: 0644]
gcc/tree-eh.cc
gcc/tree-eh.h

index 45485782cdf91e6473b16812baabd79a00745565..29191685a43c5a4c00b469797ba608417f16c68d 100644 (file)
@@ -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 (file)
index 0000000..e769b0a
--- /dev/null
@@ -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;
+  }
+}
index 7015189a2de833d71f5826f35db6de72c3d8ee68..a4d59954c059797b5424b6000b92608c68ed608a 100644 (file)
@@ -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.  */
 
index 69fe193f1b82fec912188ccaaac824273ba2b7e5..1fe6de80c42e763009ed978d93a31046dfde6970 100644 (file)
@@ -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 *);