summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-address.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-14 02:05:20 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-14 02:05:20 +0000
commitd3610beab162bbb9b18ffd643cd412dac23b6da3 (patch)
tree33e4fecfec131da30950f9a5e548ab0f2c428746 /gcc/tree-ssa-address.c
parent4cbb97104ed0bc23c27f67354fa426a8b118fec3 (diff)
downloadgcc-d3610beab162bbb9b18ffd643cd412dac23b6da3.tar.gz
* tree-ssa-loop-ivopts.c: Include tree-affine.h.
(divide): Removed. (constant_multiple_of): Fix order of operators for division. (aff_combination_const, aff_combination_elt, aff_combination_scale, aff_combination_add_elt, aff_combination_add, aff_combination_convert, tree_to_aff_combination, add_elt_to_tree, unshare_aff_combination, aff_combination_to_tree): Moved to tree-affine.c and made to work with double_int coefficients. (get_computation_aff, get_computation_at): Work with double_int coefficients. (get_computation_cost_at): Do not use divide. (rewrite_use_nonlinear_expr, rewrite_use_address, rewrite_use_compare): Assert that expressing the computation did not fail. * tree-ssa-address.c: Include tree-affine.h. (add_to_parts, most_expensive_mult_to_index, addr_to_parts, create_mem_ref): Work with double_int coefficients. * tree-affine.c: New file. * tree-affine.h: New file. * tree-flow.h (struct affine_tree_combination): Removed. * Makefile.in (tree-affine.o): Add. (tree-ssa-address.o, tree-ssa-loop-ivopts.o): Add tree-affine.h dependency. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119854 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-address.c')
-rw-r--r--gcc/tree-ssa-address.c94
1 files changed, 56 insertions, 38 deletions
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index c3394498964..eb39370f0d8 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -42,6 +42,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "recog.h"
#include "expr.h"
#include "ggc.h"
+#include "tree-affine.h"
/* TODO -- handling of symbols (according to Richard Hendersons
comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
@@ -346,25 +347,20 @@ fixed_address_object_p (tree obj)
construct. */
static void
-add_to_parts (struct mem_address *parts, tree type, tree elt,
- unsigned HOST_WIDE_INT coef)
+add_to_parts (struct mem_address *parts, tree type, tree elt)
{
+ tree elt_core = elt;
+ STRIP_NOPS (elt_core);
+
/* Check if this is a symbol. */
if (!parts->symbol
- && coef == 1
- && TREE_CODE (elt) == ADDR_EXPR
- && fixed_address_object_p (TREE_OPERAND (elt, 0)))
+ && TREE_CODE (elt_core) == ADDR_EXPR
+ && fixed_address_object_p (TREE_OPERAND (elt_core, 0)))
{
- parts->symbol = TREE_OPERAND (elt, 0);
+ parts->symbol = TREE_OPERAND (elt_core, 0);
return;
}
- if (coef != 1)
- elt = fold_build2 (MULT_EXPR, type, fold_convert (type, elt),
- build_int_cst_type (type, coef));
- else
- elt = fold_convert (type, elt);
-
if (!parts->base)
{
parts->base = elt;
@@ -388,52 +384,69 @@ add_to_parts (struct mem_address *parts, tree type, tree elt,
static void
most_expensive_mult_to_index (struct mem_address *parts, tree type,
- struct affine_tree_combination *addr)
+ aff_tree *addr)
{
- unsigned HOST_WIDE_INT best_mult = 0;
+ HOST_WIDE_INT coef;
+ double_int best_mult, amult, amult_neg;
unsigned best_mult_cost = 0, acost;
tree mult_elt = NULL_TREE, elt;
unsigned i, j;
+ enum tree_code op_code;
+ best_mult = double_int_zero;
for (i = 0; i < addr->n; i++)
{
+ if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
+ continue;
+
/* FIXME: Should use the correct memory mode rather than Pmode. */
- if (addr->coefs[i] == 1
- || !multiplier_allowed_in_address_p (addr->coefs[i], Pmode))
+
+ coef = double_int_to_shwi (addr->elts[i].coef);
+ if (coef == 1
+ || !multiplier_allowed_in_address_p (coef, Pmode))
continue;
-
- acost = multiply_by_cost (addr->coefs[i], Pmode);
+
+ acost = multiply_by_cost (coef, Pmode);
if (acost > best_mult_cost)
{
best_mult_cost = acost;
- best_mult = addr->coefs[i];
+ best_mult = addr->elts[i].coef;
}
}
- if (!best_mult)
+ if (!best_mult_cost)
return;
+ /* Collect elements multiplied by best_mult. */
for (i = j = 0; i < addr->n; i++)
{
- if (addr->coefs[i] != best_mult)
+ amult = addr->elts[i].coef;
+ amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
+
+ if (double_int_equal_p (amult, best_mult))
+ op_code = PLUS_EXPR;
+ else if (double_int_equal_p (amult_neg, best_mult))
+ op_code = MINUS_EXPR;
+ else
{
- addr->coefs[j] = addr->coefs[i];
addr->elts[j] = addr->elts[i];
j++;
continue;
}
-
- elt = fold_convert (type, addr->elts[i]);
- if (!mult_elt)
+
+ elt = fold_convert (type, addr->elts[i].val);
+ if (mult_elt)
+ mult_elt = fold_build2 (op_code, type, mult_elt, elt);
+ else if (op_code == PLUS_EXPR)
mult_elt = elt;
else
- mult_elt = fold_build2 (PLUS_EXPR, type, mult_elt, elt);
+ mult_elt = fold_build1 (NEGATE_EXPR, type, elt);
}
addr->n = j;
-
+
parts->index = mult_elt;
- parts->step = build_int_cst_type (type, best_mult);
+ parts->step = double_int_to_tree (type, best_mult);
}
/* Splits address ADDR into PARTS.
@@ -442,13 +455,13 @@ most_expensive_mult_to_index (struct mem_address *parts, tree type,
to PARTS. Some architectures do not support anything but single
register in address, possibly with a small integer offset; while
create_mem_ref will simplify the address to an acceptable shape
- later, it would be a small bit more efficient to know that asking
- for complicated addressing modes is useless. */
+ later, it would be more efficient to know that asking for complicated
+ addressing modes is useless. */
static void
-addr_to_parts (struct affine_tree_combination *addr, tree type,
- struct mem_address *parts)
+addr_to_parts (aff_tree *addr, tree type, struct mem_address *parts)
{
+ tree part;
unsigned i;
parts->symbol = NULL_TREE;
@@ -456,8 +469,8 @@ addr_to_parts (struct affine_tree_combination *addr, tree type,
parts->index = NULL_TREE;
parts->step = NULL_TREE;
- if (addr->offset)
- parts->offset = build_int_cst_type (type, addr->offset);
+ if (!double_int_zero_p (addr->offset))
+ parts->offset = double_int_to_tree (type, addr->offset);
else
parts->offset = NULL_TREE;
@@ -467,9 +480,15 @@ addr_to_parts (struct affine_tree_combination *addr, tree type,
/* Then try to process the remaining elements. */
for (i = 0; i < addr->n; i++)
- add_to_parts (parts, type, addr->elts[i], addr->coefs[i]);
+ {
+ part = fold_convert (type, addr->elts[i].val);
+ if (!double_int_one_p (addr->elts[i].coef))
+ part = fold_build2 (MULT_EXPR, type, part,
+ double_int_to_tree (type, addr->elts[i].coef));
+ add_to_parts (parts, type, part);
+ }
if (addr->rest)
- add_to_parts (parts, type, addr->rest, 1);
+ add_to_parts (parts, type, addr->rest);
}
/* Force the PARTS to register. */
@@ -490,8 +509,7 @@ gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
of created memory reference. */
tree
-create_mem_ref (block_stmt_iterator *bsi, tree type,
- struct affine_tree_combination *addr)
+create_mem_ref (block_stmt_iterator *bsi, tree type, aff_tree *addr)
{
tree mem_ref, tmp;
tree addr_type = build_pointer_type (type);