/* Predictive commoning.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007 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
+Free Software Foundation; either version 3, or (at your option) any
later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
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. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file implements the predictive commoning optimization. Predictive
commoning can be viewed as CSE around a loop, and with some improvements,
double_int *off)
{
aff_tree diff, baseb, step;
+ tree typea, typeb;
+
+ /* Check that both the references access the location in the same type. */
+ typea = TREE_TYPE (DR_REF (a));
+ typeb = TREE_TYPE (DR_REF (b));
+ if (!useless_type_conversion_p (typeb, typea))
+ return false;
/* Check whether the base address and the step of both references is the
same. */
just fail. */
goto end;
}
- dr->aux = i;
+ dr->aux = (void *) (size_t) i;
comp_father[i] = i;
comp_size[i] = 1;
}
if (!suitable_reference_p (dr, &dummy))
{
- ia = dr->aux;
+ ia = (unsigned) (size_t) dr->aux;
merge_comps (comp_father, comp_size, n, ia);
}
}
dra = DDR_A (ddr);
drb = DDR_B (ddr);
- ia = component_of (comp_father, dra->aux);
- ib = component_of (comp_father, drb->aux);
+ ia = component_of (comp_father, (unsigned) (size_t) dra->aux);
+ ib = component_of (comp_father, (unsigned) (size_t) drb->aux);
if (ia == ib)
continue;
bad = component_of (comp_father, n);
for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
{
- ia = dr->aux;
+ ia = (unsigned) (size_t) dr->aux;
ca = component_of (comp_father, ia);
if (ca == bad)
continue;
}
/* Returns true if the component COMP satisfies the conditions
- described in 2) at the begining of this file. LOOP is the current
+ described in 2) at the beginning of this file. LOOP is the current
loop. */
static bool
/* Check the conditions on references inside each of components COMPS,
and remove the unsuitable components from the list. The new list
of components is returned. The conditions are described in 2) at
- the begining of this file. LOOP is the current loop. */
+ the beginning of this file. LOOP is the current loop. */
static struct component *
filter_suitable_components (struct loop *loop, struct component *comps)
remove_phi_node (stmt, NULL_TREE, false);
/* Turn the phi node into GIMPLE_MODIFY_STMT. */
- new_stmt = build_gimple_modify_stmt_stat (val, new);
+ new_stmt = build_gimple_modify_stmt (val, new);
SSA_NAME_DEF_STMT (val) = new_stmt;
bsi_insert_before (&bsi, new_stmt, BSI_NEW_STMT);
return;
NEW = VAL */
}
- new_stmt = build_gimple_modify_stmt_stat (new, unshare_expr (val));
+ new_stmt = build_gimple_modify_stmt (new, unshare_expr (val));
bsi_insert_after (&bsi, new_stmt, BSI_NEW_STMT);
SSA_NAME_DEF_STMT (new) = new_stmt;
}
else
{
type = TREE_TYPE (iv.base);
- val = fold_build2 (MULT_EXPR, type, iv.step,
- build_int_cst_type (type, iter));
- val = fold_build2 (PLUS_EXPR, type, iv.base, val);
+ if (POINTER_TYPE_P (type))
+ {
+ val = fold_build2 (MULT_EXPR, sizetype, iv.step,
+ size_int (iter));
+ val = fold_build2 (POINTER_PLUS_EXPR, type, iv.base, val);
+ }
+ else
+ {
+ val = fold_build2 (MULT_EXPR, type, iv.step,
+ build_int_cst_type (type, iter));
+ val = fold_build2 (PLUS_EXPR, type, iv.base, val);
+ }
*idx_p = unshare_expr (val);
}
/* Marks all virtual operands of statement STMT for renaming. */
-static void
+void
mark_virtual_ops_for_renaming (tree stmt)
{
ssa_op_iter iter;
tree var;
if (TREE_CODE (stmt) == PHI_NODE)
- return;
+ {
+ var = PHI_RESULT (stmt);
+ if (is_gimple_reg (var))
+ return;
+
+ if (TREE_CODE (var) == SSA_NAME)
+ var = SSA_NAME_VAR (var);
+ mark_sym_for_renaming (var);
+ return;
+ }
update_stmt (stmt);
mark_virtual_ops_for_renaming (tsi_stmt (tsi));
}
+/* Returns a new temporary variable used for the I-th variable carrying
+ value of REF. The variable's uid is marked in TMP_VARS. */
+
+static tree
+predcom_tmp_var (tree ref, unsigned i, bitmap tmp_vars)
+{
+ tree type = TREE_TYPE (ref);
+ tree var = create_tmp_var (type, get_lsm_tmp_name (ref, i));
+
+ /* We never access the components of the temporary variable in predictive
+ commoning. */
+ if (TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)
+ DECL_GIMPLE_REG_P (var) = 1;
+
+ add_referenced_var (var);
+ bitmap_set_bit (tmp_vars, DECL_UID (var));
+ return var;
+}
+
/* Creates the variables for CHAIN, as well as phi nodes for them and
initialization on entry to LOOP. Uids of the newly created
temporary variables are marked in TMP_VARS. */
for (i = 0; i < n + (reuse_first ? 0 : 1); i++)
{
- var = create_tmp_var (TREE_TYPE (ref), get_lsm_tmp_name (ref, i));
- add_referenced_var (var);
- bitmap_set_bit (tmp_vars, DECL_UID (var));
+ var = predcom_tmp_var (ref, i, tmp_vars);
VEC_quick_push (tree, chain->vars, var);
}
if (reuse_first)
init = VEC_index (tree, inits, 0);
*vars = VEC_alloc (tree, heap, written ? 2 : 1);
- var = create_tmp_var (TREE_TYPE (ref), get_lsm_tmp_name (ref, 0));
- add_referenced_var (var);
- bitmap_set_bit (tmp_vars, DECL_UID (var));
+ var = predcom_tmp_var (ref, 0, tmp_vars);
VEC_quick_push (tree, *vars, var);
if (written)
VEC_quick_push (tree, *vars, VEC_index (tree, *vars, 0));
}
else
{
- init = build_gimple_modify_stmt_stat (var, init);
+ init = build_gimple_modify_stmt (var, init);
SSA_NAME_DEF_STMT (var) = init;
mark_virtual_ops_for_renaming (init);
bsi_insert_on_edge_immediate (entry, init);
update_ssa (TODO_update_ssa_only_virtuals);
}
-/* For each reference in CHAINS, if its definining statement is
+/* For each reference in CHAINS, if its defining statement is
ssa name, set it to phi node that defines it. */
static void
}
}
-/* For each reference in CHAINS, if its definining statement is
+/* For each reference in CHAINS, if its defining statement is
phi node, set it to the ssa name that is defined by it. */
static void
/* Base all the ssa names in the ud and du chain of NAME on VAR. */
stmt = SSA_NAME_DEF_STMT (use);
- while (TREE_CODE (stmt) == PHI_NODE)
+ while (TREE_CODE (stmt) == PHI_NODE
+ /* In case we could not unroll the loop enough to eliminate
+ all copies, we may reach the loop header before the defining
+ statement (in that case, some register copies will be present
+ in loop latch in the final code, corresponding to the newly
+ created looparound phi nodes). */
+ && bb_for_stmt (stmt) != loop->header)
{
gcc_assert (single_pred_p (bb_for_stmt (stmt)));
use = PHI_ARG_DEF (stmt, 0);
/* Returns the common statement in that NAME1 and NAME2 have a use. If there
is no such statement, returns NULL_TREE. In case the operation used on
- NAME1 and NAME2 is associative and comutative, returns the root of the
+ NAME1 and NAME2 is associative and commutative, returns the root of the
tree formed by this operation instead of the statement that uses NAME1 or
NAME2. */
var = create_tmp_var (type, "predreastmp");
add_referenced_var (var);
new_name = make_ssa_name (var, NULL_TREE);
- new_stmt = build_gimple_modify_stmt_stat (new_name,
+ new_stmt = build_gimple_modify_stmt (new_name,
fold_build2 (code, type, name1, name2));
SSA_NAME_DEF_STMT (new_name) = new_stmt;
var = create_tmp_var (type, "predreastmp");
add_referenced_var (var);
tmp_name = make_ssa_name (var, NULL_TREE);
- tmp_stmt = build_gimple_modify_stmt_stat (tmp_name,
+ tmp_stmt = build_gimple_modify_stmt (tmp_name,
GIMPLE_STMT_OPERAND (s1, 1));
SSA_NAME_DEF_STMT (tmp_name) = tmp_stmt;
/* Runs predictive commoning. */
-void
+unsigned
tree_predictive_commoning (void)
{
bool unrolled = false;
struct loop *loop;
loop_iterator li;
+ unsigned ret = 0;
initialize_original_copy_tables ();
FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
if (unrolled)
{
scev_reset ();
- cleanup_tree_cfg_loop ();
+ ret = TODO_cleanup_cfg;
}
free_original_copy_tables ();
+
+ return ret;
}