Avoid quadratic behaviour in prune_runtime_alias_test_list
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 6 Dec 2019 10:31:44 +0000 (10:31 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 6 Dec 2019 10:31:44 +0000 (10:31 +0000)
prune_runtime_alias_test_list used ordered_remove to remove a merged
alias pair, which made the function quadratic when many aliases could
be removed.

I had a testcase in which these memmoves accounted for an impressive
85% of compile time.  The fact that we had so many probably shows
a deeper problem, but still, it's easy to remove as we go.

2019-12-06  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* tree-data-ref.c (prune_runtime_alias_test_list): Exit early
for empty vectors.  Avoid using ordered_remove and instead
shuffle the vector as we go.

From-SVN: r279038

gcc/ChangeLog
gcc/tree-data-ref.c

index cf5b66601f08fce5479ba95227a1394bea809d62..68da94ae735ee0dc19a49a4f206d6b0c50142243 100644 (file)
@@ -1,3 +1,9 @@
+2019-12-06  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * tree-data-ref.c (prune_runtime_alias_test_list): Exit early
+       for empty vectors.  Avoid using ordered_remove and instead
+       shuffle the vector as we go.
+
 2019-12-06  Richard Biener  <rguenther@suse.de>
 
        * genmatch.c (enum tree_code): Remove CONVERT{0,1,2} and
index 117a14b29971cf376c39e619f806a3d1f663a901..7ef891de5e985299dd8a5a2ee3af28f2aa19de37 100644 (file)
@@ -1535,6 +1535,9 @@ void
 prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
                               poly_uint64)
 {
+  if (alias_pairs->is_empty ())
+    return;
+
   /* Canonicalize each pair so that the base components are ordered wrt
      data_ref_compare_tree.  This allows the loop below to merge more
      cases.  */
@@ -1565,10 +1568,11 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
 
   /* Scan the sorted dr pairs and check if we can combine alias checks
      of two neighboring dr pairs.  */
+  unsigned int last = 0;
   for (i = 1; i < alias_pairs->length (); ++i)
     {
       /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2).  */
-      dr_with_seg_len_pair_t *alias_pair1 = &(*alias_pairs)[i - 1];
+      dr_with_seg_len_pair_t *alias_pair1 = &(*alias_pairs)[last];
       dr_with_seg_len_pair_t *alias_pair2 = &(*alias_pairs)[i];
 
       dr_with_seg_len *dr_a1 = &alias_pair1->first;
@@ -1584,10 +1588,15 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
                         DR_REF (dr_a1->dr), DR_REF (dr_b1->dr),
                         DR_REF (dr_a2->dr), DR_REF (dr_b2->dr));
          alias_pair1->flags |= alias_pair2->flags;
-         alias_pairs->ordered_remove (i--);
          continue;
        }
 
+      /* Assume that we won't be able to merge the pairs, then correct
+        if we do.  */
+      last += 1;
+      if (last != i)
+       (*alias_pairs)[last] = (*alias_pairs)[i];
+
       if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2)
        {
          /* We consider the case that DR_B1 and DR_B2 are same memrefs,
@@ -1695,10 +1704,10 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
                         DR_REF (dr_a1->dr), DR_REF (dr_b1->dr),
                         DR_REF (dr_a2->dr), DR_REF (dr_b2->dr));
          alias_pair1->flags |= alias_pair2->flags;
-         alias_pairs->ordered_remove (i);
-         i--;
+         last -= 1;
        }
     }
+  alias_pairs->truncate (last + 1);
 
   /* Try to restore the original dr_with_seg_len order within each
      dr_with_seg_len_pair_t.  If we ended up combining swapped and