tree-optimization/101025 - fix store-motion dependence checking
authorRichard Biener <rguenther@suse.de>
Fri, 11 Jun 2021 10:06:08 +0000 (12:06 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 11 Jun 2021 16:12:30 +0000 (18:12 +0200)
This plugs a hole in store-motion where it fails to perform dependence
checking on conditionally executed but not store-motioned refs.

2021-06-11  Richard Biener  <rguenther@suse.de>

PR tree-optimization/101025
* tree-ssa-loop-im.c (sm_seq_valid_bb): Make sure to process
all refs that require dependence checking.

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

gcc/testsuite/gcc.dg/torture/pr101025.c [new file with mode: 0644]
gcc/tree-ssa-loop-im.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr101025.c b/gcc/testsuite/gcc.dg/torture/pr101025.c
new file mode 100644 (file)
index 0000000..483e0ff
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+
+int a[10];
+int b, d, g;
+volatile char c;
+short e;
+volatile int f;
+int main()
+{
+  for (; d <= 9; d++) {
+      b = e = 0;
+      for (; e < 4; e++)
+        a[e] = 4;
+      for (; b <= 3; b++)
+        if (g)
+          f = 0;
+        else
+          a[b] = c;
+  }
+  if (a[1] != 0)
+    __builtin_abort ();
+  return 0;
+}
index 8034cf6..1c865b2 100644 (file)
@@ -2169,6 +2169,7 @@ execute_sm (class loop *loop, im_mem_ref *ref,
 enum sm_kind { sm_ord, sm_unord, sm_other };
 struct seq_entry
 {
+  seq_entry () {}
   seq_entry (unsigned f, sm_kind k, tree fr = NULL)
     : first (f), second (k), from (fr) {}
   unsigned first;
@@ -2352,6 +2353,8 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
              unsigned min_len = MIN(first_edge_seq.length (),
                                     edge_seq.length ());
              /* Incrementally merge seqs into first_edge_seq.  */
+             int first_uneq = -1;
+             auto_vec<seq_entry, 2> extra_refs;
              for (unsigned int i = 0; i < min_len; ++i)
                {
                  /* ???  We can more intelligently merge when we face different
@@ -2367,6 +2370,11 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
                        bitmap_set_bit (refs_not_supported, edge_seq[i].first);
                      first_edge_seq[i].second = sm_other;
                      first_edge_seq[i].from = NULL_TREE;
+                     /* Record the dropped refs for later processing.  */
+                     if (first_uneq == -1)
+                       first_uneq = i;
+                     extra_refs.safe_push (seq_entry (edge_seq[i].first,
+                                                      sm_other, NULL_TREE));
                    }
                  /* sm_other prevails.  */
                  else if (first_edge_seq[i].second != edge_seq[i].second)
@@ -2399,10 +2407,36 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
                }
              else if (edge_seq.length () > first_edge_seq.length ())
                {
+                 if (first_uneq == -1)
+                   first_uneq = first_edge_seq.length ();
                  for (unsigned i = first_edge_seq.length ();
                       i < edge_seq.length (); ++i)
-                   if (edge_seq[i].second == sm_ord)
-                     bitmap_set_bit (refs_not_supported, edge_seq[i].first);
+                   {
+                     if (edge_seq[i].second == sm_ord)
+                       bitmap_set_bit (refs_not_supported, edge_seq[i].first);
+                     extra_refs.safe_push (seq_entry (edge_seq[i].first,
+                                                      sm_other, NULL_TREE));
+                   }
+               }
+             /* Put unmerged refs at first_uneq to force dependence checking
+                on them.  */
+             if (first_uneq != -1)
+               {
+                 /* Missing ordered_splice_at.  */
+                 if ((unsigned)first_uneq == first_edge_seq.length ())
+                   first_edge_seq.safe_splice (extra_refs);
+                 else
+                   {
+                     unsigned fes_length = first_edge_seq.length ();
+                     first_edge_seq.safe_grow (fes_length
+                                               + extra_refs.length ());
+                     memmove (&first_edge_seq[first_uneq + extra_refs.length ()],
+                              &first_edge_seq[first_uneq],
+                              (fes_length - first_uneq) * sizeof (seq_entry));
+                     memcpy (&first_edge_seq[first_uneq],
+                             extra_refs.address (),
+                             extra_refs.length () * sizeof (seq_entry));
+                   }
                }
            }
          /* Use the sequence from the first edge and push SMs down.  */