OSDN Git Service

PR optimization/12345
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Sep 2003 07:14:39 +0000 (07:14 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Sep 2003 07:14:39 +0000 (07:14 +0000)
* config/mips/mips-protos.h (mips_restore_gp): Remove.
(mips_gp_save_slot): Declare.
* config/mips/mips.c (mips_restore_gp): Remove in favor of...
(mips_gp_save_slot): ...this new function.
* config/mips/mips.md (exception_receiver): Use mips_gp_save_slot
and mips_output_move to generate the output template.
(call_internal): Force splitting if TARGET_SPLIT_CALLS.  Don't emit
a gp load after a noreturn call.  Load the gp using a move rather
than an exception_receiver pattern.
(call_value_internal, call_value_multiple_internal): Likewise.
(call_split, call_value_split, call_value_multiple_split): Clobber $28.

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

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

index c2f6901..78531d3 100644 (file)
@@ -1,3 +1,18 @@
+2003-09-30  Richard Sandiford  <rsandifo@redhat.com>
+
+       PR optimization/12345
+       * config/mips/mips-protos.h (mips_restore_gp): Remove.
+       (mips_gp_save_slot): Declare.
+       * config/mips/mips.c (mips_restore_gp): Remove in favor of...
+       (mips_gp_save_slot): ...this new function.
+       * config/mips/mips.md (exception_receiver): Use mips_gp_save_slot
+       and mips_output_move to generate the output template.
+       (call_internal): Force splitting if TARGET_SPLIT_CALLS.  Don't emit
+       a gp load after a noreturn call.  Load the gp using a move rather
+       than an exception_receiver pattern.
+       (call_value_internal, call_value_multiple_internal): Likewise.
+       (call_split, call_value_split, call_value_multiple_split): Clobber $28.
+
 2003-09-30  Carlo Wood  <carlo@alinoe.com>
 
        PR debug/12319
index d057d17..3e3e414 100644 (file)
@@ -61,7 +61,7 @@ extern rtx mips_subword (rtx, int);
 extern bool mips_split_64bit_move_p (rtx, rtx);
 extern void mips_split_64bit_move (rtx, rtx);
 extern const char *mips_output_move (rtx, rtx);
-extern const char *mips_restore_gp (rtx *);
+extern rtx mips_gp_save_slot (void);
 #ifdef RTX_CODE
 extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *);
 extern void gen_conditional_branch (rtx *, enum rtx_code);
index 7fcab39..a2232f0 100644 (file)
@@ -2749,30 +2749,27 @@ mips_output_move (rtx dest, rtx src)
   abort ();
 }
 \f
-/* Return instructions to restore the global pointer from the stack,
-   assuming TARGET_ABICALLS.  Used by exception_receiver to set up
-   the GP for exception handlers.
+/* Return an rtx for the gp save slot.  Valid only when using o32 or
+   o64 abicalls.  */
 
-   OPERANDS is an array of operands whose contents are undefined
-   on entry.  */
-
-const char *
-mips_restore_gp (rtx *operands)
+rtx
+mips_gp_save_slot (void)
 {
   rtx loc;
 
-  operands[0] = pic_offset_table_rtx;
+  if (!TARGET_ABICALLS || TARGET_NEWABI)
+    abort ();
+
   if (frame_pointer_needed)
     loc = hard_frame_pointer_rtx;
   else
     loc = stack_pointer_rtx;
   loc = plus_constant (loc, current_function_outgoing_args_size);
-  operands[1] = gen_rtx_MEM (ptr_mode, loc);
-
-  return mips_output_move (operands[0], operands[1]);
+  loc = gen_rtx_MEM (Pmode, loc);
+  RTX_UNCHANGING_P (loc) = 1;
+  return loc;
 }
 \f
-\f
 /* Make normal rtx_code into something we can index from an array */
 
 static enum internal_test
index 61aeead..1b184ac 100644 (file)
@@ -8228,7 +8228,11 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
   [(set (reg:SI 28)
        (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))]
   "TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)"
-  { return mips_restore_gp (operands); }
+{
+  operands[0] = pic_offset_table_rtx;
+  operands[1] = mips_gp_save_slot ();
+  return mips_output_move (operands[0], operands[1]);
+}
   [(set_attr "type"   "load")
    (set_attr "length" "8")])
 \f
@@ -8317,17 +8321,55 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
   DONE;
 })
 
