]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Relax gsi_replace requirement
authorRichard Sandiford <rdsandiford@googlemail.com>
Tue, 2 Jun 2026 19:50:27 +0000 (20:50 +0100)
committerRichard Sandiford <rdsandiford@googlemail.com>
Tue, 2 Jun 2026 19:50:27 +0000 (20:50 +0100)
gsi_replace requires the new statement to have the same lhs as
the old one, if both statements have lhses.  This requirement was
added by r0-96285-g0ca5af51abe63d as part of the DEBUG_EXPR_DECL
work.  And it makes sense in that context.  If gsi_replace nixes
the definition of an SSA name that is still referenced by debug
statements then things are going to go wrong.

But if that's the "only" reason, we should be able to relax the
condition to say that, if the new statement has a different lhs,
the caller must ensure that it has updated all debug uses before
calling gsi_replace.

The patch adds a completely_unused helper to test that.  The helper
has a sharp edge and is not widely useful, so I've kept it local
to gimple-iterators.cc for now.

It's arguable that the old code was too forgiving with its
!gimple_has_lhs (stmt) escape hatch.  A tighter condition would be
the one tested by:

  tree old_lhs = gimple_get_lhs (orig_stmt);
  return (!old_lhs
          || gimple_get_lhs (stmt) == old_lhs
  || completely_unused (old_lhs));

gcc/
* gimple-iterator.cc (completely_unused): New function.
(gsi_replace): Allow changes in lhs if the caller has updated
all uses of the old name, including all debug uses.
* gimple-fold.cc (gsi_replace_with_seq_vops): Likewise.

gcc/gimple-fold.cc
gcc/gimple-iterator.cc

index 1ceb5aa5fba7419aa8ba81f48569ec73d5055342..fab4886b0f2e15d55acb94296b0f50131ef967de 100644 (file)
@@ -581,8 +581,14 @@ fold_gimple_assign (gimple_stmt_iterator *si)
 
 /* Replace a statement at *SI_P with a sequence of statements in STMTS,
    adjusting the replacement stmts location and virtual operands.
-   If the statement has a lhs the last stmt in the sequence is expected
-   to assign to that lhs.  */
+
+   If the statements has an lhs, either:
+
+   - the last statement of the new sequence must assign to the same lhs or
+
+   - the caller must ensure that all uses of the old lhs have been
+     removed before calling this function.  This includes removing
+     all debug uses.  */
 
 void
 gsi_replace_with_seq_vops (gimple_stmt_iterator *si_p, gimple_seq stmts)
index 2b6133ec8c024dbe0c93fcb6ff394c46c9e5f7e8..b6cf30aea6ac296590609506602ba50a124691d9 100644 (file)
@@ -34,6 +34,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "gimplify.h"
 
+/* Return true if VAR has no uses at all, including no debug uses.  */
+
+static inline bool
+completely_unused (const_tree var)
+{
+  auto *head = &SSA_NAME_IMM_USE_NODE (var);
+  return head->next == head;
+}
 
 /* Mark the statement STMT as modified, and update it.  */
 
@@ -422,9 +430,12 @@ gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 
 /* Replace the statement pointed-to by GSI to STMT.  If UPDATE_EH_INFO
    is true, the exception handling information of the original
-   statement is moved to the new statement.  Assignments must only be
-   replaced with assignments to the same LHS.  Returns whether EH edge
-   cleanup is required.  */
+   statement is moved to the new statement.  Returns whether EH edge
+   cleanup is required.
+
+   If the two statements assign to different SSA names, the caller must
+   ensure that all uses of the old SSA name have been removed before
+   calling this function.  This includes removing all debug uses.  */
 
 bool
 gsi_replace (gimple_stmt_iterator *gsi, gimple *stmt, bool update_eh_info)
@@ -436,7 +447,8 @@ gsi_replace (gimple_stmt_iterator *gsi, gimple *stmt, bool update_eh_info)
     return false;
 
   gcc_assert (!gimple_has_lhs (orig_stmt) || !gimple_has_lhs (stmt)
-             || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
+             || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt)
+             || completely_unused (gimple_get_lhs (orig_stmt)));
 
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));