#include "alloc-pool.h"
#include "vec.h"
#include "langhooks.h"
+#include "pointer-set.h"
/* This is a simple global reassociation pass. It is, in part, based
on the LLVM pass of the same name (They do some things more/less
/* Starting rank number for a given basic block, so that we can rank
operations using unmovable instructions in that BB based on the bb
depth. */
-static unsigned int *bb_rank;
+static long *bb_rank;
/* Operand->rank hashtable. */
-static htab_t operand_rank;
+static struct pointer_map_t *operand_rank;
/* Look up the operand rank structure for expression E. */
-static operand_entry_t
+static inline long
find_operand_rank (tree e)
{
- void **slot;
- struct operand_entry vrd;
-
- vrd.op = e;
- slot = htab_find_slot (operand_rank, &vrd, NO_INSERT);
- if (!slot)
- return NULL;
- return ((operand_entry_t) *slot);
+ void **slot = pointer_map_contains (operand_rank, e);
+ return slot ? (long) *slot : -1;
}
/* Insert {E,RANK} into the operand rank hashtable. */
-static void
-insert_operand_rank (tree e, unsigned int rank)
+static inline void
+insert_operand_rank (tree e, long rank)
{
void **slot;
- operand_entry_t new_pair = pool_alloc (operand_entry_pool);
-
- new_pair->op = e;
- new_pair->rank = rank;
- slot = htab_find_slot (operand_rank, new_pair, INSERT);
- gcc_assert (*slot == NULL);
- *slot = new_pair;
-}
-
-/* Return the hash value for a operand rank structure */
-
-static hashval_t
-operand_entry_hash (const void *p)
-{
- const operand_entry_t vr = (operand_entry_t) p;
- return iterative_hash_expr (vr->op, 0);
-}
-
-/* Return true if two operand rank structures are equal. */
-
-static int
-operand_entry_eq (const void *p1, const void *p2)
-{
- const operand_entry_t vr1 = (operand_entry_t) p1;
- const operand_entry_t vr2 = (operand_entry_t) p2;
- return vr1->op == vr2->op;
+ gcc_assert (rank > 0);
+ slot = pointer_map_insert (operand_rank, e);
+ gcc_assert (!*slot);
+ *slot = (void *) rank;
}
/* Given an expression E, return the rank of the expression. */
-static unsigned int
+static long
get_rank (tree e)
{
- operand_entry_t vr;
-
/* Constants have rank 0. */
if (is_gimple_min_invariant (e))
return 0;
{
tree stmt;
tree rhs;
- unsigned int rank, maxrank;
+ long rank, maxrank;
int i;
if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
- && e == default_def (SSA_NAME_VAR (e)))
- return find_operand_rank (e)->rank;
+ && SSA_NAME_IS_DEFAULT_DEF (e))
+ return find_operand_rank (e);
stmt = SSA_NAME_DEF_STMT (e);
if (bb_for_stmt (stmt) == NULL)
return 0;
- if (TREE_CODE (stmt) != MODIFY_EXPR
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT
|| !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
return bb_rank[bb_for_stmt (stmt)->index];
/* If we already have a rank for this expression, use that. */
- vr = find_operand_rank (e);
- if (vr)
- return vr->rank;
+ rank = find_operand_rank (e);
+ if (rank != -1)
+ return rank;
/* Otherwise, find the maximum rank for the operands, or the bb
rank, whichever is less. */
rank = 0;
maxrank = bb_rank[bb_for_stmt(stmt)->index];
- rhs = TREE_OPERAND (stmt, 1);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE_LENGTH (TREE_CODE (rhs)) == 0)
rank = MAX (rank, get_rank (rhs));
else
{
fprintf (dump_file, "Rank for ");
print_generic_expr (dump_file, e, 0);
- fprintf (dump_file, " is %d\n", (rank + 1));
+ fprintf (dump_file, " is %ld\n", (rank + 1));
}
/* Note the rank in the hashtable so we don't recompute it. */
is_reassociable_op (tree stmt, enum tree_code code)
{
if (!IS_EMPTY_STMT (stmt)
- && TREE_CODE (stmt) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (stmt, 1)) == code
- && has_single_use (TREE_OPERAND (stmt, 0)))
+ && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == code
+ && has_single_use (GIMPLE_STMT_OPERAND (stmt, 0)))
return true;
return false;
}
tree stmt = SSA_NAME_DEF_STMT (name);
tree rhs;
- if (TREE_CODE (stmt) != MODIFY_EXPR)
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return NULL_TREE;
- rhs = TREE_OPERAND (stmt, 1);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == opcode)
return TREE_OPERAND (rhs, 0);
return NULL_TREE;
operand_entry_t last)
{
- /* If we have two of the same op, and the opcode is & or |, we can
- eliminate one of them.
+ /* If we have two of the same op, and the opcode is & |, min, or max,
+ we can eliminate one of them.
If we have two of the same op, and the opcode is ^, we can
eliminate both of them. */
{
switch (opcode)
{
+ case MAX_EXPR:
+ case MIN_EXPR:
case BIT_IOR_EXPR:
case BIT_AND_EXPR:
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Equivalence: ");
print_generic_expr (dump_file, curr->op, 0);
- fprintf (dump_file, " [&|] ");
+ fprintf (dump_file, " [&|minmax] ");
print_generic_expr (dump_file, last->op, 0);
fprintf (dump_file, " -> ");
print_generic_stmt (dump_file, last->op, 0);
is_phi_for_stmt (tree stmt, tree operand)
{
tree def_stmt;
- tree lhs = TREE_OPERAND (stmt, 0);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
use_operand_p arg_p;
ssa_op_iter i;
rewrite_expr_tree (tree stmt, unsigned int opindex,
VEC(operand_entry_t, heap) * ops)
{
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
operand_entry_t oe;
/* If we have three operands left, then we want to make sure the one
linearize_expr (tree stmt)
{
block_stmt_iterator bsinow, bsirhs;
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
enum tree_code rhscode = TREE_CODE (rhs);
tree binrhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
tree binlhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
bsirhs = bsi_for_stmt (binrhs);
bsi_move_before (&bsirhs, &bsinow);
- TREE_OPERAND (rhs, 1) = TREE_OPERAND (TREE_OPERAND (binrhs, 1), 0);
+ TREE_OPERAND (rhs, 1) = TREE_OPERAND (GIMPLE_STMT_OPERAND (binrhs, 1), 0);
if (TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME)
newbinrhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
- TREE_OPERAND (TREE_OPERAND (binrhs, 1), 0) = TREE_OPERAND (binlhs, 0);
- TREE_OPERAND (rhs, 0) = TREE_OPERAND (binrhs, 0);
+ TREE_OPERAND (GIMPLE_STMT_OPERAND (binrhs, 1), 0)
+ = GIMPLE_STMT_OPERAND (binlhs, 0);
+ TREE_OPERAND (rhs, 0) = GIMPLE_STMT_OPERAND (binrhs, 0);
if (dump_file && (dump_flags & TDF_DETAILS))
{
}
-/* If LHS has a single immediate use that is a MODIFY_EXPR, return
+/* If LHS has a single immediate use that is a GIMPLE_MODIFY_STMT, return
it. Otherwise, return NULL. */
static tree
{
if (TREE_CODE (immusestmt) == RETURN_EXPR)
immusestmt = TREE_OPERAND (immusestmt, 0);
- if (TREE_CODE (immusestmt) == MODIFY_EXPR)
+ if (TREE_CODE (immusestmt) == GIMPLE_MODIFY_STMT)
return immusestmt;
}
return NULL_TREE;
/* If we are trying to negate a name, defined by an add, negate the
add operands instead. */
if (TREE_CODE (tonegate) == SSA_NAME
- && TREE_CODE (negatedef) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (negatedef, 0)) == SSA_NAME
- && num_imm_uses (TREE_OPERAND (negatedef, 0)) == 1
- && TREE_CODE (TREE_OPERAND (negatedef, 1)) == PLUS_EXPR)
+ && TREE_CODE (negatedef) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (negatedef, 0)) == SSA_NAME
+ && has_single_use (GIMPLE_STMT_OPERAND (negatedef, 0))
+ && TREE_CODE (GIMPLE_STMT_OPERAND (negatedef, 1)) == PLUS_EXPR)
{
block_stmt_iterator bsi;
- tree binop = TREE_OPERAND (negatedef, 1);
+ tree binop = GIMPLE_STMT_OPERAND (negatedef, 1);
bsi = bsi_for_stmt (negatedef);
TREE_OPERAND (binop, 0) = negate_value (TREE_OPERAND (binop, 0),
TREE_OPERAND (binop, 1) = negate_value (TREE_OPERAND (binop, 1),
&bsi);
update_stmt (negatedef);
- return TREE_OPERAND (negatedef, 0);
+ return GIMPLE_STMT_OPERAND (negatedef, 0);
}
tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
should_break_up_subtract (tree stmt)
{
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
tree binlhs = TREE_OPERAND (rhs, 0);
tree binrhs = TREE_OPERAND (rhs, 1);
tree immusestmt;
if (TREE_CODE (lhs) == SSA_NAME
&& (immusestmt = get_single_immediate_use (lhs))
- && TREE_CODE (TREE_OPERAND (immusestmt, 1)) == PLUS_EXPR)
+ && TREE_CODE (GIMPLE_STMT_OPERAND (immusestmt, 1)) == PLUS_EXPR)
return true;
return false;
static void
break_up_subtract (tree stmt, block_stmt_iterator *bsi)
{
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
print_generic_stmt (dump_file, stmt, 0);
}
- TREE_SET_CODE (TREE_OPERAND (stmt, 1), PLUS_EXPR);
+ TREE_SET_CODE (GIMPLE_STMT_OPERAND (stmt, 1), PLUS_EXPR);
TREE_OPERAND (rhs, 1) = negate_value (TREE_OPERAND (rhs, 1), bsi);
update_stmt (stmt);
linearize_expr_tree (VEC(operand_entry_t, heap) **ops, tree stmt)
{
block_stmt_iterator bsinow, bsilhs;
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree rhs = GENERIC_TREE_OPERAND (stmt, 1);
tree binrhs = TREE_OPERAND (rhs, 1);
tree binlhs = TREE_OPERAND (rhs, 0);
tree binlhsdef, binrhsdef;
else if (binrhsisreassoc)
{
linearize_expr (stmt);
- gcc_assert (rhs == TREE_OPERAND (stmt, 1));
+ gcc_assert (rhs == GIMPLE_STMT_OPERAND (stmt, 1));
binlhs = TREE_OPERAND (rhs, 0);
binrhs = TREE_OPERAND (rhs, 1);
}
Force the negate operand to the RHS of the PLUS_EXPR, then
transform the PLUS_EXPR into a MINUS_EXPR. */
if (user
- && TREE_CODE (user) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (user, 1)) == PLUS_EXPR)
+ && TREE_CODE (user) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (user, 1)) == PLUS_EXPR)
{
- tree rhs = TREE_OPERAND (user, 1);
+ tree rhs = GIMPLE_STMT_OPERAND (user, 1);
/* If the negated operand appears on the LHS of the
PLUS_EXPR, exchange the operands of the PLUS_EXPR
to force the negated operand to the RHS of the PLUS_EXPR. */
- if (TREE_OPERAND (TREE_OPERAND (user, 1), 0) == negate)
+ if (TREE_OPERAND (GIMPLE_STMT_OPERAND (user, 1), 0) == negate)
{
tree temp = TREE_OPERAND (rhs, 0);
TREE_OPERAND (rhs, 0) = TREE_OPERAND (rhs, 1);
/* Now transform the PLUS_EXPR into a MINUS_EXPR and replace
the RHS of the PLUS_EXPR with the operand of the NEGATE_EXPR. */
- if (TREE_OPERAND (TREE_OPERAND (user, 1), 1) == negate)
+ if (TREE_OPERAND (GIMPLE_STMT_OPERAND (user, 1), 1) == negate)
{
TREE_SET_CODE (rhs, MINUS_EXPR);
TREE_OPERAND (rhs, 1) = get_unary_op (negate, NEGATE_EXPR);
{
tree stmt = bsi_stmt (bsi);
- if (TREE_CODE (stmt) == MODIFY_EXPR)
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
{
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
TREE_VISITED (stmt) = 0;
/* If unsafe math optimizations we can do reassociation for
{
tree stmt = bsi_stmt (bsi);
- if (TREE_CODE (stmt) == MODIFY_EXPR)
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
{
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
/* If this was part of an already processed tree, we don't
need to touch it again. */
/* There may be no immediate uses left by the time we
get here because we may have eliminated them all. */
- if (TREE_CODE (lhs) == SSA_NAME && num_imm_uses (lhs) == 0)
+ if (TREE_CODE (lhs) == SSA_NAME && has_zero_uses (lhs))
continue;
TREE_VISITED (stmt) = 1;
fprintf (dump_file, "Transforming ");
print_generic_expr (dump_file, rhs, 0);
}
- TREE_OPERAND (stmt, 1) = VEC_last (operand_entry_t, ops)->op;
+ GIMPLE_STMT_OPERAND (stmt, 1)
+ = VEC_last (operand_entry_t, ops)->op;
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " into ");
print_generic_stmt (dump_file,
- TREE_OPERAND (stmt, 1), 0);
+ GIMPLE_STMT_OPERAND (stmt, 1), 0);
}
}
else
init_reassoc (void)
{
int i;
- unsigned int rank = 2;
+ long rank = 2;
tree param;
- int *bbs = xmalloc ((last_basic_block + 1) * sizeof (int));
+ int *bbs = XNEWVEC (int, last_basic_block + 1);
memset (&reassociate_stats, 0, sizeof (reassociate_stats));
/* Reverse RPO (Reverse Post Order) will give us something where
deeper loops come later. */
pre_and_rev_post_order_compute (NULL, bbs, false);
- bb_rank = xcalloc (last_basic_block + 1, sizeof (unsigned int));
-
- operand_rank = htab_create (511, operand_entry_hash,
- operand_entry_eq, 0);
+ bb_rank = XCNEWVEC (long, last_basic_block + 1);
+ operand_rank = pointer_map_create ();
/* Give each argument a distinct rank. */
for (param = DECL_ARGUMENTS (current_function_decl);
param;
param = TREE_CHAIN (param))
{
- if (default_def (param) != NULL)
+ if (gimple_default_def (cfun, param) != NULL)
{
- tree def = default_def (param);
+ tree def = gimple_default_def (cfun, param);
insert_operand_rank (def, ++rank);
}
}
/* Give the chain decl a distinct rank. */
if (cfun->static_chain_decl != NULL)
{
- tree def = default_def (cfun->static_chain_decl);
+ tree def = gimple_default_def (cfun, cfun->static_chain_decl);
if (def != NULL)
insert_operand_rank (def, ++rank);
}
fprintf (dump_file, "Statements rewritten: %d\n",
reassociate_stats.rewritten);
}
- htab_delete (operand_rank);
+ pointer_map_destroy (operand_rank);
free_alloc_pool (operand_entry_pool);
free (bb_rank);
VEC_free (tree, heap, broken_up_subtracts);
/* Gate and execute functions for Reassociation. */
-static void
+static unsigned int
execute_reassoc (void)
{
init_reassoc ();
repropagate_negates ();
fini_reassoc ();
+ return 0;
}
struct tree_opt_pass pass_reassoc =