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

commit r17-3179-gb947bd4aac67ba3bdb6030aa4ac2f3eb0204df05
Author: Richard Biener <[email protected]>
Date:   Thu Aug 6 11:49:20 2026 +0200

    tree-optimization/126658 - TARGET_MEM_REF and non-null infering
    
    The following adjusts three places to avoid infering that operand
    zero of a TARGET_MEM_REF is literally dereferenced and thus may
    not be NULL.  This reflects the fact that within IVOPTs we cannot
    easily guarantee that there'll be a real pointer in TMR_BASE
    and fiddling with IVOPTs proved fragile.
    
    So we are taking a conservative stance here, with carving out
    the likely common case of a scaled index which is unlikely
    going to be a pointer (fingers crossing).
    
    For the testcase at hand the apparent non-NULLness was triggering
    a jump-threading miscompiling the testcase.
    
            PR tree-optimization/126658
            * gimple.cc (check_loadstore): Restrict TARGET_MEM_REF
            handling.
            * gimple-ssa-isolate-paths.cc (check_loadstore): Likewise.
            * gimple-range-infer.cc (non_null_loadstore): Likewise.
    
            * gcc.dg/torture/pr126658.c: New testcase.

Diff:
---
 gcc/gimple-range-infer.cc               | 13 +++++++++++--
 gcc/gimple-ssa-isolate-paths.cc         | 10 +++++++++-
 gcc/gimple.cc                           | 14 +++++++++++---
 gcc/testsuite/gcc.dg/torture/pr126658.c | 26 ++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc
index ecd197cf8590..65c10ac1cb43 100644
--- a/gcc/gimple-range-infer.cc
+++ b/gcc/gimple-range-infer.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-walk.h"
 #include "cfganal.h"
 #include "tree-dfa.h"
+#include "fold-const.h"
 
 // Create the global oracle.
 
@@ -61,9 +62,17 @@ private:
 // stmt range inference instance.
 
 static bool
-non_null_loadstore (gimple *, tree op, tree, void *data)
+non_null_loadstore (gimple *stmt, tree op, tree, void *data)
 {
-  if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+  if (TREE_CODE (op) == MEM_REF
+      || (TREE_CODE (op) == TARGET_MEM_REF
+         && !TMR_INDEX2 (op)
+         && (!TMR_INDEX (op)
+             || (TMR_STEP (op)
+                 && expr_not_equal_to (TMR_STEP (op),
+                                       wi::one (TYPE_PRECISION (TREE_TYPE
+                                                       (TMR_STEP (op)))),
+                                       stmt)))))
     {
       /* Some address spaces may legitimately dereference zero.  */
       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
diff --git a/gcc/gimple-ssa-isolate-paths.cc b/gcc/gimple-ssa-isolate-paths.cc
index 9d359ef84e6a..ceef422495c7 100644
--- a/gcc/gimple-ssa-isolate-paths.cc
+++ b/gcc/gimple-ssa-isolate-paths.cc
@@ -51,7 +51,15 @@ static bool cfg_altered;
 static bool
 check_loadstore (gimple *stmt, tree op, tree, void *data)
 {
-  if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+  if ((TREE_CODE (op) == MEM_REF
+       || (TREE_CODE (op) == TARGET_MEM_REF
+          && !TMR_INDEX2 (op)
+          && (!TMR_INDEX (op)
+              || (TMR_STEP (op)
+                  && expr_not_equal_to (TMR_STEP (op),
+                                        wi::one (TYPE_PRECISION (TREE_TYPE
+                                                       (TMR_STEP (op)))),
+                                        stmt)))))
       && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
     {
       TREE_THIS_VOLATILE (op) = 1;
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index c791e0412431..648400aa4445 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -3153,9 +3153,17 @@ nonbarrier_call_p (gimple *call)
    This routine only makes a superficial check for a dereference.  Thus
    it must only be used if it is safe to return a false negative.  */
 static bool
-check_loadstore (gimple *, tree op, tree, void *data)
-{
-  if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+check_loadstore (gimple *stmt, tree op, tree, void *data)
+{
+  if (TREE_CODE (op) == MEM_REF
+      || (TREE_CODE (op) == TARGET_MEM_REF
+         && !TMR_INDEX2 (op)
+         && (!TMR_INDEX (op)
+             || (TMR_STEP (op)
+                 && expr_not_equal_to (TMR_STEP (op),
+                                       wi::one (TYPE_PRECISION (TREE_TYPE
+                                                       (TMR_STEP (op)))),
+                                       stmt)))))
     {
       /* Some address spaces may legitimately dereference zero.  */
       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
diff --git a/gcc/testsuite/gcc.dg/torture/pr126658.c 
b/gcc/testsuite/gcc.dg/torture/pr126658.c
new file mode 100644
index 000000000000..c11d637d199f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126658.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+long a, b;
+int c, d;
+long long e[1];
+char __attribute__((noipa))
+f(long long *p1, int i, long long *p3)
+{
+  long long *g;
+  for (; a < i; a++)
+    g = p1 + 1;
+  while (g != p1) {
+    --g;
+    b = g - p1;
+    if (p3[b])
+      c = 3;
+  }
+  return c;
+}
+int main() {
+  long long j[] = {1096435691};
+  d = f(e, 2147483647 - 2147279301, j);
+  if (d != 3)
+    __builtin_abort ();
+}

Reply via email to