diff mbox series

[062/nnn] poly_int: prune_runtime_alias_test_list

Message ID 87fua9kc86.fsf@linaro.org
State New
Headers show
Series [062/nnn] poly_int: prune_runtime_alias_test_list | expand

Commit Message

Richard Sandiford Oct. 23, 2017, 5:25 p.m. UTC
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.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@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.

Comments

Jeff Law Dec. 5, 2017, 5:33 p.m. UTC | #1
On 10/23/2017 11:25 AM, Richard Sandiford wrote:
> 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.sandiford@linaro.org>

> 	    Alan Hayward  <alan.hayward@arm.com>

> 	    David Sherwood  <david.sherwood@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.

This is OK.  Note that both Richi and Bin have been pretty active in
this general area.  So adjustments may be needed.


Jeff
diff mbox series

Patch

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;