From 97ad7daba75127b0d09ce9d64753f8e29eebd091 Mon Sep 17 00:00:00 2001 From: amodra Date: Sat, 15 Oct 2011 10:36:00 +0000 Subject: [PATCH] * ifcvt.c (dead_or_predicable): Disable if-conversion when doing so is likely to kill a shrink-wrapping opportunity. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180028 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 3 +++ gcc/ifcvt.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 960b79b..8a0f6ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,8 @@ 2011-10-15 Alan Modra + * ifcvt.c (dead_or_predicable): Disable if-conversion when + doing so is likely to kill a shrink-wrapping opportunity. + PR rtl-optimization/49941 * jump.c (mark_jump_label_1): Set JUMP_LABEL for simple_return jumps. diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 272cbb7..fee3532 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -4166,6 +4166,64 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, FOR_BB_INSNS (merge_bb, insn) if (NONDEBUG_INSN_P (insn)) df_simulate_find_defs (insn, merge_set); + + /* If shrink-wrapping, disable this optimization when test_bb is + the first basic block and merge_bb exits. The idea is to not + move code setting up a return register as that may clobber a + register used to pass function parameters, which then must be + saved in caller-saved regs. A caller-saved reg requires the + prologue, killing a shrink-wrap opportunity. */ + if ((flag_shrink_wrap && HAVE_simple_return && !epilogue_completed) + && ENTRY_BLOCK_PTR->next_bb == test_bb + && single_succ_p (new_dest) + && single_succ (new_dest) == EXIT_BLOCK_PTR + && bitmap_intersect_p (df_get_live_in (new_dest), merge_set)) + { + regset return_regs; + unsigned int i; + + return_regs = BITMAP_ALLOC (®_obstack); + + /* Start off with the intersection of regs used to pass + params and regs used to return values. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (FUNCTION_ARG_REGNO_P (i) + && targetm.calls.function_value_regno_p (i)) + bitmap_set_bit (return_regs, INCOMING_REGNO (i)); + + bitmap_and_into (return_regs, df_get_live_out (ENTRY_BLOCK_PTR)); + bitmap_and_into (return_regs, df_get_live_in (EXIT_BLOCK_PTR)); + if (!bitmap_empty_p (return_regs)) + { + FOR_BB_INSNS_REVERSE (new_dest, insn) + if (NONDEBUG_INSN_P (insn)) + { + df_ref *def_rec; + unsigned int uid = INSN_UID (insn); + + /* If this insn sets any reg in return_regs.. */ + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref def = *def_rec; + unsigned r = DF_REF_REGNO (def); + + if (bitmap_bit_p (return_regs, r)) + break; + } + /* ..then add all reg uses to the set of regs + we're interested in. */ + if (*def_rec) + df_simulate_uses (insn, return_regs); + } + if (bitmap_intersect_p (merge_set, return_regs)) + { + BITMAP_FREE (return_regs); + BITMAP_FREE (merge_set); + return FALSE; + } + } + BITMAP_FREE (return_regs); + } } no_body: -- 2.7.4