[COMMITTED] PR tree-optimization/126533 - Use logical_depth limit in fast vrp.

Andrew MacLeod <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
GORI uses param_range_logical_depth to avoid descending too deeply into 
statements with more than one operand.   This prevents exponential 
behaviour and other silliness.

This patch makes the fast-vrp implementation also honor that setting.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  pushed.

Andrew
0002-Use-logical_depth-limit-in-fast-vrp.patch (text/x-patch, 5.6 KB)
From 8947671e9688d1c10981a4f3368f997e57230554 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Wed, 12 Aug 2026 16:08:44 -0400
Subject: [PATCH 2/4] Use logical_depth limit in fast vrp.

Fast VRP should use the logical_depth setting to limit exponential
behaviour.

	PR tree-optimization/126533
	gcc/
	* gimple-range-gori.cc (gori_name_helper): Add depth counter.

	gcc/testsuite/
	* gcc.dg/pr126533.c: New.
---
 gcc/gimple-range-gori.cc        | 11 +++--
 gcc/testsuite/gcc.dg/pr126533.c | 76 +++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr126533.c

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 1b75ca185e2..3bdc5305b49 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1681,7 +1681,7 @@ gori_on_edge (ssa_cache &r, edge e, range_query *q)
 
 bool
 gori_name_helper (vrange &r, tree name, vrange &lhs, gimple *stmt,
-		  range_query *q)
+		  range_query *q, int depth = 0)
 {
   struct gori_stmt_info si(lhs, stmt, q);
   if (!si)
@@ -1692,6 +1692,11 @@ gori_name_helper (vrange &r, tree name, vrange &lhs, gimple *stmt,
   if (si.ssa2 == name)
     return si.calc_op2 (r, lhs, si.op1_range);
 
+  // Limit the exponential growth via the logical depth limit.
+  if (si.ssa1 && si.ssa2)
+    if (++depth >= param_ranger_logical_depth)
+      return false;
+
   value_range tmp;
   // Now evaluate operand ranges, and set them in the edge cache.
   // If there was already a range, leave it and do no further evaluation.
@@ -1703,7 +1708,7 @@ gori_name_helper (vrange &r, tree name, vrange &lhs, gimple *stmt,
       gimple *src = SSA_NAME_DEF_STMT (si.ssa1);
       // If definition is in the same basic block, evaluate it.
       if (src && gimple_bb (src) == gimple_bb (stmt))
-	if (gori_name_helper (r, name, si.op1_range, src, q))
+	if (gori_name_helper (r, name, si.op1_range, src, q, depth))
 	  return true;
     }
 
@@ -1714,7 +1719,7 @@ gori_name_helper (vrange &r, tree name, vrange &lhs, gimple *stmt,
 	si.op2_range.intersect (tmp);
       gimple *src = SSA_NAME_DEF_STMT (si.ssa2);
       if (src && gimple_bb (src) == gimple_bb (stmt))
-	if (gori_name_helper (r, name, si.op2_range, src, q))
+	if (gori_name_helper (r, name, si.op2_range, src, q, depth))
 	  return true;
     }
   return false;
diff --git a/gcc/testsuite/gcc.dg/pr126533.c b/gcc/testsuite/gcc.dg/pr126533.c
new file mode 100644
index 00000000000..a3f78661dda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr126533.c
@@ -0,0 +1,76 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 --param=vrp-block-limit=1" } */
+
+/* gori_name_helper walks both SSA operands of every statement with no
+   memoisation, so a depth-N DAG of two-operand statements costs 2^N.
+
+   Entry point: gori_name_helper, gcc/gimple-range-gori.cc:1683, reached from
+   gori_name_on_edge (1729) <- dom_ranger::range_on_edge (gimple-range.cc:858)
+   <- fvrp_folder::value_on_edge, once per PHI argument.
+
+   The sibling walk gori_calc_operands (gimple-range-gori.cc:1617) memoises
+   with !r.has_range (si.ssaN) and is linear; this one has no cache, no depth
+   limit and no in_chain_p test.
+
+   Needs the fast-VRP path, selected automatically when the function has more
+   than --param=vrp-block-limit blocks (150000).  Forced here with the param.
+
+     gcc -O2 --param=vrp-block-limit=1   does not finish in 40 s
+     gcc -O2                             0.02 s
+
+   Depth 14 / 18 / 22 measure 0.35 s / 5.4 s / >40 s: one doubling per level.
+   Control: change "int r = u;" to "int r = a22;" so the queried name is the
+   condition operand and gori_name_helper returns at its first test; 0.02 s.  */
+extern int g1 (int);
+int f (int i, int j, int k)
+{
+  int u = k & 3;
+  int a0 = i & 255, b0 = j & 255;
+  int t1 = a0 * b0; int s1 = a0 - b0;
+  int a1 = t1 & 255; int b1 = s1 & 255;
+  int t2 = a1 * b1; int s2 = a1 - b1;
+  int a2 = t2 & 255; int b2 = s2 & 255;
+  int t3 = a2 * b2; int s3 = a2 - b2;
+  int a3 = t3 & 255; int b3 = s3 & 255;
+  int t4 = a3 * b3; int s4 = a3 - b3;
+  int a4 = t4 & 255; int b4 = s4 & 255;
+  int t5 = a4 * b4; int s5 = a4 - b4;
+  int a5 = t5 & 255; int b5 = s5 & 255;
+  int t6 = a5 * b5; int s6 = a5 - b5;
+  int a6 = t6 & 255; int b6 = s6 & 255;
+  int t7 = a6 * b6; int s7 = a6 - b6;
+  int a7 = t7 & 255; int b7 = s7 & 255;
+  int t8 = a7 * b7; int s8 = a7 - b7;
+  int a8 = t8 & 255; int b8 = s8 & 255;
+  int t9 = a8 * b8; int s9 = a8 - b8;
+  int a9 = t9 & 255; int b9 = s9 & 255;
+  int t10 = a9 * b9; int s10 = a9 - b9;
+  int a10 = t10 & 255; int b10 = s10 & 255;
+  int t11 = a10 * b10; int s11 = a10 - b10;
+  int a11 = t11 & 255; int b11 = s11 & 255;
+  int t12 = a11 * b11; int s12 = a11 - b11;
+  int a12 = t12 & 255; int b12 = s12 & 255;
+  int t13 = a12 * b12; int s13 = a12 - b12;
+  int a13 = t13 & 255; int b13 = s13 & 255;
+  int t14 = a13 * b13; int s14 = a13 - b13;
+  int a14 = t14 & 255; int b14 = s14 & 255;
+  int t15 = a14 * b14; int s15 = a14 - b14;
+  int a15 = t15 & 255; int b15 = s15 & 255;
+  int t16 = a15 * b15; int s16 = a15 - b15;
+  int a16 = t16 & 255; int b16 = s16 & 255;
+  int t17 = a16 * b16; int s17 = a16 - b16;
+  int a17 = t17 & 255; int b17 = s17 & 255;
+  int t18 = a17 * b17; int s18 = a17 - b17;
+  int a18 = t18 & 255; int b18 = s18 & 255;
+  int t19 = a18 * b18; int s19 = a18 - b18;
+  int a19 = t19 & 255; int b19 = s19 & 255;
+  int t20 = a19 * b19; int s20 = a19 - b19;
+  int a20 = t20 & 255; int b20 = s20 & 255;
+  int t21 = a20 * b20; int s21 = a20 - b20;
+  int a21 = t21 & 255; int b21 = s21 & 255;
+  int t22 = a21 * b21; int s22 = a21 - b21;
+  int a22 = t22 & 255; int b22 = s22 & 255;
+  int r = u;
+  if (a22 < 5) r = g1 (u);
+  return r;
+}
-- 
2.45.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.