OSDN Git Service

* ifcvt.c (dead_or_predicable): Disable if-conversion when
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Oct 2011 10:36:00 +0000 (10:36 +0000)
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Oct 2011 10:36:00 +0000 (10:36 +0000)
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
gcc/ifcvt.c

index 960b79b..8a0f6ef 100644 (file)
@@ -1,5 +1,8 @@
 2011-10-15  Alan Modra  <amodra@gmail.com>
 
+       * 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.
 
index 272cbb7..fee3532 100644 (file)
@@ -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 (&reg_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: