------- Comment #20 from steven at gcc dot gnu dot org 2009-02-13 07:44 ------- Re: "Moving loop invariants out of this loop might help if it detected as a loop, but I don't know how to check whether it is." (Comment #19):
It's not like there will not be any loop invariant code motion (LICM) at all anymore if the RTL LICM pass is disabled. There is an LICM pass on GIMPLE, and there is also PRE for GIMPLE (and lazy code motion for RTL but I think it disables itself for your test case). The RTL LICM pass mostly cleans up after expand, i.e. moves things that are not exposed in GIMPLE. This is mostly just address calculations. I think Zdenek is right in Comment #17. LICM on big loops probably does more harm than good. Still, randomly disabling RTL LICM on big loops, when we do nothing about the other LICM-like passes, looks like a hack to me and not like a permanent solution. There are a couple more ways to fix the problem (ISTR I've listed them before somewhere...): 1. Stop using the DF UD chains and build them locally only. This is not something I would like much, but clearly there is something with the DF chains that consumes too many resources. 2. Figure out why *only* RTL LICM has a big problem with the DF chains for this test case. Why does fwprop work? Does it shut down itself somehow? Is fwprop asking only for UD chains for pseudos and LICM also for hardregs, perhaps? 3. Make RTL FUD chains work. Shame on me for being unable so far to make that work. Not 4.4 material. 4. Poor-man's-FUD: For CFGs with many basic blocks and a large join-split point (like the block that holds the factored computed goto), add a no-op move for all live registers for which a valid reg-reg move instruction is available. This effectively splits the UD chains, and the no-op moves would be cleaned up later (during RA, or maybe earlier). Just to see if it works, I want to give the poor-man's-FUD option a try with Brad's smaller test case. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39157