Commit 487bf3e6 by Jeff Law Committed by Jeff Law

tree-ssa-dom.c (simplify_cond_and_lookup_avail_expr): Remove code to propagate…

tree-ssa-dom.c (simplify_cond_and_lookup_avail_expr): Remove code to propagate the RHS of a cast into COND_EXPR_COND.

        * tree-ssa-dom.c (simplify_cond_and_lookup_avail_expr): Remove
        code to propagate the RHS of a cast into COND_EXPR_COND.  Remove
        now unused arguments.  Callers updated.
        (eliminate_redundant_computations): Remove now unused arguments,
        callers updated.
        (local_fold): Remove, no longer used.
        (find_equivalent_equality_comparison): Removed from tree-ssa-dom.c
        and moved to...
        * tree-ssa-forwprop.c (find_equivalent_equality_comparison): Here.
        (simplify_cond): New function.
        (forward_propagate_into_cond): Call simplify_cond.

From-SVN: r109502
parent c49c0c39
2005-01-09 Jeff Law <law@redhat.com>
* tree-ssa-dom.c (simplify_cond_and_lookup_avail_expr): Remove
code to propagate the RHS of a cast into COND_EXPR_COND. Remove
now unused arguments. Callers updated.
(eliminate_redundant_computations): Remove now unused arguments,
callers updated.
(local_fold): Remove, no longer used.
(find_equivalent_equality_comparison): Removed from tree-ssa-dom.c
and moved to...
* tree-ssa-forwprop.c (find_equivalent_equality_comparison): Here.
(simplify_cond): New function.
(forward_propagate_into_cond): Call simplify_cond.
2006-01-09 Alexandre Oliva <aoliva@redhat.com> 2006-01-09 Alexandre Oliva <aoliva@redhat.com>
* config/i386/sse.md (*vec_extractv2di_1_sse2): New. * config/i386/sse.md (*vec_extractv2di_1_sse2): New.
......
...@@ -273,13 +273,12 @@ static void htab_statistics (FILE *, htab_t); ...@@ -273,13 +273,12 @@ static void htab_statistics (FILE *, htab_t);
static void record_cond (tree, tree); static void record_cond (tree, tree);
static void record_const_or_copy (tree, tree); static void record_const_or_copy (tree, tree);
static void record_equality (tree, tree); static void record_equality (tree, tree);
static tree simplify_cond_and_lookup_avail_expr (tree, stmt_ann_t, int); static tree simplify_cond_and_lookup_avail_expr (tree);
static tree find_equivalent_equality_comparison (tree);
static void record_range (tree, basic_block); static void record_range (tree, basic_block);
static bool extract_range_from_cond (tree, tree *, tree *, int *); static bool extract_range_from_cond (tree, tree *, tree *, int *);
static void record_equivalences_from_phis (basic_block); static void record_equivalences_from_phis (basic_block);
static void record_equivalences_from_incoming_edge (basic_block); static void record_equivalences_from_incoming_edge (basic_block);
static bool eliminate_redundant_computations (tree, stmt_ann_t); static bool eliminate_redundant_computations (tree);
static void record_equivalences_from_stmt (tree, int, stmt_ann_t); static void record_equivalences_from_stmt (tree, int, stmt_ann_t);
static void thread_across_edge (struct dom_walk_data *, edge); static void thread_across_edge (struct dom_walk_data *, edge);
static void dom_opt_finalize_block (struct dom_walk_data *, basic_block); static void dom_opt_finalize_block (struct dom_walk_data *, basic_block);
...@@ -292,21 +291,6 @@ static void restore_nonzero_vars_to_original_value (void); ...@@ -292,21 +291,6 @@ static void restore_nonzero_vars_to_original_value (void);
static inline bool unsafe_associative_fp_binop (tree); static inline bool unsafe_associative_fp_binop (tree);
/* Local version of fold that doesn't introduce cruft. */
static tree
local_fold (tree t)
{
t = fold (t);
/* Strip away useless type conversions. Both the NON_LVALUE_EXPR that
may have been added by fold, and "useless" type conversions that might
now be apparent due to propagation. */
STRIP_USELESS_TYPE_CONVERSION (t);
return t;
}
/* Allocate an EDGE_INFO for edge E and attach it to E. /* Allocate an EDGE_INFO for edge E and attach it to E.
Return the new EDGE_INFO structure. */ Return the new EDGE_INFO structure. */
...@@ -904,9 +888,7 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) ...@@ -904,9 +888,7 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
{ {
cached_lhs = lookup_avail_expr (dummy_cond, false); cached_lhs = lookup_avail_expr (dummy_cond, false);
if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs)) if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond, cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond);
NULL,
false);
} }
} }
/* We can have conditionals which just test the state of a /* We can have conditionals which just test the state of a
...@@ -1797,99 +1779,13 @@ simple_iv_increment_p (tree stmt) ...@@ -1797,99 +1779,13 @@ simple_iv_increment_p (tree stmt)
return false; return false;
} }
/* COND is a condition of the form:
x == const or x != const
Look back to x's defining statement and see if x is defined as
x = (type) y;
If const is unchanged if we convert it to type, then we can build
the equivalent expression:
y == const or y != const
Which may allow further optimizations.
Return the equivalent comparison or NULL if no such equivalent comparison
was found. */
static tree
find_equivalent_equality_comparison (tree cond)
{
tree op0 = TREE_OPERAND (cond, 0);
tree op1 = TREE_OPERAND (cond, 1);
tree def_stmt = SSA_NAME_DEF_STMT (op0);
/* OP0 might have been a parameter, so first make sure it
was defined by a MODIFY_EXPR. */
if (def_stmt && TREE_CODE (def_stmt) == MODIFY_EXPR)
{
tree def_rhs = TREE_OPERAND (def_stmt, 1);
/* If either operand to the comparison is a pointer to
a function, then we can not apply this optimization
as some targets require function pointers to be
canonicalized and in this case this optimization would
eliminate a necessary canonicalization. */
if ((POINTER_TYPE_P (TREE_TYPE (op0))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == FUNCTION_TYPE)
|| (POINTER_TYPE_P (TREE_TYPE (op1))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op1))) == FUNCTION_TYPE))
return NULL;
/* Now make sure the RHS of the MODIFY_EXPR is a typecast. */
if ((TREE_CODE (def_rhs) == NOP_EXPR
|| TREE_CODE (def_rhs) == CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME)
{
tree def_rhs_inner = TREE_OPERAND (def_rhs, 0);
tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner);
tree new;
if (TYPE_PRECISION (def_rhs_inner_type)
> TYPE_PRECISION (TREE_TYPE (def_rhs)))
return NULL;
/* If the inner type of the conversion is a pointer to
a function, then we can not apply this optimization
as some targets require function pointers to be
canonicalized. This optimization would result in
canonicalization of the pointer when it was not originally
needed/intended. */
if (POINTER_TYPE_P (def_rhs_inner_type)
&& TREE_CODE (TREE_TYPE (def_rhs_inner_type)) == FUNCTION_TYPE)
return NULL;
/* What we want to prove is that if we convert OP1 to
the type of the object inside the NOP_EXPR that the
result is still equivalent to SRC.
If that is true, the build and return new equivalent
condition which uses the source of the typecast and the
new constant (which has only changed its type). */
new = build1 (TREE_CODE (def_rhs), def_rhs_inner_type, op1);
new = local_fold (new);
if (is_gimple_val (new) && tree_int_cst_equal (new, op1))
return build2 (TREE_CODE (cond), TREE_TYPE (cond),
def_rhs_inner, new);
}
}
return NULL;
}
/* STMT is a COND_EXPR for which we could not trivially determine its /* STMT is a COND_EXPR for which we could not trivially determine its
result. This routine attempts to find equivalent forms of the result. This routine attempts to find equivalent forms of the
condition which we may be able to optimize better. It also condition which we may be able to optimize better. It also
uses simple value range propagation to optimize conditionals. */ uses simple value range propagation to optimize conditionals. */
static tree static tree
simplify_cond_and_lookup_avail_expr (tree stmt, simplify_cond_and_lookup_avail_expr (tree stmt)
stmt_ann_t ann,
int insert)
{ {
tree cond = COND_EXPR_COND (stmt); tree cond = COND_EXPR_COND (stmt);
...@@ -1908,37 +1804,6 @@ simplify_cond_and_lookup_avail_expr (tree stmt, ...@@ -1908,37 +1804,6 @@ simplify_cond_and_lookup_avail_expr (tree stmt,
struct vrp_hash_elt vrp_hash_elt, *vrp_hash_elt_p; struct vrp_hash_elt vrp_hash_elt, *vrp_hash_elt_p;
void **slot; void **slot;
/* First see if we have test of an SSA_NAME against a constant
where the SSA_NAME is defined by an earlier typecast which
is irrelevant when performing tests against the given
constant. */
if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
{
tree new_cond = find_equivalent_equality_comparison (cond);
if (new_cond)
{
/* Update the statement to use the new equivalent
condition. */
COND_EXPR_COND (stmt) = new_cond;
/* If this is not a real stmt, ann will be NULL and we
avoid processing the operands. */
if (ann)
mark_stmt_modified (stmt);
/* Lookup the condition and return its known value if it
exists. */
new_cond = lookup_avail_expr (stmt, insert);
if (new_cond)
return new_cond;
/* The operands have changed, so update op0 and op1. */
op0 = TREE_OPERAND (cond, 0);
op1 = TREE_OPERAND (cond, 1);
}
}
/* Consult the value range records for this variable (if they exist) /* Consult the value range records for this variable (if they exist)
to see if we can eliminate or simplify this conditional. to see if we can eliminate or simplify this conditional.
...@@ -2386,7 +2251,7 @@ propagate_to_outgoing_edges (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, ...@@ -2386,7 +2251,7 @@ propagate_to_outgoing_edges (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
table. */ table. */
static bool static bool
eliminate_redundant_computations (tree stmt, stmt_ann_t ann) eliminate_redundant_computations (tree stmt)
{ {
tree *expr_p, def = NULL_TREE; tree *expr_p, def = NULL_TREE;
bool insert = true; bool insert = true;
...@@ -2414,7 +2279,7 @@ eliminate_redundant_computations (tree stmt, stmt_ann_t ann) ...@@ -2414,7 +2279,7 @@ eliminate_redundant_computations (tree stmt, stmt_ann_t ann)
/* If this is a COND_EXPR and we did not find its expression in /* If this is a COND_EXPR and we did not find its expression in
the hash table, simplify the condition and try again. */ the hash table, simplify the condition and try again. */
if (! cached_lhs && TREE_CODE (stmt) == COND_EXPR) if (! cached_lhs && TREE_CODE (stmt) == COND_EXPR)
cached_lhs = simplify_cond_and_lookup_avail_expr (stmt, ann, insert); cached_lhs = simplify_cond_and_lookup_avail_expr (stmt);
opt_stats.num_exprs_considered++; opt_stats.num_exprs_considered++;
...@@ -2816,8 +2681,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, ...@@ -2816,8 +2681,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
|| TREE_CODE (stmt) == SWITCH_EXPR)); || TREE_CODE (stmt) == SWITCH_EXPR));
if (may_optimize_p) if (may_optimize_p)
may_have_exposed_new_symbols may_have_exposed_new_symbols |= eliminate_redundant_computations (stmt);
|= eliminate_redundant_computations (stmt, ann);
/* Record any additional equivalences created by this statement. */ /* Record any additional equivalences created by this statement. */
if (TREE_CODE (stmt) == MODIFY_EXPR) if (TREE_CODE (stmt) == MODIFY_EXPR)
......
...@@ -36,7 +36,8 @@ Boston, MA 02110-1301, USA. */ ...@@ -36,7 +36,8 @@ Boston, MA 02110-1301, USA. */
/* This pass propagates the RHS of assignment statements into use /* This pass propagates the RHS of assignment statements into use
sites of the LHS of the assignment. It's basically a specialized sites of the LHS of the assignment. It's basically a specialized
form of tree combination. form of tree combination. It is hoped all of this can disappear
when we have a generalized tree combiner.
Note carefully that after propagation the resulting statement Note carefully that after propagation the resulting statement
must still be a proper gimple statement. Right now we simply must still be a proper gimple statement. Right now we simply
...@@ -142,6 +143,9 @@ Boston, MA 02110-1301, USA. */ ...@@ -142,6 +143,9 @@ Boston, MA 02110-1301, USA. */
ptr2 = &x[index]; ptr2 = &x[index];
We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
{NOT_EXPR,NEG_EXPR}.
This will (of course) be extended as other needs arise. */ This will (of course) be extended as other needs arise. */
...@@ -398,6 +402,129 @@ forward_propagate_into_cond_1 (tree cond, tree *test_var_p) ...@@ -398,6 +402,129 @@ forward_propagate_into_cond_1 (tree cond, tree *test_var_p)
return new_cond; return new_cond;
} }
/* COND is a condition of the form:
x == const or x != const
Look back to x's defining statement and see if x is defined as
x = (type) y;
If const is unchanged if we convert it to type, then we can build
the equivalent expression:
y == const or y != const
Which may allow further optimizations.
Return the equivalent comparison or NULL if no such equivalent comparison
was found. */
static tree
find_equivalent_equality_comparison (tree cond)
{
tree op0 = TREE_OPERAND (cond, 0);
tree op1 = TREE_OPERAND (cond, 1);
tree def_stmt = SSA_NAME_DEF_STMT (op0);
while (def_stmt
&& TREE_CODE (def_stmt) == MODIFY_EXPR
&& TREE_CODE (TREE_OPERAND (def_stmt, 1)) == SSA_NAME)
def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (def_stmt, 1));
/* OP0 might have been a parameter, so first make sure it
was defined by a MODIFY_EXPR. */
if (def_stmt && TREE_CODE (def_stmt) == MODIFY_EXPR)
{
tree def_rhs = TREE_OPERAND (def_stmt, 1);
/* If either operand to the comparison is a pointer to
a function, then we can not apply this optimization
as some targets require function pointers to be
canonicalized and in this case this optimization would
eliminate a necessary canonicalization. */
if ((POINTER_TYPE_P (TREE_TYPE (op0))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == FUNCTION_TYPE)
|| (POINTER_TYPE_P (TREE_TYPE (op1))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op1))) == FUNCTION_TYPE))
return NULL;
/* Now make sure the RHS of the MODIFY_EXPR is a typecast. */
if ((TREE_CODE (def_rhs) == NOP_EXPR
|| TREE_CODE (def_rhs) == CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME)
{
tree def_rhs_inner = TREE_OPERAND (def_rhs, 0);
tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner);
tree new;
if (TYPE_PRECISION (def_rhs_inner_type)
> TYPE_PRECISION (TREE_TYPE (def_rhs)))
return NULL;
/* If the inner type of the conversion is a pointer to
a function, then we can not apply this optimization
as some targets require function pointers to be
canonicalized. This optimization would result in
canonicalization of the pointer when it was not originally
needed/intended. */
if (POINTER_TYPE_P (def_rhs_inner_type)
&& TREE_CODE (TREE_TYPE (def_rhs_inner_type)) == FUNCTION_TYPE)
return NULL;
/* What we want to prove is that if we convert OP1 to
the type of the object inside the NOP_EXPR that the
result is still equivalent to SRC.
If that is true, the build and return new equivalent
condition which uses the source of the typecast and the
new constant (which has only changed its type). */
new = fold_build1 (TREE_CODE (def_rhs), def_rhs_inner_type, op1);
STRIP_USELESS_TYPE_CONVERSION (new);
if (is_gimple_val (new) && tree_int_cst_equal (new, op1))
return build2 (TREE_CODE (cond), TREE_TYPE (cond),
def_rhs_inner, new);
}
}
return NULL;
}
/* STMT is a COND_EXPR
This routine attempts to find equivalent forms of the condition
which we may be able to optimize better. */
static void
simplify_cond (tree stmt)
{
tree cond = COND_EXPR_COND (stmt);
if (COMPARISON_CLASS_P (cond))
{
tree op0 = TREE_OPERAND (cond, 0);
tree op1 = TREE_OPERAND (cond, 1);
if (TREE_CODE (op0) == SSA_NAME && is_gimple_min_invariant (op1))
{
/* First see if we have test of an SSA_NAME against a constant
where the SSA_NAME is defined by an earlier typecast which
is irrelevant when performing tests against the given
constant. */
if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
{
tree new_cond = find_equivalent_equality_comparison (cond);
if (new_cond)
{
COND_EXPR_COND (stmt) = new_cond;
update_stmt (stmt);
}
}
}
}
}
/* Forward propagate a single-use variable into COND_EXPR as many /* Forward propagate a single-use variable into COND_EXPR as many
times as possible. */ times as possible. */
...@@ -436,6 +563,13 @@ forward_propagate_into_cond (tree cond_expr) ...@@ -436,6 +563,13 @@ forward_propagate_into_cond (tree cond_expr)
bsi_remove (&bsi, true); bsi_remove (&bsi, true);
} }
} }
/* There are further simplifications that can be performed
on COND_EXPRs. Specifically, when comparing an SSA_NAME
against a constant where the SSA_NAME is the result of a
conversion. Perhaps this should be folded into the rest
of the COND_EXPR simplification code. */
simplify_cond (cond_expr);
} }
/* We've just substituted an ADDR_EXPR into stmt. Update all the /* We've just substituted an ADDR_EXPR into stmt. Update all the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment