Message ID | 4D8A09E5.7070105@codesourcery.com |
---|---|
State | New |
Headers | show |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 03/23/11 08:55, Bernd Schmidt wrote: > The first basic block contains insns to move incoming argument registers > to pseudos. When these pseudos live across calls, they get allocated to > call-saved registers. This in turns disables shrink-wrapping, since the > move instruction requires the prologue (saving the call-saved reg) to > occur before it. > > This patch addresses the problem by moving such moves downwards through > the CFG until we find a place where the destination is used or the > incoming argument is clobbered. FWIW, downward motion of the moves out of arg registers (or loads from arg slots) is definitely a good thing. This was a regular source of unnecessary register pressure leading to spills in codes I've looked at. I hope your sinking code works better than the quick and dirty one I wrote but never contributed. jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNigvCAAoJEBRtltQi2kC7/DcH/0OPNnWZD9qoqRwrpm/Zc5qN zaCsSc9VYFuQa5Kh6dTd0md6ORfqSWFt6v0ygOXueYt7/bni4YsEA33N52dp3VVY xg6R0m1XEmfg8Pcn0SzyBGGmAnprgn7XpRnbOLycAT11CjfNFN9jjdeXFYbSHiNu NkvdtiKzz2HeucmvTBEZByN1mhP3/9DeQ3R6MM7uZ9xZFuA4rBfx8wfijxTYEg2d 3T52kiDzqcTBsD6Q5apAtNcFU6X7o1KS/eZsbno+nnMcc4z7lQ+6EQVfnBPfs9m2 GLb4ZNNzYCesczNHM+DyuJfQQVAkECKx0DcAGL8AivffUr9o05l4nGsS5D4Kip8= =gALv -----END PGP SIGNATURE-----
On 03/23/2011 04:03 PM, Jeff Law wrote: > On 03/23/11 08:55, Bernd Schmidt wrote: >> The first basic block contains insns to move incoming argument registers >> to pseudos. When these pseudos live across calls, they get allocated to >> call-saved registers. This in turns disables shrink-wrapping, since the >> move instruction requires the prologue (saving the call-saved reg) to >> occur before it. > >> This patch addresses the problem by moving such moves downwards through >> the CFG until we find a place where the destination is used or the >> incoming argument is clobbered. > FWIW, downward motion of the moves out of arg registers (or loads from > arg slots) is definitely a good thing. This was a regular source of > unnecessary register pressure leading to spills in codes I've looked at. > > I hope your sinking code works better than the quick and dirty one I > wrote but never contributed. Sadly I'm doing it after register allocation, so it wouldn't help with your problem. Bernd
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 03/23/11 09:04, Bernd Schmidt wrote: > On 03/23/2011 04:03 PM, Jeff Law wrote: >> On 03/23/11 08:55, Bernd Schmidt wrote: >>> The first basic block contains insns to move incoming argument registers >>> to pseudos. When these pseudos live across calls, they get allocated to >>> call-saved registers. This in turns disables shrink-wrapping, since the >>> move instruction requires the prologue (saving the call-saved reg) to >>> occur before it. >> >>> This patch addresses the problem by moving such moves downwards through >>> the CFG until we find a place where the destination is used or the >>> incoming argument is clobbered. >> FWIW, downward motion of the moves out of arg registers (or loads from >> arg slots) is definitely a good thing. This was a regular source of >> unnecessary register pressure leading to spills in codes I've looked at. >> >> I hope your sinking code works better than the quick and dirty one I >> wrote but never contributed. > > Sadly I'm doing it after register allocation, so it wouldn't help with > your problem. That'll still help :-) I can run your sinking code, then use the existing IRA callbacks to attempt to allocate any pseudos which didn't previously get hard regs. It's actually quite easy. jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNig9CAAoJEBRtltQi2kC7I3kIAJ6manYH+/ZFcdQwfxroN0im U0Oc18wbEz5VZg3SXnw7wEm6uRPKxYLS9/t2bMo0xLY2cHCWZx2QLH9g9O09lnUv EU5lG46H7oIJuwhuC8osvsJUbLfQL5PkGQJdF4mfab1uk/Et5RSo8wfna7HDhTXU b8WJltvS2ZJQIggSFxXtM101eq2/oiiU286WC8wdqlbq0lgWotBcxhHNuZeO/LEj NeGX91kcFDl8RcwQNeT2a2G+JC0i5tc1S4C3d9pGgUiqDWpmjx74WrlRpzpkF8EF 7kfYm48xY5hPcmUcZ7vJU5Aq3Ik7U2rM6aO9H3dYoFTAOmcgs22Rbj6FoDMrUXE= =N5L7 -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 03/23/11 08:55, Bernd Schmidt wrote: > The first basic block contains insns to move incoming argument registers > to pseudos. When these pseudos live across calls, they get allocated to > call-saved registers. This in turns disables shrink-wrapping, since the > move instruction requires the prologue (saving the call-saved reg) to > occur before it. > > This patch addresses the problem by moving such moves downwards through > the CFG until we find a place where the destination is used or the > incoming argument is clobbered. OK. At some point I'll probably want to move this code to run immediately after IRA completes and extend it in a few ways, but for now it's OK as it stands. jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNlIA5AAoJEBRtltQi2kC7DeIH+weQ1mb1whdL6gD18RmLeBvR cMtbAHMOz6Hyt8vojAjyXEFJtVPGDv9tbr3/GiKZiOamBhXLVy38YCh9dCZDaE/K +sqSCSPSc9/N0poUpeYY/Am5HWp/rBXbY0+vUxnaS3rCTGAiOSrzpw4/VR23MTLN mVTa4lhz4KPifFIigpvGoNS+n1MZkUfeg7CoMXMvVl516bTwuLHB0VcSWV7qud8w E4uIqHngf8k1rSLvGOsRy08a2tXxJBIRolfTI8bYZLFXG9EhsIQnR5e664ySBgyj gVPVBSTT+zpbpkF12f8qJ/PLO1JWZlS7gDTwS+lGhEcWq9hmO3+rP/C5Z7XXsYQ= =ippB -----END PGP SIGNATURE-----
Index: gcc/function.c =================================================================== --- gcc.orig/function.c +++ gcc/function.c @@ -5299,6 +5299,127 @@ requires_stack_frame_p (rtx insn) return true; return false; } + +/* Look for sets of call-saved registers in the first block of the + function, and move them down into successor blocks if the register + is used only on one path. This exposes more opportunities for + shrink-wrapping. + These kinds of sets often occur when incoming argument registers are + moved to call-saved registers because their values are live across + one or more calls during the function. */ + +static void +prepare_shrink_wrap (basic_block entry_block) +{ + rtx insn, curr; + FOR_BB_INSNS_SAFE (entry_block, insn, curr) + { + basic_block next_bb; + edge e, live_edge; + edge_iterator ei; + rtx set, scan; + unsigned destreg, srcreg; + + if (!NONDEBUG_INSN_P (insn)) + continue; + set = single_set (insn); + if (!set) + continue; + + if (!REG_P (SET_SRC (set)) || !REG_P (SET_DEST (set))) + continue; + srcreg = REGNO (SET_SRC (set)); + destreg = REGNO (SET_DEST (set)); + if (hard_regno_nregs[srcreg][GET_MODE (SET_SRC (set))] > 1 + || hard_regno_nregs[destreg][GET_MODE (SET_DEST (set))] > 1) + continue; + + next_bb = entry_block; + scan = insn; + + for (;;) + { + live_edge = NULL; + FOR_EACH_EDGE (e, ei, next_bb->succs) + { + if (REGNO_REG_SET_P (df_get_live_in (e->dest), destreg)) + { + if (live_edge) + { + live_edge = NULL; + break; + } + live_edge = e; + } + } + if (!live_edge) + break; + /* We can sometimes encounter dead code. Don't try to move it + into the exit block. */ + if (live_edge->dest == EXIT_BLOCK_PTR) + break; + if (EDGE_COUNT (live_edge->dest->preds) > 1) + break; + while (scan != BB_END (next_bb)) + { + scan = NEXT_INSN (scan); + if (NONDEBUG_INSN_P (scan)) + { + rtx link; + HARD_REG_SET set_regs; + + CLEAR_HARD_REG_SET (set_regs); + note_stores (PATTERN (scan), record_hard_reg_sets, + &set_regs); + if (CALL_P (scan)) + IOR_HARD_REG_SET (set_regs, call_used_reg_set); + for (link = REG_NOTES (scan); link; link = XEXP (link, 1)) + if (REG_NOTE_KIND (link) == REG_INC) + record_hard_reg_sets (XEXP (link, 0), NULL, &set_regs); + + if (TEST_HARD_REG_BIT (set_regs, srcreg) + || reg_referenced_p (SET_DEST (set), + PATTERN (scan))) + { + scan = NULL_RTX; + break; + } + if (CALL_P (scan)) + { + rtx link = CALL_INSN_FUNCTION_USAGE (scan); + while (link) + { + rtx tmp = XEXP (link, 0); + if (GET_CODE (tmp) == USE + && reg_referenced_p (SET_DEST (set), tmp)) + break; + link = XEXP (link, 1); + } + if (link) + { + scan = NULL_RTX; + break; + } + } + } + } + if (!scan) + break; + next_bb = live_edge->dest; + } + + if (next_bb != entry_block) + { + rtx after = BB_HEAD (next_bb); + while (!NOTE_P (after) + || NOTE_KIND (after) != NOTE_INSN_BASIC_BLOCK) + after = NEXT_INSN (after); + emit_insn_after (PATTERN (insn), after); + delete_insn (insn); + } + } +} + #endif #ifdef HAVE_return @@ -5499,6 +5620,8 @@ thread_prologue_and_epilogue_insns (void bitmap_head bb_antic_flags; bitmap_head bb_on_list; + prepare_shrink_wrap (entry_edge->dest); + bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack); bitmap_initialize (&bb_on_list, &bitmap_default_obstack);