http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52285
Steven Bosscher <steven at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED CC|steven at gcc dot gnu.org | AssignedTo|unassigned at gcc dot |steven at gcc dot gnu.org |gnu.org | --- Comment #10 from Steven Bosscher <steven at gcc dot gnu.org> 2012-11-13 10:30:27 UTC --- There are several reasons why RTL LIM cannot currently hoist the (frame) rtx. The first is that in general it stays away from any HARD_REGISTER_P reg with a 10-foot pole. For most hard registers this is probably a good strategy: Anything that's in a "real" hard register at this point is there for a reason (function return, global reg, whatever) and almost certainly not invariant in a loop. Second, RTL LIM only hoists expression that can be assigned to the original SET_DEST of a single set. In the case of this PR, the insn in case is: ;; UD chains for insn luid 2 uid 15 ;; reg 20 { } ;; reg 63 { d2(bb 4 insn 12) } (insn 15 12 16 4 (set (reg:CCZ 17 flags) (compare:CCZ (reg/v/f:DI 63 [ p ]) (reg/f:DI 20 frame))) PR52285.c:10 8 {*cmpdi_1} (nil)) This fails in may_assign_reg_p because (reg:CCZ 17) can't be assigned to (it is a hard register, and I suppose it has class NO_REGS), so the SET_SRC is not even considered by find_invariant_insn as a potential invariant. I think this condition can be relaxed with something like, Index: loop-invariant.c =================================================================== --- loop-invariant.c (revision 193454) +++ loop-invariant.c (working copy) @@ -874,11 +874,11 @@ dest = SET_DEST (set); if (!REG_P (dest) - || HARD_REGISTER_P (dest)) + || HARD_REGISTER_P (dest) + || !may_assign_reg_p (dest)) simple = false; - if (!may_assign_reg_p (SET_DEST (set)) - || !check_maybe_invariant (SET_SRC (set))) + if (!check_maybe_invariant (SET_SRC (set))) return; /* If the insn can throw exception, ... Finally, RTL LIM cannot hoist parts of expressions. It only hoists the SET_SRC as a whole, or nothing at all. I have patches for that, originally developed to hoist addresses out of MEMs. I'll dust them off and see if I can make it handle "(reg:frame + CONST_INT)" and other expressions that involve eliminable regs.