#include "tm.h"
#include "tree.h"
#include "basic-block.h"
-#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
#include "tree-inline.h"
{
VEC_free (operand_entry_t, heap, *ops);
*ops = NULL;
- add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
- integer_zero_node));
+ add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (last->op)));
*all_done = true;
}
else
}
VEC_ordered_remove (operand_entry_t, *ops, i);
- add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
- integer_zero_node));
+ add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (oe->op)));
VEC_ordered_remove (operand_entry_t, *ops, currindex);
reassociate_stats.ops_eliminated ++;
}
if (opcode == BIT_AND_EXPR)
- oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
+ oe->op = build_zero_cst (TREE_TYPE (oe->op));
else if (opcode == BIT_IOR_EXPR)
oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
TYPE_PRECISION (TREE_TYPE (oe->op)));
candidates = sbitmap_alloc (length);
sbitmap_zero (candidates);
nr_candidates = 0;
- for (i = 0; VEC_iterate (operand_entry_t, *ops, i, oe1); ++i)
+ FOR_EACH_VEC_ELT (operand_entry_t, *ops, i, oe1)
{
enum tree_code dcode;
gimple oe1def;
linearize_expr_tree (&subops[i], oedef,
associative_tree_code (oecode), false);
- for (j = 0; VEC_iterate (operand_entry_t, subops[i], j, oe1); ++j)
+ FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
{
oecount c;
void **slot;
htab_delete (ctable);
/* Sort the counting table. */
- qsort (VEC_address (oecount, cvec), VEC_length (oecount, cvec),
- sizeof (oecount), oecount_cmp);
+ VEC_qsort (oecount, cvec, oecount_cmp);
if (dump_file && (dump_flags & TDF_DETAILS))
{
oecount *c;
fprintf (dump_file, "Candidates:\n");
- for (j = 0; VEC_iterate (oecount, cvec, j, c); ++j)
+ FOR_EACH_VEC_ELT (oecount, cvec, j, c)
{
fprintf (dump_file, " %u %s: ", c->cnt,
c->oecode == MULT_EXPR
if (oecode != c->oecode)
continue;
- for (j = 0; VEC_iterate (operand_entry_t, subops[i], j, oe1); ++j)
+ FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
{
if (oe1->op == c->op)
{
}
zero_one_operation (&oe2->op, c->oecode, c->op);
sum = build_and_add_sum (tmpvar, oe1->op, oe2->op, opcode);
- oe2->op = fold_convert (TREE_TYPE (oe2->op), integer_zero_node);
+ oe2->op = build_zero_cst (TREE_TYPE (oe2->op));
oe2->rank = 0;
oe1->op = gimple_get_lhs (sum);
}
rcode = gimple_assign_rhs_code (def2);
if (TREE_CODE_CLASS (rcode) != tcc_comparison)
continue;
- if (operand_equal_p (op1, gimple_assign_rhs1 (def2), 0)
- && operand_equal_p (op2, gimple_assign_rhs2 (def2), 0))
- ;
- else if (operand_equal_p (op1, gimple_assign_rhs2 (def2), 0)
- && operand_equal_p (op2, gimple_assign_rhs1 (def2), 0))
- rcode = swap_tree_comparison (rcode);
- else
- continue;
/* If we got here, we have a match. See if we can combine the
two comparisons. */
- t = combine_comparisons (UNKNOWN_LOCATION,
- (opcode == BIT_IOR_EXPR
- ? TRUTH_OR_EXPR : TRUTH_AND_EXPR),
- lcode, rcode, TREE_TYPE (curr->op), op1, op2);
+ if (opcode == BIT_IOR_EXPR)
+ t = maybe_fold_or_comparisons (lcode, op1, op2,
+ rcode, gimple_assign_rhs1 (def2),
+ gimple_assign_rhs2 (def2));
+ else
+ t = maybe_fold_and_comparisons (lcode, op1, op2,
+ rcode, gimple_assign_rhs1 (def2),
+ gimple_assign_rhs2 (def2));
if (!t)
continue;
+
+ /* maybe_fold_and_comparisons and maybe_fold_or_comparisons
+ always give us a boolean_type_node value back. If the original
+ BIT_AND_EXPR or BIT_IOR_EXPR was of a wider integer type,
+ we need to convert. */
+ if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
+ t = fold_convert (TREE_TYPE (curr->op), t);
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Equivalence: ");
VEC_ordered_remove (operand_entry_t, *ops, currindex);
add_to_ops_vec (ops, t);
}
- else if (TREE_CODE (t) != lcode)
+ else if (!operand_equal_p (t, curr->op, 0))
{
tree tmpvar;
gimple sum;
enum tree_code subcode;
tree newop1;
tree newop2;
+ gcc_assert (COMPARISON_CLASS_P (t));
tmpvar = create_tmp_var (TREE_TYPE (t), NULL);
add_referenced_var (tmpvar);
extract_ops_from_tree (t, &subcode, &newop1, &newop2);
+ STRIP_USELESS_TYPE_CONVERSION (newop1);
+ STRIP_USELESS_TYPE_CONVERSION (newop2);
+ gcc_checking_assert (is_gimple_val (newop1)
+ && is_gimple_val (newop2));
sum = build_and_add_sum (tmpvar, newop1, newop2, subcode);
curr->op = gimple_get_lhs (sum);
}
if (TREE_CODE (binlhs) == SSA_NAME)
{
binlhsdef = SSA_NAME_DEF_STMT (binlhs);
- binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode, loop);
+ binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
+ && !stmt_could_throw_p (binlhsdef));
}
if (TREE_CODE (binrhs) == SSA_NAME)
{
binrhsdef = SSA_NAME_DEF_STMT (binrhs);
- binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode, loop);
+ binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
+ && !stmt_could_throw_p (binrhsdef));
}
/* If the LHS is not reassociable, but the RHS is, we need to swap
unsigned int i = 0;
tree negate;
- for (i = 0; VEC_iterate (tree, plus_negates, i, negate); i++)
+ FOR_EACH_VEC_ELT (tree, plus_negates, i, negate)
{
gimple user = get_single_immediate_use (negate);
can_reassociate_p (tree op)
{
tree type = TREE_TYPE (op);
- if (INTEGRAL_TYPE_P (type)
+ if ((INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
|| NON_SAT_FIXED_POINT_TYPE_P (type)
|| (flag_associative_math && FLOAT_TYPE_P (type)))
return true;
{
gimple stmt = gsi_stmt (gsi);
- if (is_gimple_assign (stmt))
+ if (is_gimple_assign (stmt)
+ && !stmt_could_throw_p (stmt))
{
tree lhs, rhs1, rhs2;
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
rhs1 = gimple_assign_rhs1 (stmt);
rhs2 = gimple_assign_rhs2 (stmt);
- if (!can_reassociate_p (lhs)
- || !can_reassociate_p (rhs1)
- || !can_reassociate_p (rhs2))
+ /* For non-bit or min/max operations we can't associate
+ all types. Verify that here. */
+ if (rhs_code != BIT_IOR_EXPR
+ && rhs_code != BIT_AND_EXPR
+ && rhs_code != BIT_XOR_EXPR
+ && rhs_code != MIN_EXPR
+ && rhs_code != MAX_EXPR
+ && (!can_reassociate_p (lhs)
+ || !can_reassociate_p (rhs1)
+ || !can_reassociate_p (rhs2)))
continue;
if (associative_tree_code (rhs_code))
gimple_set_visited (stmt, true);
linearize_expr_tree (&ops, stmt, true, true);
- qsort (VEC_address (operand_entry_t, ops),
- VEC_length (operand_entry_t, ops),
- sizeof (operand_entry_t),
- sort_by_operand_rank);
+ VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
optimize_ops_list (rhs_code, &ops);
if (undistribute_ops_list (rhs_code, &ops,
loop_containing_stmt (stmt)))
{
- qsort (VEC_address (operand_entry_t, ops),
- VEC_length (operand_entry_t, ops),
- sizeof (operand_entry_t),
- sort_by_operand_rank);
+ VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
optimize_ops_list (rhs_code, &ops);
}
operand_entry_t oe;
unsigned int i;
- for (i = 0; VEC_iterate (operand_entry_t, ops, i, oe); i++)
+ FOR_EACH_VEC_ELT (operand_entry_t, ops, i, oe)
{
fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
print_generic_expr (file, oe->op, 0);
/* Dump the operand entry vector OPS to STDERR. */
-void
+DEBUG_FUNCTION void
debug_ops_vector (VEC (operand_entry_t, heap) *ops)
{
dump_ops_vector (stderr, ops);
/* Give each argument a distinct rank. */
for (param = DECL_ARGUMENTS (current_function_decl);
param;
- param = TREE_CHAIN (param))
+ param = DECL_CHAIN (param))
{
if (gimple_default_def (cfun, param) != NULL)
{