gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Feb 2014 14:52:26 +0000 (14:52 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Feb 2014 14:52:26 +0000 (14:52 +0000)
* config/s390/s390-protos.h (s390_can_use_simple_return_insn)
(s390_can_use_return_insn): Declare.
* config/s390/s390.h (EPILOGUE_USES): Define.
* config/s390/s390.c (s390_mainpool_start): Allow two main_pool
instructions.
(s390_chunkify_start): Handle return JUMP_LABELs.
(s390_early_mach): Emit a main_pool instruction on the entry edge.
(s300_set_up_by_prologue, s390_can_use_simple_return_insn)
(s390_can_use_return_insn): New functions.
(s390_fix_long_loop_prediction): Handle conditional returns.
(TARGET_SET_UP_BY_PROLOGUE): Define.
* config/s390/s390.md (ANY_RETURN): New code iterator.
(*creturn, *csimple_return, return, simple_return): New patterns.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207605 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index 0d0f887..5703bb5 100644 (file)
@@ -1,5 +1,21 @@
 2014-02-07  Richard Sandiford  <rsandifo@linux.vnet.ibm.com>
 
+       * config/s390/s390-protos.h (s390_can_use_simple_return_insn)
+       (s390_can_use_return_insn): Declare.
+       * config/s390/s390.h (EPILOGUE_USES): Define.
+       * config/s390/s390.c (s390_mainpool_start): Allow two main_pool
+       instructions.
+       (s390_chunkify_start): Handle return JUMP_LABELs.
+       (s390_early_mach): Emit a main_pool instruction on the entry edge.
+       (s300_set_up_by_prologue, s390_can_use_simple_return_insn)
+       (s390_can_use_return_insn): New functions.
+       (s390_fix_long_loop_prediction): Handle conditional returns.
+       (TARGET_SET_UP_BY_PROLOGUE): Define.
+       * config/s390/s390.md (ANY_RETURN): New code iterator.
+       (*creturn, *csimple_return, return, simple_return): New patterns.
+
+2014-02-07  Richard Sandiford  <rsandifo@linux.vnet.ibm.com>
+
        * config/s390/s390.c (s390_restore_gprs_from_fprs): Add REG_CFA_RESTORE
        notes to each restore.  Also add REG_CFA_DEF_CFA when restoring %r15.
        (s390_optimize_prologue): Don't clear RTX_FRAME_RELATED_P.  Update the
index 72f8bb7..9bd08fa 100644 (file)
@@ -36,6 +36,8 @@ extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment);
 extern HOST_WIDE_INT s390_initial_elimination_offset (int, int);
 extern void s390_emit_prologue (void);
 extern void s390_emit_epilogue (bool);
+extern bool s390_can_use_simple_return_insn (void);
+extern bool s390_can_use_return_insn (void);
 extern void s390_function_profiler (FILE *, int);
 extern void s390_set_has_landing_pad_p (bool);
 extern bool s390_hard_regno_mode_ok (unsigned int, enum machine_mode);
