Commit 73f30c63 by Zdenek Dvorak Committed by Zdenek Dvorak

tree-ssa-loop-ivopts.c: Include tree-affine.h.

	* 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.

From-SVN: r119854
parent 904e0e97
2006-12-13 Zdenek Dvorak <dvorakz@suse.cz>
* 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.
2006-12-13 Peter Bergner <bergner@vnet.ibm.com>
PR middle-end/30191
......
......@@ -988,7 +988,7 @@ OBJS-common = \
tree-vectorizer.o tree-vect-analyze.o tree-vect-transform.o \
tree-vect-patterns.o tree-ssa-loop-prefetch.o tree-ssa-coalesce.o \
tree-ssa-loop-ivcanon.o tree-ssa-propagate.o tree-ssa-address.o \
tree-ssa-math-opts.o \
tree-ssa-math-opts.o tree-affine.o \
tree-ssa-loop-ivopts.o tree-if-conv.o tree-ssa-loop-unswitch.o \
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
......@@ -1992,7 +1992,7 @@ tree-ssa-address.o : tree-ssa-address.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h $(EXPR_H) \
gt-tree-ssa-address.h $(GGC_H)
gt-tree-ssa-address.h $(GGC_H) tree-affine.h
tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
$(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
......@@ -2018,7 +2018,10 @@ tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \
output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
$(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
tree-chrec.h $(VARRAY_H)
tree-chrec.h $(VARRAY_H) tree-affine.h
tree-affine.o : tree-affine.c tree-affine.h $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H)
tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
......
/* Operations with affine combinations of trees.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GCC.
GCC 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 2, or (at your option) any
later version.
GCC 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 GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
/* Affine combination of trees. We keep track of at most MAX_AFF_ELTS elements
to make things simpler; this is sufficient in most cases. */
#define MAX_AFF_ELTS 8
/* Element of an affine combination. */
struct aff_comb_elt
{
/* The value of the element. */
tree val;
/* Its coefficient in the combination. */
double_int coef;
};
typedef struct affine_tree_combination
{
/* Type of the result of the combination. */
tree type;
/* Constant offset. */
double_int offset;
/* Number of elements of the combination. */
unsigned n;
/* Elements and their coefficients. Type of elements may be different from
TYPE, but their sizes must be the same (STRIP_NOPS is applied to the
elements).
The coefficients are always sign extened from the precision of TYPE
(regardless of signedness of TYPE). */
struct aff_comb_elt elts[MAX_AFF_ELTS];
/* Remainder of the expression. Usually NULL, used only if there are more
than MAX_AFF_ELTS elements. Type of REST must be TYPE. */
tree rest;
} aff_tree;
double_int double_int_ext_for_comb (double_int, aff_tree *);
void aff_combination_const (aff_tree *, tree, double_int);
void aff_combination_elt (aff_tree *, tree, tree);
void aff_combination_scale (aff_tree *, double_int);
void aff_combination_add (aff_tree *, aff_tree *);
void aff_combination_add_elt (aff_tree *, tree, double_int);
void aff_combination_remove_elt (aff_tree *, unsigned);
void aff_combination_convert (aff_tree *, tree);
void tree_to_aff_combination (tree, tree, aff_tree *);
tree aff_combination_to_tree (aff_tree *);
void unshare_aff_combination (aff_tree *);
......@@ -1002,33 +1002,6 @@ extern void remove_unused_locals (void);
/* In tree-ssa-address.c */
/* Affine combination of trees. We keep track of at most MAX_AFF_ELTS elements
to make things simpler; this is sufficient in most cases. */
#define MAX_AFF_ELTS 8
struct affine_tree_combination
{
/* Type of the result of the combination. */
tree type;
/* Mask modulo that the operations are performed. */
unsigned HOST_WIDE_INT mask;
/* Constant offset. */
unsigned HOST_WIDE_INT offset;
/* Number of elements of the combination. */
unsigned n;
/* Elements and their coefficients. */
tree elts[MAX_AFF_ELTS];
unsigned HOST_WIDE_INT coefs[MAX_AFF_ELTS];
/* Remainder of the expression. */
tree rest;
};
/* Description of a memory address. */
struct mem_address
......@@ -1036,6 +1009,7 @@ struct mem_address
tree symbol, base, index, step, offset;
};
struct affine_tree_combination;
tree create_mem_ref (block_stmt_iterator *, tree,
struct affine_tree_combination *);
rtx addr_for_mem_ref (struct mem_address *, bool);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment