]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/118717 - store commoning vs. abnormals
authorRichard Biener <rguenther@suse.de>
Mon, 3 Feb 2025 08:55:50 +0000 (09:55 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 24 Feb 2025 10:47:57 +0000 (11:47 +0100)
When we sink common stores in cselim or the sink pass we have to
make sure to not introduce overlapping lifetimes for abnormals
used in the ref.  The easiest is to avoid sinking stmts which
reference abnormals at all which is what the following does.

PR tree-optimization/118717
* tree-ssa-phiopt.cc (cond_if_else_store_replacement_1):
Do not common stores referencing abnormal SSA names.
* tree-ssa-sink.cc (sink_common_stores_to_bb): Likewise.

* gcc.dg/torture/pr118717.c: New testcase.

(cherry picked from commit fbcbbfe2bf83eb8b1347144eeca37b06be5a8bb5)

gcc/testsuite/gcc.dg/torture/pr118717.c [new file with mode: 0644]
gcc/tree-ssa-phiopt.cc
gcc/tree-ssa-sink.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr118717.c b/gcc/testsuite/gcc.dg/torture/pr118717.c
new file mode 100644 (file)
index 0000000..42dc5ec
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+void jj(void);
+int ff1(void) __attribute__((__returns_twice__));
+struct s2 {
+  int prev;
+};
+typedef struct s1 {
+  unsigned interrupt_flag;
+  unsigned interrupt_mask;
+  int tag;
+  int state;
+}s1;
+int ff(void);
+static inline
+int mm(s1 *ec) {
+  if (ff())
+    if (ec->interrupt_flag & ~(ec)->interrupt_mask)
+      return 0;
+}
+void ll(s1 *ec) {
+  int t = 1;
+  int state;
+  if (t)
+  {
+    {
+      s1 *const _ec = ec;
+      struct s2 _tag = {0};
+      if (ff1())
+       state = ec->state;
+      else
+       state = 0;
+      if (!state)
+       mm (ec);
+      _ec->tag = _tag.prev;
+    }
+    if (state)
+      __builtin_exit(0);
+  }
+  jj();
+}
index 8cb1413b49a503641be8514d3243599fde68f19b..f01979aa00389c6b077a3db7946fc4c8aaf7b6fb 100644 (file)
@@ -3433,7 +3433,9 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
       || else_assign == NULL
       || !gimple_assign_single_p (else_assign)
       || gimple_clobber_p (else_assign)
-      || gimple_has_volatile_ops (else_assign))
+      || gimple_has_volatile_ops (else_assign)
+      || stmt_references_abnormal_ssa_name (then_assign)
+      || stmt_references_abnormal_ssa_name (else_assign))
     return false;
 
   lhs = gimple_assign_lhs (then_assign);
index 880d6f70a80aa70cdc1393b621b4e92b3480ec29..e29de570f52c82e65c876e955a95577787a0059a 100644 (file)
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "tree-eh.h"
 #include "tree-ssa-live.h"
+#include "tree-dfa.h"
 
 /* TODO:
    1. Sinking store only using scalar promotion (IE without moving the RHS):
@@ -503,7 +504,8 @@ sink_common_stores_to_bb (basic_block bb)
              gimple *def = SSA_NAME_DEF_STMT (arg);
              if (! is_gimple_assign (def)
                  || stmt_can_throw_internal (cfun, def)
-                 || (gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL))
+                 || (gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL)
+                 || stmt_references_abnormal_ssa_name (def))
                {
                  /* ???  We could handle some cascading with the def being
                     another PHI.  We'd have to insert multiple PHIs for