This patch makes prune_runtime_alias_test_list take the iteration
factor as a poly_int and tracks polynomial offsets internally
as well.


2017-10-23  Richard Sandiford  <richard.sandif...@linaro.org>
            Alan Hayward  <alan.hayw...@arm.com>
            David Sherwood  <david.sherw...@arm.com>

gcc/
        * tree-data-ref.h (prune_runtime_alias_test_list): Take the
        factor as a poly_uint64 rather than an unsigned HOST_WIDE_INT.
        * tree-data-ref.c (prune_runtime_alias_test_list): Likewise.
        Track polynomial offsets.

Index: gcc/tree-data-ref.h
===================================================================
--- gcc/tree-data-ref.h 2017-10-13 10:23:39.775145588 +0100
+++ gcc/tree-data-ref.h 2017-10-23 17:22:25.492282436 +0100
@@ -472,7 +472,7 @@ extern bool dr_equal_offsets_p (struct d
 extern bool runtime_alias_check_p (ddr_p, struct loop *, bool);
 extern int data_ref_compare_tree (tree, tree);
 extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
-                                          unsigned HOST_WIDE_INT);
+                                          poly_uint64);
 extern void create_runtime_alias_checks (struct loop *,
                                         vec<dr_with_seg_len_pair_t> *, tree*);
 /* Return true when the base objects of data references A and B are
Index: gcc/tree-data-ref.c
===================================================================
--- gcc/tree-data-ref.c 2017-10-23 17:22:18.231825655 +0100
+++ gcc/tree-data-ref.c 2017-10-23 17:22:25.492282436 +0100
@@ -1417,7 +1417,7 @@ comp_dr_with_seg_len_pair (const void *p
 
 void
 prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
-                              unsigned HOST_WIDE_INT factor)
+                              poly_uint64 factor)
 {
   /* Sort the collected data ref pairs so that we can scan them once to
      combine all possible aliasing checks.  */
@@ -1462,51 +1462,63 @@ prune_runtime_alias_test_list (vec<dr_wi
              std::swap (dr_a2, dr_b2);
            }
 
+         poly_int64 init_a1, init_a2;
          if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
                                DR_BASE_ADDRESS (dr_a2->dr), 0)
              || !operand_equal_p (DR_OFFSET (dr_a1->dr),
                                   DR_OFFSET (dr_a2->dr), 0)
-             || !tree_fits_shwi_p (DR_INIT (dr_a1->dr))
-             || !tree_fits_shwi_p (DR_INIT (dr_a2->dr)))
+             || !poly_int_tree_p (DR_INIT (dr_a1->dr), &init_a1)
+             || !poly_int_tree_p (DR_INIT (dr_a2->dr), &init_a2))
            continue;
 
+         /* Don't combine if we can't tell which one comes first.  */
+         if (!ordered_p (init_a1, init_a2))
+           continue;
+
+         /* Make sure dr_a1 starts left of dr_a2.  */
+         if (may_gt (init_a1, init_a2))
+           {
+             std::swap (*dr_a1, *dr_a2);
+             std::swap (init_a1, init_a2);
+           }
+
          /* Only merge const step data references.  */
-         if (TREE_CODE (DR_STEP (dr_a1->dr)) != INTEGER_CST
-             || TREE_CODE (DR_STEP (dr_a2->dr)) != INTEGER_CST)
+         poly_int64 step_a1, step_a2;
+         if (!poly_int_tree_p (DR_STEP (dr_a1->dr), &step_a1)
+             || !poly_int_tree_p (DR_STEP (dr_a2->dr), &step_a2))
            continue;
 
-         /* DR_A1 and DR_A2 must goes in the same direction.  */
-         if (tree_int_cst_compare (DR_STEP (dr_a1->dr), size_zero_node)
-             != tree_int_cst_compare (DR_STEP (dr_a2->dr), size_zero_node))
+         bool neg_step = may_lt (step_a1, 0) || may_lt (step_a2, 0);
+
+         /* DR_A1 and DR_A2 must go in the same direction.  */
+         if (neg_step && (may_gt (step_a1, 0) || may_gt (step_a2, 0)))
            continue;
 
-         bool neg_step
-           = (tree_int_cst_compare (DR_STEP (dr_a1->dr), size_zero_node) < 0);
+         poly_uint64 seg_len_a1 = 0, seg_len_a2 = 0;
+         bool const_seg_len_a1 = poly_int_tree_p (dr_a1->seg_len,
+                                                  &seg_len_a1);
+         bool const_seg_len_a2 = poly_int_tree_p (dr_a2->seg_len,
+                                                  &seg_len_a2);
 
          /* We need to compute merged segment length at compilation time for
             dr_a1 and dr_a2, which is impossible if either one has non-const
             segment length.  */
