The following addresses the latent issue that gsi_replace_with_seq
causes debug info to unnecessarily degrade and in this process
break the new immediate use iterator sanity checking.  In particular
gsi_remove has side-effects on debug stmts even when operating
in non-permanent operation.  But as we are operating on a sequence
not in the IL here this should be avoided.  Re-factoring
gsi_replace_with_seq to not rely on gsi_remove fulfills this.

I've noticed gsi_split_seq_before has misleading documentation.
Fixed thereby as well.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

I'm also considering to backport this, it seems quite detrimental
on debug info quality.

        PR tree-optimization/122589
        PR middle-end/122594
        * gimple-iterator.cc (gsi_replace_with_seq): Instead of
        removing the last stmt from the sequence with gsi_remove,
        split it using gsi_split_seq_before.
        (gsi_split_seq_before): Fix bogus documentation.

        * g++.dg/torture/pr122589.C: New testcase.
---
 gcc/gimple-iterator.cc                  | 14 ++++++--------
 gcc/testsuite/g++.dg/torture/pr122589.C | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr122589.C

diff --git a/gcc/gimple-iterator.cc b/gcc/gimple-iterator.cc
index 3af672bf0b9..741e5a59684 100644
--- a/gcc/gimple-iterator.cc
+++ b/gcc/gimple-iterator.cc
@@ -389,8 +389,8 @@ gsi_set_stmt (gimple_stmt_iterator *gsi, gimple *stmt)
 }
 
 
-/* Move all statements in the sequence before I to a new sequence.
-   Return this new sequence.  I is set to the head of the new list.  */
+/* Move all statements in the sequence starting at I to a new sequence.
+   Set *PNEW_SEQ to this sequence.  I is set to the head of the new list.  */
 
 void
 gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
@@ -471,18 +471,16 @@ void
 gsi_replace_with_seq (gimple_stmt_iterator *gsi, gimple_seq seq,
                      bool update_eh_info)
 {
-  gimple_stmt_iterator seqi;
-  gimple *last;
   if (gimple_seq_empty_p (seq))
     {
       gsi_remove (gsi, true);
       return;
     }
-  seqi = gsi_last (seq);
-  last = gsi_stmt (seqi);
-  gsi_remove (&seqi, false);
+  gimple_seq tail;
+  gimple_stmt_iterator lasti = gsi_last (seq);
+  gsi_split_seq_before (&lasti, &tail);
   gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
-  gsi_replace (gsi, last, update_eh_info);
+  gsi_replace (gsi, gsi_stmt (lasti), update_eh_info);
 }
 
 
diff --git a/gcc/testsuite/g++.dg/torture/pr122589.C 
b/gcc/testsuite/g++.dg/torture/pr122589.C
new file mode 100644
index 00000000000..ac441a0d68c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr122589.C
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// { dg-additional-options "-g" }
+
+struct QPointF {
+  QPointF(double xpos, double ypos) : xp(xpos), yp(ypos) {}
+  double xp;
+  double yp;
+};
+double xp, yp, w, h;
+struct QRectF {
+  QRectF(QPointF, int);
+  QPointF center() { return QPointF(xp + w / 2, yp + h / 2); }
+};
+void clientArea(QPointF &);
+int workspace_size;
+void workspace() {
+  QRectF geom(QPointF(0, 0), workspace_size);
+  xp = 0 - w / 2;
+  yp = -h;
+  QPointF __trans_tmp_2 = geom.center();
+  clientArea(__trans_tmp_2);
+}
-- 
2.51.0

Reply via email to