On Mon, 13 Jun 2016, Jakub Jelinek wrote: > Hi! > > Cross-jumping at GIMPLE level gives up e.g. because there are any labels > at the beginning of the block (which is always the case for bbs referenced > from switches). While labels for non-local goto as well as computed goto > are hard to handle, after all the edges are then EDGE_ABNORMAL that can't be > redirected anyway, other labels can be handled very easily. > > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for > trunk?
Ok. > In the PR, beyond this I'm also talking about switchconv pass not being able > to know that some cases could be cross-jumped and thus use better conversion > sequences. Wonder if we shouldn't schedule either a full, or a limited > version of tailmerging before switchconv, perhaps just use the > infrastructure from tree-ssa-tail-merge.c to handle the easiest cases > where the cross-jumping in the end would end up simplifying some of the > switches. Thoughts on this? I'd like to postpone this until tail-merging got rid of its SCCVN dependency (the proposed merge with the ICF machinery). I also think that switch-conversion is a bit early in the pipeline, I'd put it not before at least one VRP pass. I know Martin put it in early opts because it can reduce code-size and thus trigger inlining but that can be said about most of the scalar opts we have in the late pipeline as well. Richard. > 2016-06-13 Jakub Jelinek <ja...@redhat.com> > > 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. > > --- gcc/tree-ssa-tail-merge.c.jj 2016-06-10 20:23:55.196164390 +0200 > +++ gcc/tree-ssa-tail-merge.c 2016-06-13 12:08:34.691985005 +0200 > @@ -1265,6 +1265,10 @@ find_duplicate (same_succ *same_succ, ba > 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, ba > 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 <glabel *> (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 <glabel *> (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 > 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 <glabel *> (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); > --- gcc/testsuite/gcc.dg/tree-ssa/pr71520.c.jj 2016-06-13 > 12:26:55.251630020 +0200 > +++ gcc/testsuite/gcc.dg/tree-ssa/pr71520.c 2016-06-13 12:26:31.000000000 > +0200 > @@ -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" } } */ > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)