https://gcc.gnu.org/g:acf7028b79b72176f8ab2f6ebc4dbb9b5fb11a48

commit r16-7923-gacf7028b79b72176f8ab2f6ebc4dbb9b5fb11a48
Author: Jakub Jelinek <[email protected]>
Date:   Fri Mar 6 08:14:09 2026 +0100

    match.pd: Move cast into p+ operand for (ptr) (x p+ y) p+ z -> (ptr) (x p+ 
(y + z)) [PR124358]
    
    The following testcase is miscompiled since my r12-6382 change, because
    it doesn't play well with the gimple_fold_indirect_ref function which uses
    STRIP_NOPS and then has
      /* *(foo *)fooarrptr => (*fooarrptr)[0] */
      if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
          && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == 
INTEGER_CST
          && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
        {
          tree type_domain;
          tree min_val = size_zero_node;
          tree osub = sub;
          sub = gimple_fold_indirect_ref (sub);
          if (! sub)
            sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub);
          type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
          if (TREE_CODE (min_val) == INTEGER_CST)
            return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
        }
    Without the GENERIC
     #if GENERIC
     (simplify
       (pointer_plus (convert:s (pointer_plus:s @0 @1)) @3)
       (convert:type (pointer_plus @0 (plus @1 @3))))
     #endif
    we have INDIRECT_REF of POINTER_PLUS_EXPR with int * type of NOP_EXPR
    to that type of POINTER_PLUS_EXPR with pointer to int[4] ARRAY_TYPE, so
    gimple_fold_indirect_ref doesn't create the ARRAY_REF.
    But with it, it is simplified to NOP_EXPR to int * type from
    POINTER_PLUS_EXPR with pointer to int[4] ARRAY_TYPE, the NOP_EXPR is
    skipped over by STRIP_NOPS and the above code triggers.
    
    The following patch fixes it by swapping the order, do NOP_EXPR
    inside of POINTER_PLUS_EXPR first argument instead of NOP_EXPR with
    POINTER_PLUS_EXPR.
    
    2026-03-06  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/124358
            * match.pd ((ptr) (x p+ y) p+ z -> (ptr) (x p+ (y + z))): Simplify
            into (ptr) x p+ (y + z) instead.
    
            * gcc.c-torture/execute/pr124358.c: New test.

Diff:
---
 gcc/match.pd                                   |  2 +-
 gcc/testsuite/gcc.c-torture/execute/pr124358.c | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 7f16fd4e0814..1d6428bf7e53 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3136,7 +3136,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #if GENERIC
 (simplify
   (pointer_plus (convert:s (pointer_plus:s @0 @1)) @3)
-  (convert:type (pointer_plus @0 (plus @1 @3))))
+  (pointer_plus (convert:type @0) (plus @1 @3)))
 #endif
 
 /* Pattern match
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr124358.c 
b/gcc/testsuite/gcc.c-torture/execute/pr124358.c
new file mode 100644
index 000000000000..81bf6a29d7c9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr124358.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/124358 */
+
+[[gnu::noipa]] void
+foo (int d)
+{
+  static int u = 11;
+  if (d != u++)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  int a[1][4] = { 11, 12, 13, 14 };
+  int (*p)[4] = a;
+  for (int i = 0; i < 1; i++)
+    for (int j = 0; j < 4; j++)
+      foo (*(*(p + i) + j));
+}

Reply via email to