The following testcase shows a missed optimization that then leads to
wrong-code when issueing SMed stores on exits.  When we were able to
compute an ordered sequence of stores for an exit we need to emit
that in the correct order and we can emit it disregarding to any
conditional for whether a store actually happened (we know it did).
We can also improve detection as of whether we need conditional
processing at all.  Both parts fix the testcase.

Bootstrapped / tested on x86_64-unknown-linux-gnu, applied.

2020-05-18  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/95172
        * tree-ssa-loop-im.c (execute_sm): Get flag whether we
        eventually need the conditional processing.
        (execute_sm_exit): When processing an orderd sequence
        avoid doing any conditional processing.
        (hoist_memory_references): Pass down whether all edges
        have ordered processing for a ref to execute_sm.

        * gcc.dg/torture/pr95172.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr95172.c | 17 +++++++++++++++++
 gcc/tree-ssa-loop-im.c                 | 11 ++++++-----
 2 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr95172.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr95172.c 
b/gcc/testsuite/gcc.dg/torture/pr95172.c
new file mode 100644
index 00000000000..b39de69f08e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr95172.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+
+int a, d;
+int *b = &a;
+short c;
+int main()
+{
+  for (; c <= 4; c--) {
+    for (; d;)
+      ;
+    a = 1;
+    *b = 0;
+  }
+  if (a != 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 0d77aaa08a5..63f4ef8883c 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -2130,7 +2130,7 @@ struct sm_aux
 
 static void
 execute_sm (class loop *loop, im_mem_ref *ref,
-           hash_map<im_mem_ref *, sm_aux *> &aux_map)
+           hash_map<im_mem_ref *, sm_aux *> &aux_map, bool maybe_mt)
 {
   gassign *load;
   struct fmt_data fmt_data;
@@ -2154,8 +2154,9 @@ execute_sm (class loop *loop, im_mem_ref *ref,
   for_each_index (&ref->mem.ref, force_move_till, &fmt_data);
 
   bool always_stored = ref_always_accessed_p (loop, ref, true);
-  if (bb_in_transaction (loop_preheader_edge (loop)->src)
-      || (! flag_store_data_races && ! always_stored))
+  if (maybe_mt
+      && (bb_in_transaction (loop_preheader_edge (loop)->src)
+         || (! flag_store_data_races && ! always_stored)))
     multi_threaded_model_p = true;
 
   if (multi_threaded_model_p)
@@ -2244,7 +2245,7 @@ execute_sm_exit (class loop *loop, edge ex, 
vec<seq_entry> &seq,
       else
        {
          sm_aux *aux = *aux_map.get (ref);
-         if (!aux->store_flag)
+         if (!aux->store_flag || kind == sm_ord)
            {
              gassign *store;
              store = gimple_build_assign (unshare_expr (ref->mem.ref),
@@ -2630,7 +2631,7 @@ hoist_memory_references (class loop *loop, bitmap 
mem_refs,
   EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi)
     {
       ref = memory_accesses.refs_list[i];
-      execute_sm (loop, ref, aux_map);
+      execute_sm (loop, ref, aux_map, bitmap_bit_p (refs_not_supported, i));
     }
 
   /* Materialize ordered store sequences on exits.  */
-- 
2.12.3

Reply via email to