aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-04-14 13:53:35 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-04-14 13:53:35 +0000
commit7b4cae1b530c88b2e723c5cf621ceb5cb97183b5 (patch)
tree879cbb3e2f547759d82534d22cd3800c96ceb24c /gcc
parent4116e7d0e0cd33503b5968808ef6e6edc987d816 (diff)
downloadgcc-7b4cae1b530c88b2e723c5cf621ceb5cb97183b5.zip
gcc-7b4cae1b530c88b2e723c5cf621ceb5cb97183b5.tar.gz
gcc-7b4cae1b530c88b2e723c5cf621ceb5cb97183b5.tar.bz2
tree-ssa-forwprop.c (simplify_gimple_switch): Enhance check for which sign-changes we allow when...
2014-04-14 Richard Biener <rguenther@suse.de> * 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. From-SVN: r209372
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C24
-rw-r--r--gcc/tree-ssa-forwprop.c55
4 files changed, 59 insertions, 30 deletions
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 <rguenther@suse.de>
+
+ * 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 <ebotcazou@adacore.com>
* 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 <rguenther@suse.de>
+
+ * g++.dg/tree-ssa/forwprop-switch.C: New testcase.
+
2014-04-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* 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);