]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Make FOR_EACH_IMM_USE_STMT work w/o fake imm use node
authorRichard Biener <rguenther@suse.de>
Fri, 31 Oct 2025 12:08:05 +0000 (13:08 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 6 Nov 2025 13:55:27 +0000 (14:55 +0100)
This is an attempt to fix PR122502 by making a FOR_EACH_IMM_USE_FAST
with in an FOR_EACH_IMM_USE_STMT on _the same_ VAR work without
the former running into the FOR_EACH_IMM_USE_STMT inserted marker
use operand.  It does this by getting rid of the marker.

The downside is that this in principle restricts the set of operations
that can be done on the immediate use list of VAR.  Where previously
almost anything was OK (but technically not well-defined what happens
to the iteration) after this patch you may only remove immediate
uses of VAR on the current stmt from the FOR_EACH_IMM_USE_STMT
iteration.  In particular things will break if you happen to remove
the one immediate use of VAR on the stmt immediately following
the set of immediate uses on the currrent stmt.

Additional checking to combat such cases is implemented in a
followup.

PR tree-optimization/122502
* ssa-iterators.h (imm_use_iterator::iter_node): Remove.
(imm_use_iterator::next_stmt_use): New.
(next_readonly_imm_use): Adjust checking code.
(end_imm_use_stmt_traverse): Simplify.
(link_use_stmts_after): Likewise.  Return the last use
with the same stmt.
(first_imm_use_stmt): Simplify.  Set next_stmt_use.
(next_imm_use_stmt): Likewise.
(end_imm_use_on_stmt_p): Adjust.

* gcc.dg/torture/pr122502-2.c: New testcase.

gcc/ssa-iterators.h
gcc/testsuite/gcc.dg/torture/pr122502-2.c [new file with mode: 0644]

index 47220c5ce25a7c736dbd3ecaf1b24a2ed97aca71..8fcc9b8a55f6ba2d764b2ba345d50aeb6d339e03 100644 (file)
@@ -53,8 +53,9 @@ struct imm_use_iterator
   ssa_use_operand_t *imm_use;
   /* This marks the last use in the list (use node from SSA_NAME)  */
   ssa_use_operand_t *end_p;
-  /* This node is inserted and used to mark the end of the uses for a stmt.  */
-  ssa_use_operand_t iter_node;
+  /* This is the next ssa_name to visit in an outer FOR_EACH_IMM_USE_STMT.
+     Also used for fast imm use iterator checking.  */
+  ssa_use_operand_t *next_stmt_use;
   /* This is the next ssa_name to visit.  IMM_USE may get removed before
      the next one is traversed to, so it must be cached early.  */
   ssa_use_operand_t *next_imm_name;
@@ -350,7 +351,7 @@ first_readonly_imm_use (imm_use_iterator *imm, tree var)
 {
   imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
   imm->imm_use = imm->end_p->next;
-  imm->iter_node.next = imm->imm_use->next;
+  imm->next_stmt_use = imm->imm_use->next;
   if (end_readonly_imm_use_p (imm))
     return NULL_USE_OPERAND_P;
   return imm->imm_use;
@@ -368,8 +369,8 @@ next_readonly_imm_use (imm_use_iterator *imm)
      using the SAFE version of the iterator.  */
   if (flag_checking)
     {
-      gcc_assert (imm->iter_node.next == old->next);
-      imm->iter_node.next = old->next->next;
+      gcc_assert (imm->next_stmt_use == old->next);
+      imm->next_stmt_use = old->next->next;
     }
 
   imm->imm_use = old->next;
@@ -845,9 +846,8 @@ end_imm_use_stmt_p (const imm_use_iterator *imm)
    placeholder node from the list.  */
 
 inline void
-end_imm_use_stmt_traverse (imm_use_iterator *imm)
+end_imm_use_stmt_traverse (imm_use_iterator *)
 {
-  delink_imm_use (&(imm->iter_node));
 }
 
 /* Immediate use traversal of uses within a stmt require that all the
@@ -880,10 +880,11 @@ move_use_after_head (use_operand_p use_p, use_operand_p head,
 
 
 /* This routine will relink all uses with the same stmt as HEAD into the list
-   immediately following HEAD for iterator IMM.  */
+   immediately following HEAD for iterator IMM and returns the last use on
+   that stmt.  */
 
-inline void
-link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
+inline use_operand_p
+link_use_stmts_after (use_operand_p head, imm_use_iterator *)
 {
   use_operand_p use_p;
   use_operand_p last_p = head;
@@ -915,10 +916,7 @@ link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
            last_p = move_use_after_head (use_p, head, last_p);
        }
     }
-  /* Link iter node in after last_p.  */
-  if (imm->iter_node.prev != NULL)
-    delink_imm_use (&imm->iter_node);
-  link_imm_use_to_list (&(imm->iter_node), last_p);
+  return last_p;
 }
 
 /* Initialize IMM to traverse over uses of VAR.  Return the first statement.  */
