diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-09 16:56:49 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-09 16:56:49 +0000 |
commit | 8f628ee83a8e26b6bb2a8ad4ff4d0d46cded7ccf (patch) | |
tree | f25d3e3fc6c291e9620d52bbd2922ca9435a0a26 /gcc/tree-ssa-forwprop.c | |
parent | a150ee15564cbd8d4a5396d90180047952165895 (diff) | |
download | gcc-8f628ee83a8e26b6bb2a8ad4ff4d0d46cded7ccf.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109502 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 979f2b44c4a..2f857dc1076 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -36,7 +36,8 @@ Boston, MA 02110-1301, USA. */ /* This pass propagates the RHS of assignment statements into use 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 must still be a proper gimple statement. Right now we simply @@ -142,6 +143,9 @@ Boston, MA 02110-1301, USA. */ 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. */ @@ -398,6 +402,129 @@ forward_propagate_into_cond_1 (tree cond, tree *test_var_p) 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 times as possible. */ @@ -436,6 +563,13 @@ forward_propagate_into_cond (tree cond_expr) 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 |