new file mode 100644
@@ -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" } } */
@@ -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;