summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-30 07:14:39 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-30 07:14:39 +0000
commit614c1fd706c3b4b237759beb6983e24eb52f6a23 (patch)
treed9bb6788e6323d712f0199315f1b13c2a591f53f /gcc
parent5a3d4fbb02ef88fd054364575bd0c78af7ba5a86 (diff)
downloadgcc-614c1fd706c3b4b237759beb6983e24eb52f6a23.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71935 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/mips/mips-protos.h2
-rw-r--r--gcc/config/mips/mips.c23
-rw-r--r--gcc/config/mips/mips.md72
4 files changed, 85 insertions, 27 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c2f690187e8..78531d31642 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index d057d17111a..3e3e414ad53 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -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);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 7fcab39b367..a2232f0c0df 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2749,30 +2749,27 @@ mips_output_move (rtx dest, rtx src)
abort ();
}
-/* 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;
}
-
/* Make normal rtx_code into something we can index from an array */
static enum internal_test
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 61aeead6eb6..1b184ac11fe 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -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")])
@@ -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")])