diff options
author | Jeff Law <law@redhat.com> | 2005-06-13 17:24:47 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2005-06-13 17:24:47 -0600 |
commit | a513fe886b1dba3d2c9ed39fd633c35de45ddd4b (patch) | |
tree | 8a76829140490cc690c7da63ffdce7aaa8e1f9a6 /gcc/tree-vrp.c | |
parent | 2b5554f3c0d84b54c5863e8054bd68fd367cdc4a (diff) | |
download | gcc-a513fe886b1dba3d2c9ed39fd633c35de45ddd4b.zip gcc-a513fe886b1dba3d2c9ed39fd633c35de45ddd4b.tar.gz gcc-a513fe886b1dba3d2c9ed39fd633c35de45ddd4b.tar.bz2 |
tree-ssa-dom.c (simplify_rhs_and_lookup_avail_expr): No longer simplify DIV, MOD or ABS expressions using VRP information.
* tree-ssa-dom.c (simplify_rhs_and_lookup_avail_expr): No longer
simplify DIV, MOD or ABS expressions using VRP information.
Remove WALK_DATA parameter. Prototype and all callers updated.
(eliminate_redundant_computations): Remove WALK_DATA parameter.
Prototype and all callers updated.
(optimize_stmt): WALK_DATA parameter is now unused.
* tree-vrp.c (local_fold): New function. Like fold, but
strips useless type conversions in the result.
(simplify_using_ranges): New function, largely cribbed from
tree-ssa-dom.c::simplify_rhs_and_lookup_avail_expr.
(vrp_finalize): Call simplify_using_ranges.
* gcc.dg/tree-ssa/20030807-10.c: VRP is now expected to
perform the desired transformations.
* gcc.dg/tree-ssa/20030806-6.c: Similarly.
* gcc.dg/tree-ssa/20040514-2.c: Similarly.
From-SVN: r100909
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 35f78f4..89dae4b 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -94,6 +94,21 @@ static sbitmap blocks_visited; of values that SSA name N_I may take. */ static value_range_t **vr_value; +/* 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; +} + /* Given a comparison code, return its opposite. Note that this is *not* the same as inverting its truth value (invert_tree_comparison). Here we just want to literally flip the comparison around. @@ -3402,6 +3417,124 @@ varying: return SSA_PROP_VARYING; } +/* Walk through the IL simplifying expressions using knowledge + gathered by VRP. */ + +static void +simplify_using_ranges (void) +{ + basic_block bb; + + FOR_EACH_BB (bb) + { + block_stmt_iterator bsi; + + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + + if (TREE_CODE (stmt) == MODIFY_EXPR) + { + tree rhs = TREE_OPERAND (stmt, 1); + enum tree_code rhs_code = TREE_CODE (rhs); + + /* Transform TRUNC_DIV_EXPR and TRUNC_MOD_EXPR into RSHIFT_EXPR + and BIT_AND_EXPR respectively if the first operand is greater + than zero and the second operand is an exact power of two. */ + if ((rhs_code == TRUNC_DIV_EXPR || rhs_code == TRUNC_MOD_EXPR) + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0))) + && integer_pow2p (TREE_OPERAND (rhs, 1))) + { + tree val = NULL; + tree op = TREE_OPERAND (rhs, 0); + value_range_t *vr = get_value_range (TREE_OPERAND (rhs, 0)); + + if (TYPE_UNSIGNED (TREE_TYPE (op))) + { + val = integer_one_node; + } + else + { + val = compare_range_with_value (GT_EXPR, vr, + integer_zero_node); + } + + if (val && integer_onep (val)) + { + tree t; + tree op0 = TREE_OPERAND (rhs, 0); + tree op1 = TREE_OPERAND (rhs, 1); + + if (rhs_code == TRUNC_DIV_EXPR) + t = build (RSHIFT_EXPR, TREE_TYPE (op0), op0, + build_int_cst (NULL_TREE, tree_log2 (op1))); + else + t = build (BIT_AND_EXPR, TREE_TYPE (op0), op0, + local_fold (build (MINUS_EXPR, + TREE_TYPE (op1), + op1, + integer_one_node))); + + TREE_OPERAND (stmt, 1) = t; + update_stmt (stmt); + } + + } + + /* Transform ABS (X) into X or -X as appropriate. */ + if (rhs_code == ABS_EXPR + && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0)))) + { + tree val = NULL; + tree op = TREE_OPERAND (rhs, 0); + tree type = TREE_TYPE (op); + value_range_t *vr = get_value_range (TREE_OPERAND (rhs, 0)); + + if (TYPE_UNSIGNED (type)) + { + val = integer_zero_node; + } + else if (vr) + { + val = compare_range_with_value (LE_EXPR, vr, + integer_zero_node); + if (!val) + { + val = compare_range_with_value (GE_EXPR, vr, + integer_zero_node); + + if (val) + { + if (integer_zerop (val)) + val = integer_one_node; + else if (integer_onep (val)) + val = integer_zero_node; + } + } + + if (val + && (integer_onep (val) || integer_zerop (val))) + { + tree t; + + if (integer_onep (val)) + t = build1 (NEGATE_EXPR, TREE_TYPE (op), op); + else + t = op; + + TREE_OPERAND (stmt, 1) = t; + update_stmt (stmt); + } + } + } + } + + /* TODO. Simplify conditionals. */ + } + } +} + /* Traverse all the blocks folding conditionals with known ranges. */ @@ -3445,6 +3578,12 @@ vrp_finalize (void) substitute_and_fold (single_val_range, true); + /* One could argue all simplifications should be done here + rather than using substitute_and_fold since this code + is going to have to perform a complete walk through the + IL anyway. */ + simplify_using_ranges (); + /* Free allocated memory. */ for (i = 0; i < num_ssa_names; i++) if (vr_value[i]) |