poly_int: tree-ssa-loop-ivopts.c:iv_use
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 21 Dec 2017 07:02:36 +0000 (07:02 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 21 Dec 2017 07:02:36 +0000 (07:02 +0000)
This patch makes ivopts handle polynomial address offsets
when recording potential IV uses.

2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* tree-ssa-loop-ivopts.h (strip_offset): Return the offset as
poly_uint64_pod rather than an unsigned HOST_WIDE_INT.
* tree-loop-distribution.c (classify_builtin_st): Update accordingly.
* tree-ssa-loop-ivopts.c (iv_use::addr_offset): Change from
an unsigned HOST_WIDE_INT to a poly_uint64_pod.
(group_compare_offset): Update accordingly.
(split_small_address_groups_p): Likewise.
(record_use): Take addr_offset as a poly_uint64 rather than
an unsigned HOST_WIDE_INT.
(strip_offset): Return the offset as a poly_uint64 rather than
an unsigned HOST_WIDE_INT.
(record_group_use, split_address_groups): Track polynomial offsets.
(add_iv_candidate_for_use): Likewise.
(addr_offset_valid_p): Take the offset as a poly_int64 rather
than a HOST_WIDE_INT.
(strip_offset_1): Return the offset as a poly_int64 rather than
a HOST_WIDE_INT.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r255933

gcc/ChangeLog
gcc/tree-loop-distribution.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-ivopts.h

index 9aa16a381a990f120729bdff19ad54b2a4355c87..5f45bd15d9b4c2a81324b7d01349d3a904576180 100644 (file)
@@ -1,3 +1,25 @@
+2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * tree-ssa-loop-ivopts.h (strip_offset): Return the offset as
+       poly_uint64_pod rather than an unsigned HOST_WIDE_INT.
+       * tree-loop-distribution.c (classify_builtin_st): Update accordingly.
+       * tree-ssa-loop-ivopts.c (iv_use::addr_offset): Change from
+       an unsigned HOST_WIDE_INT to a poly_uint64_pod.
+       (group_compare_offset): Update accordingly.
+       (split_small_address_groups_p): Likewise.
+       (record_use): Take addr_offset as a poly_uint64 rather than
+       an unsigned HOST_WIDE_INT.
+       (strip_offset): Return the offset as a poly_uint64 rather than
+       an unsigned HOST_WIDE_INT.
+       (record_group_use, split_address_groups): Track polynomial offsets.
+       (add_iv_candidate_for_use): Likewise.
+       (addr_offset_valid_p): Take the offset as a poly_int64 rather
+       than a HOST_WIDE_INT.
+       (strip_offset_1): Return the offset as a poly_int64 rather than
+       a HOST_WIDE_INT.
+
 2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 7439a1f370e8f17470ea4007ae5722705f786ad2..e195a46a36e311f29e7670005cba33a41a85b66f 100644 (file)
@@ -1513,10 +1513,16 @@ classify_builtin_st (loop_p loop, partition *partition, data_reference_p dr)
   if (!compute_access_range (loop, dr, &base, &size))
     return;
 
+  poly_uint64 base_offset;
+  unsigned HOST_WIDE_INT const_base_offset;
+  tree base_base = strip_offset (base, &base_offset);
+  if (!base_offset.is_constant (&const_base_offset))
+    return;
+
   struct builtin_info *builtin;
   builtin = alloc_builtin (dr, NULL, base, NULL_TREE, size);
-  builtin->dst_base_base = strip_offset (builtin->dst_base,
-                                        &builtin->dst_base_offset);
+  builtin->dst_base_base = base_base;
+  builtin->dst_base_offset = const_base_offset;
   partition->builtin = builtin;
   partition->kind = PKIND_MEMSET;
 }
index 5555f46eb305879278906ec6cc056356766ed5ac..b5d5ea629202b213981beef56433a25b9cd2319d 100644 (file)
@@ -367,7 +367,7 @@ struct iv_use
   tree *op_p;          /* The place where it occurs.  */
 
   tree addr_base;      /* Base address with const offset stripped.  */
-  unsigned HOST_WIDE_INT addr_offset;
+  poly_uint64_pod addr_offset;
                        /* Const offset stripped from base address.  */
 };
 
