diff options
author | Richard Guenther <rguenther@suse.de> | 2011-07-07 14:20:16 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-07-07 14:20:16 +0000 |
commit | 29c5134ac901bba223eb66866cd4be7d30194dc3 (patch) | |
tree | f136ffc88ee435e9cda3b37d111d3f10497c5b11 /gcc/tree-vrp.c | |
parent | 0816a42a1fa5f3fa99d5756b35c9e7a94cbdb86e (diff) | |
download | gcc-29c5134ac901bba223eb66866cd4be7d30194dc3.zip gcc-29c5134ac901bba223eb66866cd4be7d30194dc3.tar.gz gcc-29c5134ac901bba223eb66866cd4be7d30194dc3.tar.bz2 |
tree-vrp.c (simplify_conversion_using_ranges): New function.
2011-07-07 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (simplify_conversion_using_ranges): New function.
(simplify_stmt_using_ranges): Call it.
* gcc.dg/tree-ssa/vrp58.c: New testcase.
* gcc.dg/tree-ssa/scev-cast.c: Adjust.
From-SVN: r175975
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index c049c5d..68998b37 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -7342,6 +7342,39 @@ simplify_switch_using_ranges (gimple stmt) return false; } +/* Simplify an integral conversion from an SSA name in STMT. */ + +static bool +simplify_conversion_using_ranges (gimple stmt) +{ + tree rhs1 = gimple_assign_rhs1 (stmt); + gimple def_stmt = SSA_NAME_DEF_STMT (rhs1); + value_range_t *final, *inner; + + /* Obtain final and inner value-ranges for a conversion + sequence (final-type)(intermediate-type)inner-type. */ + final = get_value_range (gimple_assign_lhs (stmt)); + if (final->type != VR_RANGE) + return false; + if (!is_gimple_assign (def_stmt) + || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) + return false; + rhs1 = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs1) != SSA_NAME) + return false; + inner = get_value_range (rhs1); + if (inner->type != VR_RANGE) + return false; + /* If the value-range is preserved by the conversion sequence strip + the intermediate conversion. */ + if (!tree_int_cst_equal (final->min, inner->min) + || !tree_int_cst_equal (final->max, inner->max)) + return false; + gimple_assign_set_rhs1 (stmt, rhs1); + update_stmt (stmt); + return true; +} + /* Simplify STMT using ranges if possible. */ static bool @@ -7351,6 +7384,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) if (is_gimple_assign (stmt)) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); + tree rhs1 = gimple_assign_rhs1 (stmt); switch (rhs_code) { @@ -7364,7 +7398,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) or identity if the RHS is zero or one, and the LHS are known to be boolean values. Transform all TRUTH_*_EXPR into BIT_*_EXPR if both arguments are known to be boolean values. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))) + if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) return simplify_truth_ops_using_ranges (gsi, stmt); break; @@ -7373,15 +7407,15 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) than zero and the second operand is an exact power of two. */ case TRUNC_DIV_EXPR: case TRUNC_MOD_EXPR: - if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))) + if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) && integer_pow2p (gimple_assign_rhs2 (stmt))) return simplify_div_or_mod_using_ranges (stmt); break; /* Transform ABS (X) into X or -X as appropriate. */ case ABS_EXPR: - if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME - && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))) + if (TREE_CODE (rhs1) == SSA_NAME + && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) return simplify_abs_using_ranges (stmt); break; @@ -7390,10 +7424,16 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) /* Optimize away BIT_AND_EXPR and BIT_IOR_EXPR if all the bits being cleared are already cleared or all the bits being set are already set. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))) + if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) return simplify_bit_ops_using_ranges (gsi, stmt); break; + CASE_CONVERT: + if (TREE_CODE (rhs1) == SSA_NAME + && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) + return simplify_conversion_using_ranges (stmt); + break; + default: break; } |