In the covering message for the shrink-wrap patch I said:

  Perhaps the only subtle thing is the handling of call-clobbered base
  registers.  The idea is to emit the initialising main_pool pattern in
  both early_mach -- at the very beginning of the function -- and in the
  prologue.  Then, if shrink-wrapping is used, the one added by early_mach
  will still be the first in the function.  If shrink-wrapping isn't used
  then the one added by the prologue will be the first in the function.
  s390_mainpool_start then deletes whichever isn't needed.

And as so often, the "subtle" bit wasn't really well thought out.
Having an extra unspec_volatile main_pool instruction until md_reorg
unnecessarily constrained the second scheduling pass.  This caused a
regression in some internal benchmarking.

When the base register is call-clobbered and can be set and used
anywhere in the function, there's no real need to emit it before
md_reorg.  The patch below therefore defers it until then.

Tested on s390x-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
        * config/s390/s390.c (s390_mainpool_start): Emit the main_pool
        instruction at the start of the function if the base register is
        call-clobbered.  Revert 2014-02-07 change.
        (s390_early_mach): Don't initialize the base register here.
        (s390_emit_prologue): Only initialize the base register if it
        is call-saved.
        (s300_extra_live_on_entry): New function.
        (TARGET_EXTRA_LIVE_ON_ENTRY): Define.

Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c      2014-02-07 14:56:19.205859847 +0000
+++ gcc/config/s390/s390.c      2014-02-13 12:49:55.756293247 +0000
@@ -6668,20 +6668,21 @@ s390_mainpool_start (void)
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
+      /* If the base register is call-clobbered, output the initializing
+        instruction at the start of the function.  */
+      if (!pool->pool_insn
+         && NONDEBUG_INSN_P (insn)
+         && cfun->machine->base_reg
+         && call_really_used_regs[REGNO (cfun->machine->base_reg)])
+       pool->pool_insn
+         = emit_insn_before (gen_main_pool (cfun->machine->base_reg), insn);
+
       if (NONJUMP_INSN_P (insn)
          && GET_CODE (PATTERN (insn)) == SET
          && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
          && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
        {
-         /* There might be two main_pool instructions if base_reg
-            is call-clobbered; one for shrink-wrapped code and one
-            for the rest.  We want to keep the first.  */
-         if (pool->pool_insn)
-           {
-             insn = PREV_INSN (insn);
-             delete_insn (NEXT_INSN (insn));
-             continue;
-           }
+         gcc_assert (!pool->pool_insn);
          pool->pool_insn = insn;
        }
 
@@ -8643,11 +8644,6 @@ s390_early_mach (void)
   /* Re-compute register info.  */
   s390_register_info ();
 
-  /* If we're using a base register, ensure that it is always valid for
-     the first non-prologue instruction.  */
-  if (cfun->machine->base_reg)
-    emit_insn_at_entry (gen_main_pool (cfun->machine->base_reg));
-
   /* Annotate all constant pool references to let the scheduler know
      they implicitly use the base register.  */
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -8728,7 +8724,8 @@ s390_emit_prologue (void)
 
   /* Dummy insn to mark literal pool slot.  */
 
-  if (cfun->machine->base_reg)
+  if (cfun->machine->base_reg
+      && !call_really_used_regs[REGNO (cfun->machine->base_reg)])
     emit_insn (gen_main_pool (cfun->machine->base_reg));
 
   offset = cfun_frame_layout.f0_offset;
@@ -9183,6 +9180,19 @@ s390_emit_epilogue (bool sibcall)
     }
 }
 
+/* Implement TARGET_EXTRA_LIVE_ON_ENTRY.  */
+
+static void
+s300_extra_live_on_entry (bitmap regs)
+{
+  /* If the base register is call-clobbered, the main_pool instruction
+     should go at the beginning of the function.  We only add it during
+     md_reorg.  */
+  if (cfun->machine->base_reg
+      && call_really_used_regs[REGNO (cfun->machine->base_reg)])
+    bitmap_set_bit (regs, REGNO (cfun->machine->base_reg));
+}
+
 /* Implement TARGET_SET_UP_BY_PROLOGUE.  */
 
 static void
@@ -12230,6 +12240,9 @@ #define TARGET_ATTRIBUTE_TABLE s390_attr
 #undef TARGET_CAN_INLINE_P
 #define TARGET_CAN_INLINE_P s390_can_inline_p
 
+#undef TARGET_EXTRA_LIVE_ON_ENTRY
+#define TARGET_EXTRA_LIVE_ON_ENTRY s300_extra_live_on_entry
+
 #undef TARGET_SET_UP_BY_PROLOGUE
 #define TARGET_SET_UP_BY_PROLOGUE s300_set_up_by_prologue
 

Reply via email to