@@ -1508,7 +1508,7 @@ find_induction_variables (struct ivopts_data *data)
 static struct iv_use *
 record_use (struct iv_group *group, tree *use_p, struct iv *iv,
            gimple *stmt, enum use_type type, tree addr_base,
-           unsigned HOST_WIDE_INT addr_offset)
+           poly_uint64 addr_offset)
 {
   struct iv_use *use = XCNEW (struct iv_use);
 
@@ -1577,7 +1577,7 @@ record_group_use (struct ivopts_data *data, tree *use_p,
 {
   tree addr_base = NULL;
   struct iv_group *group = NULL;
-  unsigned HOST_WIDE_INT addr_offset = 0;
+  poly_uint64 addr_offset = 0;
 
   /* Record non address type use in a new group.  */
   if (type == USE_ADDRESS && iv->base_object)
@@ -2511,7 +2511,7 @@ find_interesting_uses_outside (struct ivopts_data *data, edge exit)
 static GTY (()) vec<rtx, va_gc> *addr_list;
 
 static bool
-addr_offset_valid_p (struct iv_use *use, HOST_WIDE_INT offset)
+addr_offset_valid_p (struct iv_use *use, poly_int64 offset)
 {
   rtx reg, addr;
   unsigned list_index;
@@ -2545,10 +2545,7 @@ group_compare_offset (const void *a, const void *b)
   const struct iv_use *const *u1 = (const struct iv_use *const *) a;
   const struct iv_use *const *u2 = (const struct iv_use *const *) b;
 
-  if ((*u1)->addr_offset != (*u2)->addr_offset)
-    return (*u1)->addr_offset < (*u2)->addr_offset ? -1 : 1;
-  else
-    return 0;
+  return compare_sizes_for_sort ((*u1)->addr_offset, (*u2)->addr_offset);
 }
 
 /* Check if small groups should be split.  Return true if no group
@@ -2579,7 +2576,8 @@ split_small_address_groups_p (struct ivopts_data *data)
       gcc_assert (group->type == USE_ADDRESS);
       if (group->vuses.length () == 2)
        {
-         if (group->vuses[0]->addr_offset > group->vuses[1]->addr_offset)
+         if (compare_sizes_for_sort (group->vuses[0]->addr_offset,
+                                     group->vuses[1]->addr_offset) > 0)
            std::swap (group->vuses[0], group->vuses[1]);
        }
       else
@@ -2591,7 +2589,7 @@ split_small_address_groups_p (struct ivopts_data *data)
       distinct = 1;
       for (pre = group->vuses[0], j = 1; j < group->vuses.length (); j++)
        {
-         if (group->vuses[j]->addr_offset != pre->addr_offset)
+         if (maybe_ne (group->vuses[j]->addr_offset, pre->addr_offset))
            {
              pre = group->vuses[j];
              distinct++;
@@ -2632,13 +2630,13 @@ split_address_groups (struct ivopts_data *data)
       for (j = 1; j < group->vuses.length ();)
        {
          struct iv_use *next = group->vuses[j];
-         HOST_WIDE_INT offset = next->addr_offset - use->addr_offset;
+         poly_int64 offset = next->addr_offset - use->addr_offset;
 
          /* Split group if aksed to, or the offset against the first
             use can't fit in offset part of addressing mode.  IV uses
             having the same offset are still kept in one group.  */
-         if (offset != 0 &&
-             (split_p || !addr_offset_valid_p (use, offset)))
+         if (maybe_ne (offset, 0)
+             && (split_p || !addr_offset_valid_p (use, offset)))
            {
              if (!new_group)
                new_group = record_group (data, group->type);
@@ -2699,12 +2697,13 @@ find_interesting_uses (struct ivopts_data *data)
 
 static tree
 strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
-               HOST_WIDE_INT *offset)
+               poly_int64 *offset)
 {
   tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step;
   enum tree_code code;
   tree type, orig_type = TREE_TYPE (expr);
-  HOST_WIDE_INT off0, off1, st;
+  poly_int64 off0, off1;
+  HOST_WIDE_INT st;
   tree orig_expr = expr;
 
   STRIP_NOPS (expr);
@@ -2715,14 +2714,6 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
 
   switch (code)
     {
-    case INTEGER_CST:
-      if (!cst_and_fits_in_hwi (expr)
-         || integer_zerop (expr))
-       return orig_expr;
-
-      *offset = int_cst_value (expr);
-      return build_int_cst (orig_type, 0);
-
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -2840,6 +2831,8 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
       break;
 
     default:
+      if (ptrdiff_tree_p (expr, offset) && maybe_ne (*offset, 0))
+       return build_int_cst (orig_type, 0);
       return orig_expr;
     }
 
@@ -2869,9 +2862,9 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
 /* Strips constant offsets from EXPR and stores them to OFFSET.  */
 
 tree
-strip_offset (tree expr, unsigned HOST_WIDE_INT *offset)
+strip_offset (tree expr, poly_uint64_pod *offset)
 {
-  HOST_WIDE_INT off;
+  poly_int64 off;
   tree core = strip_offset_1 (expr, false, false, &off);
   *offset = off;
   return core;
@@ -3398,7 +3391,7 @@ add_iv_candidate_derived_from_uses (struct ivopts_data *data)
 static void
 add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use)
 {
-  unsigned HOST_WIDE_INT offset;
+  poly_uint64 offset;
   tree base;
   tree basetype;
   struct iv *iv = use->iv;
@@ -3417,7 +3410,7 @@ add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use)
   /* Record common candidate with constant offset stripped in base.
      Like the use itself, we also add candidate directly for it.  */
   base = strip_offset (iv->base, &offset);
-  if (offset || base != iv->base)
+  if (maybe_ne (offset, 0U) || base != iv->base)
     {
       record_common_cand (data, base, iv->step, use);
       add_candidate (data, base, iv->step, false, use);
@@ -3436,7 +3429,7 @@ add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use)
       record_common_cand (data, base, step, use);
       /* Also record common candidate with offset stripped.  */
       base = strip_offset (base, &offset);
-      if (offset)
+      if (maybe_ne (offset, 0U))
        record_common_cand (data, base, step, use);
     }
 
index a723f46dae4b85a2b862c20b7a4b71e84152c1aa..cca3692203a67a3e431b23aabb92edb1c8cc246c 100644 (file)
@@ -28,7 +28,7 @@ extern void dump_cand (FILE *, struct iv_cand *);
 extern bool contains_abnormal_ssa_name_p (tree);
 extern struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
 extern bool expr_invariant_in_loop_p (struct loop *, tree);
-extern tree strip_offset (tree, unsigned HOST_WIDE_INT *);
+extern tree strip_offset (tree, poly_uint64_pod *);
 bool may_be_nonaddressable_p (tree expr);
 void tree_ssa_iv_optimize (void);