]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
- ICE verify_vssa exceeds stack space for big functions [PR124805]
authorHeiko Eißfeldt <heiko.Eissfeldt@hexco.de>
Wed, 8 Apr 2026 21:36:12 +0000 (23:36 +0200)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Thu, 30 Apr 2026 15:24:50 +0000 (08:24 -0700)
The source from PR124561 led to an ICE with --enable-checking, caused by a stack overflow.
The recursive verification code verify_vssa in tree-ssa.cc could not handle the extreme
number of basic blocks within the typical limits of stack space.

As for PR124561 the recursive code was transformed into an iterative version, which
avoided the recursive calls.

A worklist is used, which has as entries a pair of a basic_block and a tree (vdef).
The logic of verification steps for each basic_block is unchanged, although the order
of basic_blocks is changed.

This fixes PR124805.

Reg tested OK.

2026-04-07 Heiko Eißfeldt <heiko@hexco.de>

PR middle-end/124805
* tree-ssa.cc (verify_vssa):
replace recursive calls with iteration for lower stack usage

gcc/tree-ssa.cc

index 3c899eb5979f60388061e8e14df75d516f8e3090..e110e4acf2b000bac357f8a0d6d005c30cbaa81a 100644 (file)
@@ -636,96 +636,119 @@ release_defs_bitset (bitmap toremove)
 /* Verify virtual SSA form.  */
 
 bool
-verify_vssa (basic_block bb, tree current_vdef, sbitmap visited)
+verify_vssa (basic_block bb_start, tree current_vdef, sbitmap visited)
 {
   bool err = false;
 
-  if (!bitmap_set_bit (visited, bb->index))
-    return false;
+  struct state_t {
+    basic_block bb;
+    tree       vdef;
+  } state;
+
+  auto_vec<state_t, 3> worklist;
+  state.bb = bb_start;
+  state.vdef = current_vdef;
+  worklist.safe_push (state);
 
-  /* Pick up the single virtual PHI def.  */
-  gphi *phi = NULL;
-  for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
-       gsi_next (&si))
+  while (!worklist.is_empty ())
     {
-      tree res = gimple_phi_result (si.phi ());
-      if (virtual_operand_p (res))
+      const auto &state = worklist.pop ();
+      const auto &bb = state.bb;
+      current_vdef = state.vdef;
+
+      if (!bitmap_set_bit (visited, bb->index))
+       continue;
+
+      /* Pick up the single virtual PHI def.  */
+      gphi *phi = NULL;
+      for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+          gsi_next (&si))
+       {
+         tree res = gimple_phi_result (si.phi ());
+         if (virtual_operand_p (res))
+           {
+             if (phi)
+               {
+                 error ("multiple virtual PHI nodes in BB %d", bb->index);
+                 print_gimple_stmt (stderr, phi, 0);
+                 print_gimple_stmt (stderr, si.phi (), 0);
+                 err = true;
+               }
+             else
+               phi = si.phi ();
+           }
+       }
+      if (phi)
        {
-         if (phi)
+         current_vdef = gimple_phi_result (phi);
+         if (TREE_CODE (current_vdef) != SSA_NAME)
            {
-             error ("multiple virtual PHI nodes in BB %d", bb->index);
+             error ("virtual definition is not an SSA name");
              print_gimple_stmt (stderr, phi, 0);
-             print_gimple_stmt (stderr, si.phi (), 0);
              err = true;
            }
-         else
-           phi = si.phi ();
        }
-    }
-  if (phi)
-    {
-      current_vdef = gimple_phi_result (phi);
-      if (TREE_CODE (current_vdef) != SSA_NAME)
+
+      /* Verify stmts.  */
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
        {
-         error ("virtual definition is not an SSA name");
-         print_gimple_stmt (stderr, phi, 0);
-         err = true;
+         gimple *stmt = gsi_stmt (gsi);
+         tree vuse = gimple_vuse (stmt);
+         if (vuse)
+           {
+             if (vuse != current_vdef)
+               {
+                 error ("stmt with wrong VUSE");
+                 print_gimple_stmt (stderr, stmt, 0, TDF_VOPS);
+                 fprintf (stderr, "expected ");
+                 print_generic_expr (stderr, current_vdef);
+                 fprintf (stderr, "\n");
+                 err = true;
+               }
+             tree vdef = gimple_vdef (stmt);
+             if (vdef)
+               {
+                 current_vdef = vdef;
+                 if (TREE_CODE (current_vdef) != SSA_NAME)
+                   {
+                     error ("virtual definition is not an SSA name");
+                     print_gimple_stmt (stderr, phi, 0);
+                     err = true;
+                   }
+               }
+           }
        }
-    }
 
-  /* Verify stmts.  */
-  for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
-       gsi_next (&gsi))
-    {
-      gimple *stmt = gsi_stmt (gsi);
-      tree vuse = gimple_vuse (stmt);
-      if (vuse)
+      /* Verify destination PHI uses and add successors to worklist.  */
+      edge_iterator ei;
+      edge e;
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
-         if (vuse != current_vdef)
+         gphi *phi = get_virtual_phi (e->dest);
+         if (phi
+            && PHI_ARG_DEF_FROM_EDGE (phi, e) != current_vdef)
            {
-             error ("stmt with wrong VUSE");
-             print_gimple_stmt (stderr, stmt, 0, TDF_VOPS);
+             error ("PHI node with wrong VUSE on edge from BB %d",
+                    e->src->index);
+             print_gimple_stmt (stderr, phi, 0, TDF_VOPS);
              fprintf (stderr, "expected ");
              print_generic_expr (stderr, current_vdef);
              fprintf (stderr, "\n");
              err = true;
            }
-         tree vdef = gimple_vdef (stmt);
-         if (vdef)
+
+         /* Add successor BB along with current vdef to worklist.  */
+         if (!bitmap_bit_p (visited, e->dest->index))
            {
-             current_vdef = vdef;
-             if (TREE_CODE (current_vdef) != SSA_NAME)
-               {
-                 error ("virtual definition is not an SSA name");
-                 print_gimple_stmt (stderr, phi, 0);
-                 err = true;
-               }
-           }
-       }
-    }
+             state_t new_state;
+             new_state.bb = e->dest;
+             new_state.vdef = current_vdef;
 
-  /* Verify destination PHI uses and recurse.  */
-  edge_iterator ei;
-  edge e;
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    {
-      gphi *phi = get_virtual_phi (e->dest);
-      if (phi
-         && PHI_ARG_DEF_FROM_EDGE (phi, e) != current_vdef)
-       {
-         error ("PHI node with wrong VUSE on edge from BB %d",
-                e->src->index);
-         print_gimple_stmt (stderr, phi, 0, TDF_VOPS);
-         fprintf (stderr, "expected ");
-         print_generic_expr (stderr, current_vdef);
-         fprintf (stderr, "\n");
-         err = true;
+             worklist.safe_push (new_state);
+           }
        }
-
-      /* Recurse.  */
-      err |= verify_vssa (e->dest, current_vdef, visited);
     }
-
   return err;
 }