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;
