From 23e025db703c84f0f22c667faff15d4ac2b86e64 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 14 Jun 2016 12:20:04 +0200 Subject: [PATCH] re PR tree-optimization/71520 (Missing cross-jumping of switch cases) PR tree-optimization/71520 * tree-ssa-tail-merge.c (find_duplicate): Handle labels. (replace_block_by): Move user labels from bb1 to bb2. * gcc.dg/tree-ssa/pr71520.c: New test. From-SVN: r237427 --- gcc/ChangeLog | 6 ++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/tree-ssa/pr71520.c | 90 +++++++++++++++++++++++++ gcc/tree-ssa-tail-merge.c | 35 ++++++++++ 4 files changed, 136 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71520.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 40e60a3db34..1a3e5fdd907 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-06-14 Jakub Jelinek + + PR tree-optimization/71520 + * tree-ssa-tail-merge.c (find_duplicate): Handle labels. + (replace_block_by): Move user labels from bb1 to bb2. + 2016-06-14 Richard Biener PR middle-end/71310 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8763aad7556..a61661455e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-14 Jakub Jelinek + + PR tree-optimization/71520 + * gcc.dg/tree-ssa/pr71520.c: New test. + 2016-06-14 Richard Biener PR tree-optimization/71521 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71520.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71520.c new file mode 100644 index 00000000000..f647a5bfe04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71520.c @@ -0,0 +1,90 @@ +/* PR tree-optimization/71520 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar (int); + +void +foo (int x) +{ + switch (x) + { + case 1: + case 12: + case 28: + case 174: + bar (1); + bar (2); + break; + case 3: + case 7: + case 78: + case 96: + case 121: + default: + bar (3); + bar (4); + bar (5); + bar (6); + break; + case 8: + case 13: + case 27: + case 19: + case 118: + bar (3); + bar (4); + bar (5); + bar (6); + break; + case 4: + bar (7); + break; + } +} + +void +baz (int x) +{ + switch (x) + { + case 1: + case 12: + case 28: + case 174: + bar (8); + bar (9); + break; + case 3: + case 7: + case 78: + case 96: + case 121: + default: + lab1: + lab2: + bar (10); + bar (11); + bar (12); + bar (13); + break; + case 8: + case 13: + case 27: + case 19: + case 118: + lab3: + lab4: + bar (10); + bar (11); + bar (12); + bar (13); + break; + case 4: + bar (14); + break; + } +} + +/* { dg-final { scan-tree-dump-times "bar \\\(3\\\);" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "bar \\\(10\\\);" 1 "optimized" } } */ diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index 3df41fd08fc..042d9646b74 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -1265,6 +1265,10 @@ find_duplicate (same_succ *same_succ, basic_block bb1, basic_block bb2) gimple *stmt1 = gsi_stmt (gsi1); gimple *stmt2 = gsi_stmt (gsi2); + if (gimple_code (stmt1) == GIMPLE_LABEL + && gimple_code (stmt2) == GIMPLE_LABEL) + break; + if (!gimple_equal_p (same_succ, stmt1, stmt2)) return; @@ -1277,6 +1281,20 @@ find_duplicate (same_succ *same_succ, basic_block bb1, basic_block bb2) gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2, &vuse_escaped); } + while (!gsi_end_p (gsi1) && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL) + { + tree label = gimple_label_label (as_a (gsi_stmt (gsi1))); + if (DECL_NONLOCAL (label) || FORCED_LABEL (label)) + return; + gsi_prev (&gsi1); + } + while (!gsi_end_p (gsi2) && gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL) + { + tree label = gimple_label_label (as_a (gsi_stmt (gsi2))); + if (DECL_NONLOCAL (label) || FORCED_LABEL (label)) + return; + gsi_prev (&gsi2); + } if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2))) return; @@ -1555,6 +1573,23 @@ replace_block_by (basic_block bb1, basic_block bb2) e2->probability = GCOV_COMPUTE_SCALE (e2->count, out_sum); } + /* Move over any user labels from bb1 after the bb2 labels. */ + gimple_stmt_iterator gsi1 = gsi_start_bb (bb1); + if (!gsi_end_p (gsi1) && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL) + { + gimple_stmt_iterator gsi2 = gsi_after_labels (bb2); + while (!gsi_end_p (gsi1) + && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL) + { + tree label = gimple_label_label (as_a (gsi_stmt (gsi1))); + gcc_assert (!DECL_NONLOCAL (label) && !FORCED_LABEL (label)); + if (DECL_ARTIFICIAL (label)) + gsi_next (&gsi1); + else + gsi_move_before (&gsi1, &gsi2); + } + } + /* Clear range info from all stmts in BB2 -- this transformation could make them out of date. */ reset_flow_sensitive_info_in_bb (bb2); -- 2.30.2