From 00bffa46a86081cd7c6445bd620c769e32b40e01 Mon Sep 17 00:00:00 2001 From: rguenth Date: Mon, 14 Apr 2014 13:53:35 +0000 Subject: [PATCH] 2014-04-14 Richard Biener * tree-ssa-forwprop.c (simplify_gimple_switch): Enhance check for which sign-changes we allow when forwarding a converted value into a switch. * g++.dg/tree-ssa/forwprop-switch.C: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209372 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 +++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C | 24 +++++++++++ gcc/tree-ssa-forwprop.c | 55 +++++++++++-------------- 4 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bec304..724c5f5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2014-04-14 Richard Biener + + * tree-ssa-forwprop.c (simplify_gimple_switch): Enhance + check for which sign-changes we allow when forwarding + a converted value into a switch. + 2014-04-14 Eric Botcazou * stor-layout.c (place_field): Finalize non-constant offset for the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eb30db9..0a741fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-04-14 Richard Biener + + * g++.dg/tree-ssa/forwprop-switch.C: New testcase. + 2014-04-14 Rainer Orth * gcc.dg/lto/pr55113_0.c: Skip on i?86-*-solaris2.1[0-1]*. diff --git a/gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C b/gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C new file mode 100644 index 0000000..c3f12ac --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-O -fdump-tree-cddce1" } + +enum Scale { E1, E2, E3, E4, E5, E6, E7, E8 }; + +int Test(Scale s) +{ + switch(s) + { + case E1: return 12; + case E2: return 17; + case E3: return 22; + case E4: return 42; + default: break; + } + return 0; +} + +// tree forwprop should have eliminated the (int) s cast for the +// switch value and directly switch on the 's' parameter + +// { dg-final { scan-tree-dump-not "\\\(int\\\)" "cddce1" } } +// { dg-final { scan-tree-dump "switch \\\(s_.\\\(D\\\)\\\)" "cddce1" } } +// { dg-final { cleanup-tree-dump "cddce1" } } diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index b229429..b6bedfe 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/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); -- 2.7.4