diff options
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 237 |
1 files changed, 234 insertions, 3 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index b13894e42fc..813b7e3604f 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -1,5 +1,5 @@ /* Forward propagation of single use variables. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -472,6 +472,233 @@ substitute_single_use_vars (varray_type *cond_worklist, } } +/* APPLE LOCAL begin cast removal. */ + +/* Return TRUE iff STMT is a MODIFY_EXPR of the form + x = (cast) y; +*/ +static bool cast_conversion_assignment_p (tree stmt) +{ + tree lhs, rhs; + + gcc_assert (stmt); + + if (TREE_CODE (stmt) != MODIFY_EXPR) + return false; + + lhs = TREE_OPERAND (stmt, 0); + rhs = TREE_OPERAND (stmt, 1); + if ((TREE_CODE (rhs) == NOP_EXPR + || TREE_CODE (rhs) == CONVERT_EXPR) + && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME + && TREE_CODE (lhs) == SSA_NAME) + return true; + + return false; +} + +/* STMT is a comparision and it uses DEF_STMT. + DEF_STMT is a modify expression that applys cast. + Return TRUE iff, it is OK to replace use of DEF_STMT by LHS's + inner type. If NEW_STMT is not NULL then */ +static bool +replacable_use_in_cond_expr (tree stmt, tree def_stmt, tree *new_stmt) +{ + tree op0, op1, candidate_op, other_op, temp, def_rhs, def_rhs_inner_type; + + gcc_assert (stmt); + gcc_assert (def_stmt); + gcc_assert (COMPARISON_CLASS_P (stmt)); + gcc_assert (TREE_CODE (def_stmt) == MODIFY_EXPR); + + candidate_op = NULL_TREE; + other_op = NULL_TREE; + + op0 = TREE_OPERAND (stmt, 0); + op1 = TREE_OPERAND (stmt, 1); + + if (TREE_CODE (op0) == SSA_NAME + && SSA_NAME_DEF_STMT (op0) == def_stmt + && is_gimple_min_invariant (op1)) + { + candidate_op = op0; + other_op = op1; + } + else if (TREE_CODE (op1) == SSA_NAME + && SSA_NAME_DEF_STMT (op1) == def_stmt + && is_gimple_min_invariant (op0)) + { + candidate_op = op1; + other_op = op0; + } + else + return false; + + if (!cast_conversion_assignment_p (def_stmt)) + return false; + + /* What we want to prove is that if we convert CANDIDATE_OP to + the type of the object inside the NOP_EXPR that the + result is still equivalent to SRC. */ + def_rhs = TREE_OPERAND (def_stmt, 1); + def_rhs_inner_type = TREE_TYPE (TREE_OPERAND (def_rhs, 0)); + temp = build1 (TREE_CODE (def_rhs), def_rhs_inner_type, other_op); + temp = fold (temp); + if (is_gimple_val (temp) && tree_int_cst_equal (temp, other_op)) + { + if (new_stmt) + *new_stmt = build (TREE_CODE (stmt), TREE_TYPE (stmt), + TREE_OPERAND (def_rhs, 0), temp); + + return true; + } + return false; +} + +/* Return TRUE iff all uses of STMT are candidate for replacement. */ +static bool +all_uses_are_replacable (tree stmt, bool replace) +{ + dataflow_t df; + int j, num_uses; + bool replacable = true; + + /* Now compute the immediate uses of TEST_VAR. */ + df = get_immediate_uses (stmt); + num_uses = num_immediate_uses (df); + + for (j = 0; j < num_uses && replacable; j++) + { + tree use = immediate_use (df, j); + + if (replace && dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, " Removing casts"); + print_generic_expr (dump_file, use, dump_flags); + fprintf (dump_file, "\n"); + } + + if (TREE_CODE (use) == MODIFY_EXPR) + { + replacable = cast_conversion_assignment_p (use); + if (replace) + { + /* Before + + STMT: a = (cast) b; + USE: c = (undo_cast) a; + + After + + USE: c = b; + */ + tree def_rhs = TREE_OPERAND (stmt, 1); + tree def_rhs_inner = TREE_OPERAND (def_rhs, 0); + tree use_lhs = TREE_OPERAND (use, 0); + + tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner); + tree use_lhs_type = TREE_TYPE (use_lhs); + + if ((TYPE_PRECISION (def_rhs_inner_type) + == TYPE_PRECISION (use_lhs_type)) + && (TYPE_MAIN_VARIANT (def_rhs_inner_type) + == TYPE_MAIN_VARIANT (use_lhs_type))) + { + TREE_OPERAND (use, 1) = TREE_OPERAND (def_rhs, 0); + modify_stmt (use); + } + } + } + else if (TREE_CODE (use) == COND_EXPR + && COMPARISON_CLASS_P (COND_EXPR_COND (use))) + { + if (replace) + { + tree new_cond = NULL_TREE; + replacable = replacable_use_in_cond_expr (COND_EXPR_COND (use), + stmt, &new_cond); + if (new_cond) + { + COND_EXPR_COND (use) = new_cond; + modify_stmt (use); + } + else + abort (); + } + else + replacable = replacable_use_in_cond_expr (COND_EXPR_COND (use), + stmt, NULL); + } + else + replacable = false; + } + + return replacable; +} + +static void +eliminate_unnecessary_casts (void) +{ + basic_block bb; + block_stmt_iterator bsi; + varray_type worklist; + + /* Memory allocation. */ + vars = BITMAP_ALLOC (NULL); + VARRAY_TREE_INIT (worklist, 10, "worklist"); + FOR_EACH_BB (bb) + { + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + + /* If stmt is of the form + x = (cast) y; + then make x candidate. */ + + if (cast_conversion_assignment_p (stmt)) + { + tree lhs = TREE_OPERAND (stmt, 0); + tree rhs = TREE_OPERAND (stmt, 1); + tree rhs_inner = TREE_OPERAND (rhs, 0); + tree rhs_type = TREE_TYPE (rhs); + tree rhs_inner_type = TREE_TYPE (rhs_inner); + + if ((TYPE_PRECISION (rhs_inner_type) <= TYPE_PRECISION (rhs_type)) + && (TYPE_UNSIGNED (rhs_inner_type) == TYPE_UNSIGNED (rhs_type))) + { + bitmap_set_bit (vars, SSA_NAME_VERSION (lhs)); + VARRAY_PUSH_TREE (worklist, stmt); + } + } + } + } + + /* Now compute immidiate uses for candidates. */ + compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for); + while (VARRAY_ACTIVE_SIZE (worklist) > 0) + { + tree stmt = VARRAY_TOP_TREE (worklist); + VARRAY_POP (worklist); + + if (all_uses_are_replacable (stmt, false /* Do not replace */)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file,"File name = %s\n", __FILE__); + fprintf (dump_file,"Input name = %s\n", main_input_filename); + } + all_uses_are_replacable (stmt, true /* Replace */); + } + + } + /* Cleanup */ + free_df (); + BITMAP_FREE (vars); +} + +/* APPLE LOCAL end cast removal. */ + /* Main entry point for the forward propagation optimizer. */ static void @@ -480,7 +707,11 @@ tree_ssa_forward_propagate_single_use_vars (void) basic_block bb; varray_type vars_worklist, cond_worklist; - vars = BITMAP_XMALLOC (); + /* APPLE LOCAL begin cast removal. */ + eliminate_unnecessary_casts (); + /* APPLE LOCAL end cast removal. */ + + vars = BITMAP_ALLOC (NULL); VARRAY_TREE_INIT (vars_worklist, 10, "VARS worklist"); VARRAY_TREE_INIT (cond_worklist, 10, "COND worklist"); @@ -522,7 +753,7 @@ tree_ssa_forward_propagate_single_use_vars (void) } /* All done. Clean up. */ - BITMAP_XFREE (vars); + BITMAP_FREE (vars); } |