+;; This instruction directly corresponds to an assembly-language "jal".
+;; There are four cases:
+;;
+;;    - -mno-abicalls:
+;;       Both symbolic and register destinations are OK.  The pattern
+;;       always expands to a single mips instruction.
+;;
+;;    - -mabicalls/-mno-explicit-relocs:
+;;       Again, both symbolic and register destinations are OK.
+;;       The call is treated as a multi-instruction black box.
+;;
+;;    - -mabicalls/-mexplicit-relocs with n32 or n64:
+;;       Only "jal $25" is allowed.  This expands to a single "jalr $25"
+;;       instruction.
+;;
+;;    - -mabicalls/-mexplicit-relocs with o32 or o64:
+;;       Only "jal $25" is allowed.  The call is actually two instructions:
+;;       "jalr $25" followed by an insn to reload $gp.
+;;
+;; In the last case, we can generate the individual instructions with
+;; a define_split.  There are several things to be wary of:
+;;
+;;   - We can't expose the load of $gp before reload.  If we did,
+;;     it might get removed as dead, but reload can introduce new
+;;     uses of $gp by rematerializing constants.
+;;
+;;   - We shouldn't restore $gp after calls that never return.
+;;     It isn't valid to insert instructions between a noreturn
+;;     call and the following barrier.
+;;
+;;   - The splitter deliberately changes the liveness of $gp.  The unsplit
+;;     instruction preserves $gp and so have no effect on its liveness.
+;;     But once we generate the separate insns, it becomes obvious that
+;;     $gp is not live on entry to the call.
+;;
+;; ??? The operands[2] = insn check is a hack to make the original insn
+;; available to the splitter.
 (define_insn_and_split "call_internal"
   [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S"))
         (match_operand 1 "" ""))
    (clobber (reg:SI 31))]
   ""
-  "%*jal\t%0%/"
-  "reload_completed && TARGET_SPLIT_CALLS"
+  { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%0%/"; }
+  "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
   [(const_int 0)]
 {
   emit_call_insn (gen_call_split (operands[0], operands[1]));
-  emit_insn (gen_exception_receiver ());
+  if (!find_reg_note (operands[2], REG_NORETURN, 0))
+    emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ());
   DONE;
 }
   [(set_attr "jal" "indirect,direct")
@@ -8337,7 +8379,7 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
   [(call (mem:SI (match_operand 0 "call_insn_operand" "c"))
         (match_operand 1 "" ""))
    (clobber (reg:SI 31))
-   (const_int 1)]
+   (clobber (reg:SI 28))]
   "TARGET_SPLIT_CALLS"
   "%*jalr\t%0%/"
   [(set_attr "type" "call")])
@@ -8354,19 +8396,21 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
   DONE;
 })
 
+;; See comment for call_internal.
 (define_insn_and_split "call_value_internal"
   [(set (match_operand 0 "register_operand" "=df,df")
         (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
               (match_operand 2 "" "")))
    (clobber (reg:SI 31))]
   ""
-  "%*jal\t%1%/"
-  "reload_completed && TARGET_SPLIT_CALLS"
+  { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; }
+  "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
   [(const_int 0)]
 {
   emit_call_insn (gen_call_value_split (operands[0], operands[1],
                                        operands[2]));
-  emit_insn (gen_exception_receiver ());
+  if (!find_reg_note (operands[3], REG_NORETURN, 0))
+    emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ());
   DONE;
 }
   [(set_attr "jal" "indirect,direct")
@@ -8377,11 +8421,12 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
         (call (mem:SI (match_operand 1 "call_insn_operand" "c"))
               (match_operand 2 "" "")))
    (clobber (reg:SI 31))
-   (const_int 1)]
+   (clobber (reg:SI 28))]
   "TARGET_SPLIT_CALLS"
   "%*jalr\t%1%/"
   [(set_attr "type" "call")])
 
+;; See comment for call_internal.
 (define_insn_and_split "call_value_multiple_internal"
   [(set (match_operand 0 "register_operand" "=df,df")
         (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
@@ -8391,13 +8436,14 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
              (match_dup 2)))
    (clobber (reg:SI 31))]
   ""
-  "%*jal\t%1%/"
-  "reload_completed && TARGET_SPLIT_CALLS"
+  { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; }
+  "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)"
   [(const_int 0)]
 {
   emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1],
                                                 operands[2], operands[3]));
-  emit_insn (gen_exception_receiver ());
+  if (!find_reg_note (operands[4], REG_NORETURN, 0))
+    emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ());
   DONE;
 }
   [(set_attr "jal" "indirect,direct")
@@ -8411,7 +8457,7 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
        (call (mem:SI (match_dup 1))
              (match_dup 2)))
    (clobber (reg:SI 31))
-   (const_int 1)]
+   (clobber (reg:SI 28))]
   "TARGET_SPLIT_CALLS"
   "%*jalr\t%1%/"
   [(set_attr "type" "call")])