https://gcc.gnu.org/g:9ded9b80c111559ece589197a17d6e7e512dd449

commit r16-5056-g9ded9b80c111559ece589197a17d6e7e512dd449
Author: Richard Biener <[email protected]>
Date:   Fri Oct 31 13:08:05 2025 +0100

    Make FOR_EACH_IMM_USE_STMT work w/o fake imm use node
    
    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.

Diff:
---
 gcc/ssa-iterators.h                       | 50 +++++++++++++------------------
 gcc/testsuite/gcc.dg/torture/pr122502-2.c | 23 ++++++++++++++
 2 files changed, 43 insertions(+), 30 deletions(-)

diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h
index 47220c5ce25a..8fcc9b8a55f6 100644
--- a/gcc/ssa-iterators.h
+++ b/gcc/ssa-iterators.h
@@ -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
index 000000000000..36a114d97b70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122502-2.c
@@ -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;
+  }
+}

Reply via email to