index 2d6f8d0..993ed84 100644 (file)
@@ -6673,7 +6673,15 @@ s390_mainpool_start (void)
          && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
          && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
        {
-         gcc_assert (!pool->pool_insn);
+         /* 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;
+           }
          pool->pool_insn = insn;
        }
 
@@ -7110,7 +7118,7 @@ s390_chunkify_start (void)
          if (GET_CODE (pat) == SET)
            {
              rtx label = JUMP_LABEL (insn);
-             if (label)
+             if (label && !ANY_RETURN_P (label))
                {
                  if (s390_find_pool (pool_list, label)
                      != s390_find_pool (pool_list, insn))
@@ -8635,6 +8643,11 @@ 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))
@@ -9170,6 +9183,55 @@ s390_emit_epilogue (bool sibcall)
     }
 }
 
+/* Implement TARGET_SET_UP_BY_PROLOGUE.  */
+
+static void
+s300_set_up_by_prologue (hard_reg_set_container *regs)
+{
+  if (cfun->machine->base_reg
+      && !call_really_used_regs[REGNO (cfun->machine->base_reg)])
+    SET_HARD_REG_BIT (regs->set, REGNO (cfun->machine->base_reg));
+}
+
+/* Return true if the function can use simple_return to return outside
+   of a shrink-wrapped region.  At present shrink-wrapping is supported
+   in all cases.  */
+
+bool
+s390_can_use_simple_return_insn (void)
+{
+  return true;
+}
+
+/* Return true if the epilogue is guaranteed to contain only a return
+   instruction and if a direct return can therefore be used instead.
+   One of the main advantages of using direct return instructions
+   is that we can then use conditional returns.  */
+
+bool
+s390_can_use_return_insn (void)
+{
+  int i;
+
+  if (!reload_completed)
+    return false;
+
+  if (crtl->profile)
+    return false;
+
+  if (TARGET_TPF_PROFILING)
+    return false;
+
+  for (i = 0; i < 16; i++)
+    if (cfun_gpr_save_slot (i))
+      return false;
+
+  if (cfun->machine->base_reg
+      && !call_really_used_regs[REGNO (cfun->machine->base_reg)])
+    return false;
+
+  return cfun_frame_layout.frame_size == 0;
+}
 
 /* Return the size in bytes of a function argument of
    type TYPE and/or mode MODE.  At least one of TYPE or
@@ -11019,6 +11081,11 @@ s390_fix_long_loop_prediction (rtx insn)
       || GET_CODE (SET_SRC(set)) != IF_THEN_ELSE)
     return false;
 
+  /* Skip conditional returns.  */
+  if (ANY_RETURN_P (XEXP (SET_SRC (set), 1))
+      && XEXP (SET_SRC (set), 2) == pc_rtx)
+    return false;
+
   label_ref = (GET_CODE (XEXP (SET_SRC (set), 1)) == LABEL_REF ?
               XEXP (SET_SRC (set), 1) : XEXP (SET_SRC (set), 2));
 
@@ -12163,6 +12230,9 @@ s390_option_override (void)
 #undef TARGET_CAN_INLINE_P
 #define TARGET_CAN_INLINE_P s390_can_inline_p
 
+#undef TARGET_SET_UP_BY_PROLOGUE
+#define TARGET_SET_UP_BY_PROLOGUE s300_set_up_by_prologue
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-s390.h"
index 9099fc8..2f2139e 100644 (file)
@@ -878,6 +878,10 @@ do {                                                                       \
   fputc ('\n', (FILE));                                                        \
 } while (0)
 
+/* Mark the return register as used by the epilogue so that we can
+   use it in unadorned (return) and (simple_return) instructions.  */
+#define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_REGNUM)
+
 #undef ASM_OUTPUT_FUNCTION_LABEL
 #define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \
   s390_asm_output_function_label (FILE, NAME, DECL)
index 3f86304..76902b5 100644 (file)
 ;; In place of GET_MODE_BITSIZE (<MODE>mode)
 (define_mode_attr bitsize [(DI "64") (SI "32") (HI "16") (QI "8")])
 
+;; Allow return and simple_return to be defined from a single template.
+(define_code_iterator ANY_RETURN [return simple_return])
+
 ;;
 ;;- Compare instructions.
 ;;
    (set_attr "type"  "branch")
    (set_attr "atype" "agen")])
 
+;; A conditional return instruction.
+(define_insn "*c<code>"
+  [(set (pc)
+        (if_then_else
+          (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+          (ANY_RETURN)
+          (pc)))]
+  "s390_can_use_<code>_insn ()"
+  "b%C0r\t%%r14"
+  [(set_attr "op_type" "RR")
+   (set_attr "type"  "jsr")
+   (set_attr "atype" "agen")])
 
 ;;
 ;;- Negated conditional jump instructions.
   ""
   "s390_emit_epilogue (true); DONE;")
 
+;; A direct return instruction, without using an epilogue.
+(define_insn "<code>"
+  [(ANY_RETURN)]
+  "s390_can_use_<code>_insn ()"
+  "br\t%%r14"
+  [(set_attr "op_type" "RR")
+   (set_attr "type"    "jsr")
+   (set_attr "atype"   "agen")])
+
 (define_insn "*return"
   [(return)
    (use (match_operand 0 "register_operand" "a"))]