From: Ulrich Weigand Date: Mon, 2 Nov 2009 14:30:39 +0000 (+0000) Subject: re PR tree-optimization/41857 (Loop optimizer breaks __ea pointers with -mea64) X-Git-Tag: releases/gcc-4.5.0~2558 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d7c0c068dd5d174f5183c2187499332198aea683;p=thirdparty%2Fgcc.git re PR tree-optimization/41857 (Loop optimizer breaks __ea pointers with -mea64) 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. From-SVN: r153810 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index df8f0ed9082d..3b64aed951c8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-11-02 Ulrich Weigand + + 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 PR tree-optimization/41750 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4fe2079320bc..2d1378aa7a9d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-11-02 Ulrich Weigand + + PR tree-optimization/41857 + * gcc.target/spu/ea/pr41857.c: New file. + 2009-11-02 Martin Jambor 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 000000000000..17710674cf6d --- /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 + . */ + +/* { 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 a70156918118..40fad2dd5562 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 1428803272f3..37bce5e2d2e5 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 82e45d2db4d3..e89ee0e4ce82 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; }