X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftree-ssa-reassoc.c;h=6e6f5f7f4425520e713f9c0be060bd77a2c7b328;hp=c36293f6937d7a3f0293314ab8897223f56bc10d;hb=1a60bb06c82a32d6bfd33b89b5e65937afdfaefb;hpb=4c36ffe68d981c213d168cf07f42dcc558bc7f1b diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index c36293f6937..6e6f5f7f442 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -1,12 +1,12 @@ /* Reassociation for trees. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. Contributed by Daniel Berlin 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) +the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, @@ -15,9 +15,8 @@ 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. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -38,6 +37,9 @@ Boston, MA 02110-1301, USA. */ #include "alloc-pool.h" #include "vec.h" #include "langhooks.h" +#include "pointer-set.h" +#include "cfgloop.h" +#include "flags.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 @@ -179,68 +181,38 @@ static alloc_pool operand_entry_pool; /* 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; @@ -260,37 +232,39 @@ get_rank (tree e) { tree stmt; tree rhs; - unsigned int rank, maxrank; + long rank, maxrank; int i; + int n; 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); - if (TREE_CODE_LENGTH (TREE_CODE (rhs)) == 0) + rhs = GIMPLE_STMT_OPERAND (stmt, 1); + n = TREE_OPERAND_LENGTH (rhs); + if (n == 0) rank = MAX (rank, get_rank (rhs)); else { for (i = 0; - i < TREE_CODE_LENGTH (TREE_CODE (rhs)) + i < n && TREE_OPERAND (rhs, i) && rank != maxrank; i++) @@ -301,7 +275,7 @@ get_rank (tree e) { 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. */ @@ -364,7 +338,7 @@ sort_by_operand_rank (const void *pa, const void *pb) static void add_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op) { - operand_entry_t oe = pool_alloc (operand_entry_pool); + operand_entry_t oe = (operand_entry_t) pool_alloc (operand_entry_pool); oe->op = op; oe->rank = get_rank (op); @@ -372,15 +346,23 @@ add_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op) } /* Return true if STMT is reassociable operation containing a binary - operation with tree code CODE. */ + operation with tree code CODE, and is inside LOOP. */ static bool -is_reassociable_op (tree stmt, enum tree_code code) +is_reassociable_op (tree stmt, enum tree_code code, struct loop *loop) { - if (!IS_EMPTY_STMT (stmt) - && TREE_CODE (stmt) == MODIFY_EXPR - && TREE_CODE (TREE_OPERAND (stmt, 1)) == code - && has_single_use (TREE_OPERAND (stmt, 0))) + basic_block bb; + + if (IS_EMPTY_STMT (stmt)) + return false; + + bb = bb_for_stmt (stmt); + if (!flow_bb_inside_loop_p (loop, bb)) + return false; + + if (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; } @@ -395,10 +377,10 @@ get_unary_op (tree name, enum tree_code opcode) 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; @@ -417,8 +399,8 @@ eliminate_duplicate_pair (enum tree_code opcode, 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. */ @@ -426,13 +408,15 @@ eliminate_duplicate_pair (enum tree_code opcode, { 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); @@ -615,8 +599,10 @@ eliminate_using_constants (enum tree_code opcode, VEC(operand_entry_t, heap) **ops) { operand_entry_t oelast = VEC_last (operand_entry_t, *ops); + tree type = TREE_TYPE (oelast->op); - if (oelast->rank == 0 && INTEGRAL_TYPE_P (TREE_TYPE (oelast->op))) + if (oelast->rank == 0 + && (INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type))) { switch (opcode) { @@ -677,7 +663,11 @@ eliminate_using_constants (enum tree_code opcode, } break; case MULT_EXPR: - if (integer_zerop (oelast->op)) + if (integer_zerop (oelast->op) + || (FLOAT_TYPE_P (type) + && !HONOR_NANS (TYPE_MODE (type)) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)) + && real_zerop (oelast->op))) { if (VEC_length (operand_entry_t, *ops) != 1) { @@ -692,7 +682,10 @@ eliminate_using_constants (enum tree_code opcode, return; } } - else if (integer_onep (oelast->op)) + else if (integer_onep (oelast->op) + || (FLOAT_TYPE_P (type) + && !HONOR_SNANS (TYPE_MODE (type)) + && real_onep (oelast->op))) { if (VEC_length (operand_entry_t, *ops) != 1) { @@ -707,7 +700,11 @@ eliminate_using_constants (enum tree_code opcode, case BIT_XOR_EXPR: case PLUS_EXPR: case MINUS_EXPR: - if (integer_zerop (oelast->op)) + if (integer_zerop (oelast->op) + || (FLOAT_TYPE_P (type) + && (opcode == PLUS_EXPR || opcode == MINUS_EXPR) + && fold_real_zero_addition_p (type, oelast->op, + opcode == MINUS_EXPR))) { if (VEC_length (operand_entry_t, *ops) != 1) { @@ -752,8 +749,8 @@ optimize_ops_list (enum tree_code opcode, if (oelm1->rank == 0 && is_gimple_min_invariant (oelm1->op) - && lang_hooks.types_compatible_p (TREE_TYPE (oelm1->op), - TREE_TYPE (oelast->op))) + && useless_type_conversion_p (TREE_TYPE (oelm1->op), + TREE_TYPE (oelast->op))) { tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op), oelm1->op, oelast->op); @@ -812,7 +809,7 @@ static bool 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; @@ -837,7 +834,7 @@ static void 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 @@ -874,6 +871,18 @@ rewrite_expr_tree (tree stmt, unsigned int opindex, oe1->op = temp.op; oe1->rank= temp.rank; } + else if ((oe1->rank == oe3->rank + && oe2->rank != oe3->rank) + || (is_phi_for_stmt (stmt, oe2->op) + && !is_phi_for_stmt (stmt, oe1->op) + && !is_phi_for_stmt (stmt, oe3->op))) + { + struct operand_entry temp = *oe2; + oe2->op = oe1->op; + oe2->rank = oe1->rank; + oe1->op = temp.op; + oe1->rank= temp.rank; + } } /* The final recursion case for this function is that you have @@ -950,24 +959,26 @@ static void 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)); tree newbinrhs = NULL_TREE; + struct loop *loop = loop_containing_stmt (stmt); - gcc_assert (is_reassociable_op (binlhs, TREE_CODE (rhs)) - && is_reassociable_op (binrhs, TREE_CODE (rhs))); + gcc_assert (is_reassociable_op (binlhs, TREE_CODE (rhs), loop) + && is_reassociable_op (binrhs, TREE_CODE (rhs), loop)); bsinow = bsi_for_stmt (stmt); 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)) { @@ -984,12 +995,11 @@ linearize_expr (tree stmt) TREE_VISITED (stmt) = 1; /* Tail recurse on the new rhs if it still needs reassociation. */ - if (newbinrhs && is_reassociable_op (newbinrhs, rhscode)) + if (newbinrhs && is_reassociable_op (newbinrhs, rhscode, loop)) linearize_expr (stmt); - } -/* 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 @@ -1003,7 +1013,7 @@ get_single_immediate_use (tree lhs) { 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; @@ -1030,13 +1040,13 @@ negate_value (tree tonegate, block_stmt_iterator *bsi) /* 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), @@ -1045,12 +1055,12 @@ negate_value (tree tonegate, block_stmt_iterator *bsi) 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); resultofnegate = force_gimple_operand_bsi (bsi, tonegate, true, - NULL_TREE); + NULL_TREE, true, BSI_SAME_STMT); VEC_safe_push (tree, heap, broken_up_subtracts, resultofnegate); return resultofnegate; @@ -1066,23 +1076,24 @@ static bool 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; + struct loop *loop = loop_containing_stmt (stmt); if (TREE_CODE (binlhs) == SSA_NAME - && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR)) + && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR, loop)) return true; if (TREE_CODE (binrhs) == SSA_NAME - && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR)) + && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR, loop)) return true; 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; @@ -1093,7 +1104,7 @@ should_break_up_subtract (tree stmt) 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)) { @@ -1101,7 +1112,7 @@ break_up_subtract (tree stmt, block_stmt_iterator *bsi) 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); @@ -1114,26 +1125,27 @@ static void 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; bool binlhsisreassoc = false; bool binrhsisreassoc = false; enum tree_code rhscode = TREE_CODE (rhs); + struct loop *loop = loop_containing_stmt (stmt); TREE_VISITED (stmt) = 1; if (TREE_CODE (binlhs) == SSA_NAME) { binlhsdef = SSA_NAME_DEF_STMT (binlhs); - binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode); + binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode, loop); } if (TREE_CODE (binrhs) == SSA_NAME) { binrhsdef = SSA_NAME_DEF_STMT (binrhs); - binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode); + binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode, loop); } /* If the LHS is not reassociable, but the RHS is, we need to swap @@ -1178,13 +1190,14 @@ linearize_expr_tree (VEC(operand_entry_t, heap) **ops, tree stmt) 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); } gcc_assert (TREE_CODE (binrhs) != SSA_NAME - || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), rhscode)); + || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), + rhscode, loop)); bsinow = bsi_for_stmt (stmt); bsilhs = bsi_for_stmt (SSA_NAME_DEF_STMT (binlhs)); bsi_move_before (&bsilhs, &bsinow); @@ -1211,15 +1224,15 @@ repropagate_negates (void) 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); @@ -1228,7 +1241,7 @@ repropagate_negates (void) /* 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); @@ -1263,19 +1276,22 @@ break_up_subtract_bb (basic_block bb) { 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 - non-integral types. */ + /* If associative-math we can do reassociation for + non-integral types. Or, we can do reassociation for + non-saturating fixed-point types. */ if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || !INTEGRAL_TYPE_P (TREE_TYPE (rhs))) && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs)) || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs)) - || !flag_unsafe_math_optimizations)) + || !flag_associative_math) + && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs)) + || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs)))) continue; /* Check for a subtract used only in an addition. If this @@ -1306,23 +1322,26 @@ reassociate_bb (basic_block bb) { 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. */ if (TREE_VISITED (stmt)) continue; - /* If unsafe math optimizations we can do reassociation for - non-integral types. */ + /* If associative-math we can do reassociation for + non-integral types. Or, we can do reassociation for + non-saturating fixed-point types. */ if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || !INTEGRAL_TYPE_P (TREE_TYPE (rhs))) && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs)) || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs)) - || !flag_unsafe_math_optimizations)) + || !flag_associative_math) + && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs)) + || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs)))) continue; if (associative_tree_code (TREE_CODE (rhs))) @@ -1331,7 +1350,7 @@ reassociate_bb (basic_block bb) /* 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; @@ -1349,14 +1368,15 @@ reassociate_bb (basic_block bb) 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 @@ -1413,10 +1433,14 @@ static void init_reassoc (void) { int i; - unsigned int rank = 2; + long rank = 2; tree param; int *bbs = XNEWVEC (int, last_basic_block + 1); + /* Find the loops, so that we can prevent moving calculations in + them. */ + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + memset (&reassociate_stats, 0, sizeof (reassociate_stats)); operand_entry_pool = create_alloc_pool ("operand entry pool", @@ -1425,19 +1449,17 @@ init_reassoc (void) /* 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 = XCNEWVEC (unsigned int, last_basic_block + 1); - - 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); } } @@ -1445,7 +1467,7 @@ init_reassoc (void) /* 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); } @@ -1455,7 +1477,6 @@ init_reassoc (void) bb_rank[bbs[i]] = ++rank << 16; free (bbs); - calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS); broken_up_subtracts = NULL; } @@ -1466,7 +1487,6 @@ init_reassoc (void) static void fini_reassoc (void) { - if (dump_file && (dump_flags & TDF_STATS)) { fprintf (dump_file, "Reassociation stats:\n"); @@ -1479,17 +1499,18 @@ fini_reassoc (void) 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); free_dominance_info (CDI_POST_DOMINATORS); + loop_optimizer_finalize (); } /* Gate and execute functions for Reassociation. */ -static void +static unsigned int execute_reassoc (void) { init_reassoc (); @@ -1498,17 +1519,24 @@ execute_reassoc (void) repropagate_negates (); fini_reassoc (); + return 0; +} + +static bool +gate_tree_ssa_reassoc (void) +{ + return flag_tree_reassoc != 0; } struct tree_opt_pass pass_reassoc = { "reassoc", /* name */ - NULL, /* gate */ - execute_reassoc, /* execute */ + gate_tree_ssa_reassoc, /* gate */ + execute_reassoc, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_TREE_REASSOC, /* tv_id */ + TV_TREE_REASSOC, /* tv_id */ PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */