summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-02 14:30:39 +0000
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-02 14:30:39 +0000
commit2451b8b88f07121042f58a4f646cbc045f8630e0 (patch)
treef4baec2a8f727693a22c86047fb07064f6e86319 /gcc
parentfe9e92d635d662fe1cd8d03dea9d33a7457fb3d7 (diff)
downloadgcc-2451b8b88f07121042f58a4f646cbc045f8630e0.tar.gz
gcc/
PR tree-optimization/41857 * tree-flow.h (rewrite_use_address): Add BASE_HINT argument. * tree-ssa-loop-ivopts.c (rewrite_use_address): Pass base hint to create_mem_ref. * tree-ssa-address.c (move_hint_to_base): New function. (most_expensive_mult_to_index): Add TYPE argument. Use mode and address space associated with TYPE. (addr_to_parts): Add TYPE and BASE_HINT arguments. Pass TYPE to most_expensive_mult_to_index. Call move_hint_to_base. (create_mem_ref): Add BASE_HINT argument. Pass BASE_HINT and TYPE to addr_to_parts. gcc/testsuite/ PR tree-optimization/41857 * gcc.target/spu/ea/pr41857.c: New file. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153810 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/spu/ea/pr41857.c29
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-ssa-address.c59
-rw-r--r--gcc/tree-ssa-loop-ivopts.c18
6 files changed, 111 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index df8f0ed9082..3b64aed951c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2009-11-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ PR tree-optimization/41857
+ * tree-flow.h (rewrite_use_address): Add BASE_HINT argument.
+ * tree-ssa-loop-ivopts.c (rewrite_use_address): Pass base hint
+ to create_mem_ref.
+ * tree-ssa-address.c (move_hint_to_base): New function.
+ (most_expensive_mult_to_index): Add TYPE argument. Use mode and
+ address space associated with TYPE.
+ (addr_to_parts): Add TYPE and BASE_HINT arguments. Pass TYPE to
+ most_expensive_mult_to_index. Call move_hint_to_base.
+ (create_mem_ref): Add BASE_HINT argument. Pass BASE_HINT and
+ TYPE to addr_to_parts.
+
2009-11-02 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/41750
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4fe2079320b..2d1378aa7a9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-11-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ PR tree-optimization/41857
+ * gcc.target/spu/ea/pr41857.c: New file.
+
2009-11-02 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/41750
diff --git a/gcc/testsuite/gcc.target/spu/ea/pr41857.c b/gcc/testsuite/gcc.target/spu/ea/pr41857.c
new file mode 100644
index 00000000000..17710674cf6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/spu/ea/pr41857.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This file is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* { dg-do compile } */
+
+__ea char *strchr_ea (__ea const char *s, int c);
+__ea char *foo (__ea char *s)
+{
+ __ea char *ret = s;
+ int i;
+
+ for (i = 0; i < 3; i++)
+ ret = strchr_ea (ret, s[i]);
+
+ return ret;
+}
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index a7015691811..40fad2dd556 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -921,7 +921,7 @@ struct mem_address
struct affine_tree_combination;
tree create_mem_ref (gimple_stmt_iterator *, tree,
- struct affine_tree_combination *, bool);
+ struct affine_tree_combination *, tree, bool);
rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
void get_address_description (tree, struct mem_address *);
tree maybe_fold_tmr (tree);
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 1428803272f..37bce5e2d2e 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -392,6 +392,33 @@ move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
aff_combination_remove_elt (addr, i);
}
+/* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */
+
+static void
+move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
+ aff_tree *addr)
+{
+ unsigned i;
+ tree val = NULL_TREE;
+
+ for (i = 0; i < addr->n; i++)
+ {
+ if (!double_int_one_p (addr->elts[i].coef))
+ continue;
+
+ val = addr->elts[i].val;
+ if (operand_equal_p (val, base_hint, 0))
+ break;
+ }
+
+ if (i == addr->n)
+ return;
+
+ /* Cast value to appropriate pointer type. */
+ parts->base = fold_convert (build_pointer_type (type), val);
+ aff_combination_remove_elt (addr, i);
+}
+
/* If ADDR contains an address of a dereferenced pointer, move it to
PARTS->base. */
@@ -453,9 +480,11 @@ add_to_parts (struct mem_address *parts, tree elt)
element(s) to PARTS. */
static void
-most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr,
- bool speed)
+most_expensive_mult_to_index (tree type, struct mem_address *parts,
+ aff_tree *addr, bool speed)
{
+ addr_space_t as = TYPE_ADDR_SPACE (type);
+ enum machine_mode address_mode = targetm.addr_space.address_mode (as);
HOST_WIDE_INT coef;
double_int best_mult, amult, amult_neg;
unsigned best_mult_cost = 0, acost;
@@ -469,15 +498,12 @@ most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr,
if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
continue;
- /* FIXME: Should use the correct memory mode rather than Pmode. */
-
coef = double_int_to_shwi (addr->elts[i].coef);
if (coef == 1
- || !multiplier_allowed_in_address_p (coef, Pmode,
- ADDR_SPACE_GENERIC))
+ || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
continue;
- acost = multiply_by_cost (coef, Pmode, speed);
+ acost = multiply_by_cost (coef, address_mode, speed);
if (acost > best_mult_cost)
{
@@ -520,8 +546,10 @@ most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr,
parts->step = double_int_to_tree (sizetype, best_mult);
}
-/* Splits address ADDR into PARTS.
-
+/* Splits address ADDR for a memory access of type TYPE into PARTS.
+ If BASE_HINT is non-NULL, it specifies an SSA name to be used
+ preferentially as base of the reference.
+
TODO -- be more clever about the distribution of the elements of ADDR
to PARTS. Some architectures do not support anything but single
register in address, possibly with a small integer offset; while
@@ -530,7 +558,8 @@ most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr,
addressing modes is useless. */
static void
-addr_to_parts (aff_tree *addr, struct mem_address *parts, bool speed)
+addr_to_parts (tree type, aff_tree *addr, tree base_hint,
+ struct mem_address *parts, bool speed)
{
tree part;
unsigned i;
@@ -550,12 +579,14 @@ addr_to_parts (aff_tree *addr, struct mem_address *parts, bool speed)
/* First move the most expensive feasible multiplication
to index. */
- most_expensive_mult_to_index (parts, addr, speed);
+ most_expensive_mult_to_index (type, parts, addr, speed);
/* Try to find a base of the reference. Since at the moment
there is no reliable way how to distinguish between pointer and its
offset, this is just a guess. */
- if (!parts->symbol)
+ if (!parts->symbol && base_hint)
+ move_hint_to_base (type, parts, base_hint, addr);
+ if (!parts->symbol && !parts->base)
move_pointer_to_base (parts, addr);
/* Then try to process the remaining elements. */
@@ -592,13 +623,13 @@ gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
tree
create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
- bool speed)
+ tree base_hint, bool speed)
{
tree mem_ref, tmp;
tree atype;
struct mem_address parts;
- addr_to_parts (addr, &parts, speed);
+ addr_to_parts (type, addr, base_hint, &parts, speed);
gimplify_mem_ref_parts (gsi, &parts);
mem_ref = create_mem_ref_raw (type, &parts);
if (mem_ref)
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 82e45d2db4d..e89ee0e4ce8 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5510,6 +5510,7 @@ rewrite_use_address (struct ivopts_data *data,
{
aff_tree aff;
gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
+ tree base_hint = NULL_TREE;
tree ref;
bool ok;
@@ -5517,7 +5518,22 @@ rewrite_use_address (struct ivopts_data *data,
gcc_assert (ok);
unshare_aff_combination (&aff);
- ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, data->speed);
+ /* To avoid undefined overflow problems, all IV candidates use unsigned
+ integer types. The drawback is that this makes it impossible for
+ create_mem_ref to distinguish an IV that is based on a memory object
+ from one that represents simply an offset.
+
+ To work around this problem, we pass a hint to create_mem_ref that
+ indicates which variable (if any) in aff is an IV based on a memory
+ object. Note that we only consider the candidate. If this is not
+ based on an object, the base of the reference is in some subexpression
+ of the use -- but these will use pointer types, so they are recognized
+ by the create_mem_ref heuristics anyway. */
+ if (cand->iv->base_object)
+ base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
+
+ ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, base_hint,
+ data->speed);
copy_ref_info (ref, *use->op_p);
*use->op_p = ref;
}