Hi,
I ran into this when investigating PR82369 which we failed to find base object.
This simple patch tries harder to find base object by expanding base address
in alloc_iv.  In general, we don't want to do aggressive expansion, but this
case is fine because finding base object means reduction happened during the
expansion.  And it's good to have base object for address type iv_uses.
Bootstrap and test on x86_64 and AArch64.  Is it OK?

Thanks,
bin
2017-10-12  Bin Cheng  <bin.ch...@arm.com>

        * tree-scalar-evolution.c (alloc_iv): New parameter controlling
        base expansion for finding base object.
        (find_interesting_uses_address): Adjust call to alloc_iv.

gcc/testsuite
2017-10-12  Bin Cheng  <bin.ch...@arm.com>

        * gcc.dg/tree-ssa/ivopt_6.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_6.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_6.c
new file mode 100644
index 0000000..de94b88
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_6.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+
+typedef unsigned long int uintptr_t;
+typedef long unsigned int size_t;
+typedef long int ptrdiff_t;
+
+void foo (unsigned char *restrict dst, unsigned char *restrict src, size_t 
bytes)
+{
+  uintptr_t end_dst = (uintptr_t) (dst + bytes);
+  uintptr_t srcu = (uintptr_t) src, dstu = (uintptr_t) dst;
+  ptrdiff_t src_dst_offset = srcu - 2 * dstu;
+
+  do {
+     unsigned char v0 = *(unsigned char *) (dstu * 2 + src_dst_offset);
+     unsigned char v1 = *(unsigned char *) ((dstu * 2 + src_dst_offset) + 1);
+     unsigned char res = v1 + v0;
+
+     *((unsigned char*) dstu) = res;
+     dstu += 16;
+  } while (dstu < end_dst);
+}
+/* { dg-final { scan-tree-dump-times "Type:\tADDRESS" 3 "ivopts" } } */
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index bbea619..4ccdf32 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1160,11 +1160,12 @@ contain_complex_addr_expr (tree expr)
 }
 
 /* Allocates an induction variable with given initial value BASE and step STEP
-   for loop LOOP.  NO_OVERFLOW implies the iv doesn't overflow.  */
+   for loop LOOP.  NO_OVERFLOW implies the iv doesn't overflow.  If EXPAND_P
+   is true, this function expands base address to find base object.  */
 
 static struct iv *
 alloc_iv (struct ivopts_data *data, tree base, tree step,
-         bool no_overflow = false)
+         bool no_overflow = false, bool expand_p = false)
 {
   tree expr = base;
   struct iv *iv = (struct iv*) obstack_alloc (&data->iv_obstack,
@@ -1185,8 +1186,22 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
       base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
     }
 
+  tree base_object = determine_base_object (base);
+  /* Try harder to find base object by expanding base.  */
+  if (expand_p && base_object == NULL_TREE)
+    {
+      aff_tree comb;
+      expr = unshare_expr (base);
+      tree_to_aff_combination_expand (base, TREE_TYPE (base), &comb,
+                                     &data->name_expansion_cache);
+      base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
+      base_object = determine_base_object (base);
+      /* Fall back to unexpanded base if no base object is found.  */
+      if (!base_object)
+       base = expr;
+    }
   iv->base = base;
-  iv->base_object = determine_base_object (base);
+  iv->base_object = base_object;
   iv->step = step;
   iv->biv_p = false;
   iv->nonlin_use = NULL;
@@ -2365,7 +2380,7 @@ find_interesting_uses_address (struct ivopts_data *data, 
gimple *stmt,
        }
     }
 
-  civ = alloc_iv (data, base, step);
+  civ = alloc_iv (data, base, step, false, true);
   /* Fail if base object of this memory reference is unknown.  */
   if (civ->base_object == NULL_TREE)
     goto fail;

Reply via email to