diff options
Diffstat (limited to 'gcc-4.9/gcc/tree-ssa-forwprop.c')
-rw-r--r-- | gcc-4.9/gcc/tree-ssa-forwprop.c | 55 |
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); |