tree-ssa-loop-ivopts.c (contain_complex_addr_expr): New.
* tree-ssa-loop-ivopts.c (contain_complex_addr_expr): New. (alloc_iv): Lower base expressions containing ADDR_EXPR. * gcc.dg/tree-ssa/ivopts-lower_base.c: New test. From-SVN: r210356
This commit is contained in:
parent
73d9ac6a6a
commit
be9a0da55e
4 changed files with 105 additions and 11 deletions
|
@ -1,3 +1,8 @@
|
|||
2014-05-13 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* tree-ssa-loop-ivopts.c (contain_complex_addr_expr): New.
|
||||
(alloc_iv): Lower base expressions containing ADDR_EXPR.
|
||||
|
||||
2014-05-13 Ian Bolton <ian.bolton@arm.com>
|
||||
|
||||
* config/aarch64/aarch64-protos.h
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2014-05-13 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* gcc.dg/tree-ssa/ivopts-lower_base.c: New test.
|
||||
|
||||
2014-05-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/61060
|
||||
|
|
61
gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c
Normal file
61
gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_NUM (256)
|
||||
|
||||
void
|
||||
sort_pointers (size_t n, void **pointers, void **work)
|
||||
{
|
||||
typedef unsigned char digit_t;
|
||||
unsigned int count[MAX_NUM];
|
||||
int big_endian_p;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if ((sizeof (void *) / sizeof (digit_t)) % 2 != 0)
|
||||
abort ();
|
||||
|
||||
for (i = 0, j = 0; i < sizeof (size_t); ++i)
|
||||
{
|
||||
j *= MAX_NUM;
|
||||
j += i;
|
||||
}
|
||||
|
||||
big_endian_p = (((char *)&j)[0] == 0);
|
||||
for (i = 0; i < sizeof (void *) / sizeof (digit_t); ++i)
|
||||
{
|
||||
digit_t *digit;
|
||||
digit_t *bias;
|
||||
digit_t *top;
|
||||
unsigned int *countp;
|
||||
void **pointerp;
|
||||
|
||||
if (big_endian_p)
|
||||
j = sizeof (void *) / sizeof (digit_t) - i;
|
||||
else
|
||||
j = i;
|
||||
|
||||
memset (count, 0, MAX_NUM * sizeof (unsigned int));
|
||||
bias = ((digit_t *) pointers) + j;
|
||||
top = ((digit_t *) (pointers + n)) + j;
|
||||
for (digit = bias;
|
||||
digit < top;
|
||||
digit += sizeof (void *) / sizeof (digit_t))
|
||||
++count[*digit];
|
||||
|
||||
for (countp = count + 1; countp < count + MAX_NUM; ++countp)
|
||||
*countp += countp[-1];
|
||||
|
||||
for (pointerp = pointers + n - 1; pointerp >= pointers; --pointerp)
|
||||
work[--count[((digit_t *) pointerp)[j]]] = *pointerp;
|
||||
|
||||
pointerp = pointers;
|
||||
pointers = work;
|
||||
work = pointerp;
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "base \[^\\n\]*&MEM\\\[" "ivopts" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ivopts" } } */
|
|
@ -928,36 +928,60 @@ determine_base_object (tree expr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return true if address expression with non-DECL_P operand appears
|
||||
in EXPR. */
|
||||
|
||||
static bool
|
||||
contain_complex_addr_expr (tree expr)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
STRIP_NOPS (expr);
|
||||
switch (TREE_CODE (expr))
|
||||
{
|
||||
case POINTER_PLUS_EXPR:
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
res |= contain_complex_addr_expr (TREE_OPERAND (expr, 0));
|
||||
res |= contain_complex_addr_expr (TREE_OPERAND (expr, 1));
|
||||
break;
|
||||
|
||||
case ADDR_EXPR:
|
||||
return (!DECL_P (TREE_OPERAND (expr, 0)));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Allocates an induction variable with given initial value BASE and step STEP
|
||||
for loop LOOP. */
|
||||
|
||||
static struct iv *
|
||||
alloc_iv (tree base, tree step)
|
||||
{
|
||||
tree base_object = base;
|
||||
tree expr = base;
|
||||
struct iv *iv = XCNEW (struct iv);
|
||||
gcc_assert (step != NULL_TREE);
|
||||
|
||||
/* Lower all address expressions except ones with DECL_P as operand.
|
||||
/* Lower address expression in base except ones with DECL_P as operand.
|
||||
By doing this:
|
||||
1) More accurate cost can be computed for address expressions;
|
||||
2) Duplicate candidates won't be created for bases in different
|
||||
forms, like &a[0] and &a. */
|
||||
STRIP_NOPS (base_object);
|
||||
if (TREE_CODE (base_object) == ADDR_EXPR
|
||||
&& !DECL_P (TREE_OPERAND (base_object, 0)))
|
||||
STRIP_NOPS (expr);
|
||||
if ((TREE_CODE (expr) == ADDR_EXPR && !DECL_P (TREE_OPERAND (expr, 0)))
|
||||
|| contain_complex_addr_expr (expr))
|
||||
{
|
||||
aff_tree comb;
|
||||
widest_int size;
|
||||
base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0),
|
||||
&comb, &size);
|
||||
gcc_assert (base_object != NULL_TREE);
|
||||
base_object = build_fold_addr_expr (base_object);
|
||||
tree_to_aff_combination (expr, TREE_TYPE (base), &comb);
|
||||
base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
|
||||
}
|
||||
|
||||
iv->base = base;
|
||||
iv->base_object = determine_base_object (base_object);
|
||||
iv->base_object = determine_base_object (base);
|
||||
iv->step = step;
|
||||
iv->biv_p = false;
|
||||
iv->have_use_for = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue