From be9a0da55efc35bcdafbd53d1feb169358ca6748 Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Tue, 13 May 2014 10:09:54 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++ gcc/testsuite/ChangeLog | 4 ++ .../gcc.dg/tree-ssa/ivopts-lower_base.c | 61 +++++++++++++++++++ gcc/tree-ssa-loop-ivopts.c | 46 ++++++++++---- 4 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8352d09f314e..a6cb773cd0ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-05-13 Bin Cheng + + * tree-ssa-loop-ivopts.c (contain_complex_addr_expr): New. + (alloc_iv): Lower base expressions containing ADDR_EXPR. + 2014-05-13 Ian Bolton * config/aarch64/aarch64-protos.h diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b99777ebf417..1428a133a7c2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-13 Bin Cheng + + * gcc.dg/tree-ssa/ivopts-lower_base.c: New test. + 2014-05-13 Jakub Jelinek PR target/61060 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c new file mode 100644 index 000000000000..3b2b81f46a4d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ivopts-details" } */ +#include +#include + +#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" } } */ diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index b0d39271798f..b24463df4081 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -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;