aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc-4.9/gcc/tree-ssa-forwprop.c55
1 files changed, 25 insertions, 30 deletions
diff --git a/gcc-4.9/gcc/tree-ssa-forwprop.c b/gcc-4.9/gcc/tree-ssa-forwprop.c
index b22942900..b6bedfea6 100644
--- a/gcc-4.9/gcc/tree-ssa-forwprop.c
+++ b/gcc-4.9/gcc/tree-ssa-forwprop.c
@@ -1356,43 +1356,38 @@ simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
static bool
simplify_gimple_switch (gimple stmt)
{
- tree cond = gimple_switch_index (stmt);
- tree def, to, ti;
- gimple def_stmt;
-
/* The optimization that we really care about is removing unnecessary
casts. That will let us do much better in propagating the inferred
constant at the switch target. */
+ tree cond = gimple_switch_index (stmt);
if (TREE_CODE (cond) == SSA_NAME)
{
- def_stmt = SSA_NAME_DEF_STMT (cond);
- if (is_gimple_assign (def_stmt))
+ gimple def_stmt = SSA_NAME_DEF_STMT (cond);
+ if (gimple_assign_cast_p (def_stmt))
{
- if (gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
- {
- int need_precision;
- bool fail;
-
- def = gimple_assign_rhs1 (def_stmt);
-
- to = TREE_TYPE (cond);
- ti = TREE_TYPE (def);
-
- /* If we have an extension that preserves value, then we
- can copy the source value into the switch. */
-
- need_precision = TYPE_PRECISION (ti);
- fail = false;
- if (! INTEGRAL_TYPE_P (ti))
- fail = true;
- else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
- fail = true;
- else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
- need_precision += 1;
- if (TYPE_PRECISION (to) < need_precision)
- fail = true;
+ tree def = gimple_assign_rhs1 (def_stmt);
+ if (TREE_CODE (def) != SSA_NAME)
+ return false;
- if (!fail)
+ /* If we have an extension or sign-change that preserves the
+ values we check against then we can copy the source value into
+ the switch. */
+ tree ti = TREE_TYPE (def);
+ if (INTEGRAL_TYPE_P (ti)
+ && TYPE_PRECISION (ti) <= TYPE_PRECISION (TREE_TYPE (cond)))
+ {
+ size_t n = gimple_switch_num_labels (stmt);
+ tree min = NULL_TREE, max = NULL_TREE;
+ if (n > 1)
+ {
+ min = CASE_LOW (gimple_switch_label (stmt, 1));
+ if (CASE_HIGH (gimple_switch_label (stmt, n - 1)))
+ max = CASE_HIGH (gimple_switch_label (stmt, n - 1));
+ else
+ max = CASE_LOW (gimple_switch_label (stmt, n - 1));
+ }
+ if ((!min || int_fits_type_p (min, ti))
+ && (!max || int_fits_type_p (max, ti)))
{
gimple_switch_set_index (stmt, def);
simplify_gimple_switch_label_vec (stmt, ti);