-         if ((!tree_fits_uhwi_p (dr_a1->seg_len)
-              || !tree_fits_uhwi_p (dr_a2->seg_len))
-             && tree_int_cst_compare (DR_STEP (dr_a1->dr),
-                                      DR_STEP (dr_a2->dr)) != 0)
+         if ((!const_seg_len_a1 || !const_seg_len_a2)
+             && may_ne (step_a1, step_a2))
            continue;
 
-         /* Make sure dr_a1 starts left of dr_a2.  */
-         if (tree_int_cst_lt (DR_INIT (dr_a2->dr), DR_INIT (dr_a1->dr)))
-           std::swap (*dr_a1, *dr_a2);
-
          bool do_remove = false;
-         wide_int diff = (wi::to_wide (DR_INIT (dr_a2->dr))
-                          - wi::to_wide (DR_INIT (dr_a1->dr)));
-         wide_int min_seg_len_b;
+         poly_uint64 diff = init_a2 - init_a1;
+         poly_uint64 min_seg_len_b;
          tree new_seg_len;
 
-         if (TREE_CODE (dr_b1->seg_len) == INTEGER_CST)
-           min_seg_len_b = wi::abs (wi::to_wide (dr_b1->seg_len));
-         else
-           min_seg_len_b
-             = factor * wi::abs (wi::to_wide (DR_STEP (dr_b1->dr)));
+         if (!poly_int_tree_p (dr_b1->seg_len, &min_seg_len_b))
+           {
+             tree step_b = DR_STEP (dr_b1->dr);
+             if (!tree_fits_shwi_p (step_b))
+               continue;
+             min_seg_len_b = factor * abs_hwi (tree_to_shwi (step_b));
+           }
 
          /* Now we try to merge alias check dr_a1 & dr_b and dr_a2 & dr_b.
 
@@ -1543,26 +1555,24 @@ prune_runtime_alias_test_list (vec<dr_wi
          if (neg_step)
            {
              /* Adjust diff according to access size of both references.  */
-             tree size_a1 = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a1->dr)));
-             tree size_a2 = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a2->dr)));
-             diff += wi::to_wide (size_a2) - wi::to_wide (size_a1);
+             diff += tree_to_poly_uint64
+               (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a2->dr))));
+             diff -= tree_to_poly_uint64
+               (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a1->dr))));
              /* Case A.1.  */
-             if (wi::leu_p (diff, min_seg_len_b)
+             if (must_le (diff, min_seg_len_b)
                  /* Case A.2 and B combined.  */
-                 || (tree_fits_uhwi_p (dr_a2->seg_len)))
+                 || const_seg_len_a2)
                {
-                 if (tree_fits_uhwi_p (dr_a1->seg_len)
-                     && tree_fits_uhwi_p (dr_a2->seg_len))
-                   {
-                     wide_int min_len
-                       = wi::umin (wi::to_wide (dr_a1->seg_len) - diff,
-                                   wi::to_wide (dr_a2->seg_len));
-                     new_seg_len = wide_int_to_tree (sizetype, min_len);
-                   }
+                 if (const_seg_len_a1 || const_seg_len_a2)
+                   new_seg_len
+                     = build_int_cstu (sizetype,
+                                       lower_bound (seg_len_a1 - diff,
+                                                    seg_len_a2));
                  else
                    new_seg_len
                      = size_binop (MINUS_EXPR, dr_a2->seg_len,
-                                   wide_int_to_tree (sizetype, diff));
+                                   build_int_cstu (sizetype, diff));
 
                  dr_a2->seg_len = new_seg_len;
                  do_remove = true;
@@ -1571,22 +1581,19 @@ prune_runtime_alias_test_list (vec<dr_wi
          else
            {
              /* Case A.1.  */
-             if (wi::leu_p (diff, min_seg_len_b)
+             if (must_le (diff, min_seg_len_b)
                  /* Case A.2 and B combined.  */
-                 || (tree_fits_uhwi_p (dr_a1->seg_len)))
+                 || const_seg_len_a1)
                {
-                 if (tree_fits_uhwi_p (dr_a1->seg_len)
-                     && tree_fits_uhwi_p (dr_a2->seg_len))
-                   {
-                     wide_int max_len
-                       = wi::umax (wi::to_wide (dr_a2->seg_len) + diff,
-                                   wi::to_wide (dr_a1->seg_len));
-                     new_seg_len = wide_int_to_tree (sizetype, max_len);
-                   }
+                 if (const_seg_len_a1 && const_seg_len_a2)
+                   new_seg_len
+                     = build_int_cstu (sizetype,
+                                       upper_bound (seg_len_a2 + diff,
+                                                    seg_len_a1));
                  else
                    new_seg_len
                      = size_binop (PLUS_EXPR, dr_a2->seg_len,
-                                   wide_int_to_tree (sizetype, diff));
+                                   build_int_cstu (sizetype, diff));
 
                  dr_a1->seg_len = new_seg_len;
                  do_remove = true;

Reply via email to