On Wed, 19 Feb 2014, Bin.Cheng wrote: > On Wed, Feb 19, 2014 at 10:06 PM, Richard Biener <rguent...@suse.de> wrote: > > On Wed, 19 Feb 2014, Bin.Cheng wrote: > > > >> Hi Richard, > >> Does this have to wait for stage 1? Or I will try to work out a full > >> patch with loop recreating issue fixed. > > > > If it is a regression and there is a bugzilla about it it doesn't > > have to wait. > > > > The patch should be complete (but is untested yet) > > > >> On Wed, Feb 19, 2014 at 7:57 PM, Richard Biener <rguent...@suse.de> wrote: > >> > > >> > This allows cfgcleanup to remove some of the extra CFG that exists > >> > just for loop analysis passes convenience (those can be and are > >> > easily re-created by passes doing loop_optimizer_init ()). > >> > > >> > It may fix a regression uncovered in private communication. > >> It's the regression about the code size checks in > >> gcc.target/arm/ivopts.c and gcc.target/arm/ivopts-2.c > > > > I see. So it is a regression then. > OK, I will file a PR about it. > > > > >> > > >> > Untested - my original idea how to fix this (tree_forwarder_block_p > >> > hunk) ran into the issue in remove_forwarder_block which causes > >> > loops to be removed / re-discovered (losing meta-data). > >> > > >> > Richard. > >> > > >> > 2014-02-19 Richard Biener <rguent...@suse.de> > >> > > >> > * tree-cfgcleanup.c (tree_forwarder_block_p): Protect > >> > latches and preheaders only if requested. > >> > (remove_forwarder_block): Update loop structure if we > >> > removed a forwarder that is a loop latch. > >> > > >> > Index: gcc/tree-cfgcleanup.c > >> > =================================================================== > >> > *** gcc/tree-cfgcleanup.c (revision 207878) > >> > --- gcc/tree-cfgcleanup.c (working copy) > >> > *************** tree_forwarder_block_p (basic_block bb, > >> > *** 307,321 **** > >> > > >> > if (current_loops) > >> > { > >> > ! basic_block dest; > >> > ! /* Protect loop latches, headers and preheaders. */ > >> > if (bb->loop_father->header == bb) > >> > return false; > >> > - dest = EDGE_SUCC (bb, 0)->dest; > >> > > >> > ! if (dest->loop_father->header == dest) > >> > return false; > >> > } > >> > return true; > >> > } > >> > > >> > --- 307,324 ---- > >> > > >> > if (current_loops) > >> > { > >> > ! /* Protect loop headers. */ > >> > if (bb->loop_father->header == bb) > >> > return false; > >> > > >> > ! /* Protect loop latches and preheaders if requested. */ > >> > ! basic_block dest = EDGE_SUCC (bb, 0)->dest; > >> > ! if (dest->loop_father->header == dest > >> > ! && (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS) > >> > ! || loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES))) > >> > return false; > >> > } > >> Sorry for being nit-picking here. There is a scenario that bb is > >> pre-header and loop prop is set to (!LOOPS_HAVE_PREHEADERS && > >> LOOPS_HAVE_SIMPLE_LATCHES). Of course, this may not happen anyway. > > > > Yeah, but then we'd have to detect whether this is a preheader > > forwarder or a latch forwarder. I doubt it happens right now > > so I thought it doesn't matter to do it like above. > > > >> > + > >> > return true; > >> > } > >> > > >> > *************** remove_forwarder_block (basic_block bb) > >> > *** 497,503 **** > >> > set_immediate_dominator (CDI_DOMINATORS, dest, dom); > >> > } > >> > > >> > ! /* And kill the forwarder block. */ > >> > delete_basic_block (bb); > >> > > >> > return true; > >> > --- 500,511 ---- > >> > set_immediate_dominator (CDI_DOMINATORS, dest, dom); > >> > } > >> > > >> > ! /* And kill the forwarder block, but first adjust its parent loop > >> > ! latch info as otherwise the cfg hook has a hard time not to > >> > ! kill the loop. */ > >> > ! if (current_loops > >> > ! && bb->loop_father->latch == bb) > >> > ! bb->loop_father->latch = dest; > >> > delete_basic_block (bb); > >> By this code, do you mean to prevent cfgcleanup from > >> removing/rebuilding the loop struct? > > > > Yes. It prevents triggering cfghooks.c: > > > > void > > delete_basic_block (basic_block bb) > > { > > ... > > /* If we remove the header or the latch of a loop, mark the loop for > > removal by setting its header and latch to NULL. */ > > if (loop->latch == bb > > || loop->header == bb) > > { > > loop->header = NULL; > > loop->latch = NULL; > > loops_state_set (LOOPS_NEED_FIXUP); > > > > generally delete_basic_block has too little context to work out > > anything more specific than the above (so it's a very bad tool ;)) > > Well, it can't. From what I observed, it is pass_ch that modifies the > loop header with some specific control flow graph. Doesn't matter if > the LOOPS_NEED_FIXUP is set before pass_ch, since it calls > loop_optimizer_init to fix loop structure before starting work. In > another word, pass_ch always starts with LOOPS_NEED_FIXUP cleared. > > I will do further investigation on pass_ch.
Ok. With a latent bug in replace_uses_by fixed the patch passed bootstrap & regtest on x86_64-unknown-linux-gnu for me with the following regressions: FAIL: gcc.dg/tree-prof/crossmodule-indircall-1.c execution, -fprofile-use -D_ PROFILE_USE FAIL: gcc.dg/tree-prof/update-loopch.c scan-tree-dump-not optimized "Invalid sum " FAIL: gcc.dg/tree-ssa/pr21417.c scan-tree-dump-times dom2 "Threaded jump" 1 FAIL: gcc.dg/tree-ssa/pr21559.c scan-tree-dump-times vrp1 "Threaded jump" 2 FAIL: gnat.dg/renaming5.adb scan-tree-dump-times optimized "goto" 3 you've already fixed crossmodule-indircall-1.c and pr21417.c is due to (several) overly conservative bail-outs in jump-threading (can be fixed by computing loops with pre-headers in DOM or by fixing those bail-outs). Richard.