@@ -929,18 +927,14 @@ first_imm_use_stmt (imm_use_iterator *imm, tree var)
   imm->imm_use = imm->end_p->next;
   imm->next_imm_name = NULL_USE_OPERAND_P;
 
-  /* iter_node is used as a marker within the immediate use list to indicate
-     where the end of the current stmt's uses are.  Initialize it to NULL
-     stmt and use, which indicates a marker node.  */
-  imm->iter_node.prev = NULL_USE_OPERAND_P;
-  imm->iter_node.next = NULL_USE_OPERAND_P;
-  imm->iter_node.loc.stmt = NULL;
-  imm->iter_node.use = NULL;
+  /* next_stmt_use is used to point to the immediate use node after
+     the set of uses for the current stmt.  */
+  imm->next_stmt_use = NULL_USE_OPERAND_P;
 
   if (end_imm_use_stmt_p (imm))
     return NULL;
 
-  link_use_stmts_after (imm->imm_use, imm);
+  imm->next_stmt_use = link_use_stmts_after (imm->imm_use, imm)->next;
 
   return USE_STMT (imm->imm_use);
 }
@@ -950,15 +944,11 @@ first_imm_use_stmt (imm_use_iterator *imm, tree var)
 inline gimple *
 next_imm_use_stmt (imm_use_iterator *imm)
 {
-  imm->imm_use = imm->iter_node.next;
+  imm->imm_use = imm->next_stmt_use;
   if (end_imm_use_stmt_p (imm))
-    {
-      if (imm->iter_node.prev != NULL)
-       delink_imm_use (&imm->iter_node);
-      return NULL;
-    }
+    return NULL;
 
-  link_use_stmts_after (imm->imm_use, imm);
+  imm->next_stmt_use = link_use_stmts_after (imm->imm_use, imm)->next;
   return USE_STMT (imm->imm_use);
 }
 
@@ -977,7 +967,7 @@ first_imm_use_on_stmt (imm_use_iterator *imm)
 inline bool
 end_imm_use_on_stmt_p (const imm_use_iterator *imm)
 {
-  return (imm->imm_use == &(imm->iter_node));
+  return (imm->imm_use == imm->next_stmt_use);
 }
 
 /* Bump to the next use on the stmt IMM refers to, return NULL if done.  */
diff --git a/gcc/testsuite/gcc.dg/torture/pr122502-2.c b/gcc/testsuite/gcc.dg/torture/pr122502-2.c
new file mode 100644 (file)
index 0000000..36a114d
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+typedef struct {
+  int mant;
+  int exp;
+} SoftFloat;
+SoftFloat __trans_tmp_8, main___trans_tmp_5;
+static SoftFloat av_normalize_sf(SoftFloat a) {
+  while (a.mant + 536870911 < 1073741823) {
+    a.mant += a.mant;
+    a.exp -= 1;
+  }
+  return a;
+}
+void main() {
+  main___trans_tmp_5 = av_normalize_sf((SoftFloat){1, 29 + 1});
+  SoftFloat sf1 = main___trans_tmp_5;
+  for (;;) {
+    int t = main___trans_tmp_5.exp - sf1.exp;
+    if (t < 2)
+      sf1 = __trans_tmp_8;
+  }
+}