aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c237
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);
}