Commit 573850d4 by Richard Sandiford Committed by Richard Sandiford

re PR rtl-optimization/12345 (internal compiler error: verify_flow_info failed)

	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.

From-SVN: r71935
parent 3c44a3c4
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> 2003-09-30 Carlo Wood <carlo@alinoe.com>
PR debug/12319 PR debug/12319
......
...@@ -61,7 +61,7 @@ extern rtx mips_subword (rtx, int); ...@@ -61,7 +61,7 @@ extern rtx mips_subword (rtx, int);
extern bool mips_split_64bit_move_p (rtx, rtx); extern bool mips_split_64bit_move_p (rtx, rtx);
extern void mips_split_64bit_move (rtx, rtx); extern void mips_split_64bit_move (rtx, rtx);
extern const char *mips_output_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 #ifdef RTX_CODE
extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *);
extern void gen_conditional_branch (rtx *, enum rtx_code); extern void gen_conditional_branch (rtx *, enum rtx_code);
......
...@@ -2749,30 +2749,27 @@ mips_output_move (rtx dest, rtx src) ...@@ -2749,30 +2749,27 @@ mips_output_move (rtx dest, rtx src)
abort (); abort ();
} }
/* Return instructions to restore the global pointer from the stack, /* Return an rtx for the gp save slot. Valid only when using o32 or
assuming TARGET_ABICALLS. Used by exception_receiver to set up o64 abicalls. */
the GP for exception handlers.
OPERANDS is an array of operands whose contents are undefined rtx
on entry. */ mips_gp_save_slot (void)
const char *
mips_restore_gp (rtx *operands)
{ {
rtx loc; rtx loc;
operands[0] = pic_offset_table_rtx; if (!TARGET_ABICALLS || TARGET_NEWABI)
abort ();
if (frame_pointer_needed) if (frame_pointer_needed)
loc = hard_frame_pointer_rtx; loc = hard_frame_pointer_rtx;
else else
loc = stack_pointer_rtx; loc = stack_pointer_rtx;
loc = plus_constant (loc, current_function_outgoing_args_size); loc = plus_constant (loc, current_function_outgoing_args_size);
operands[1] = gen_rtx_MEM (ptr_mode, loc); loc = gen_rtx_MEM (Pmode, loc);
RTX_UNCHANGING_P (loc) = 1;
return mips_output_move (operands[0], operands[1]); return loc;
} }
/* Make normal rtx_code into something we can index from an array */ /* Make normal rtx_code into something we can index from an array */
static enum internal_test static enum internal_test
......
...@@ -8228,7 +8228,11 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -8228,7 +8228,11 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
[(set (reg:SI 28) [(set (reg:SI 28)
(unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))]
"TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)" "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 "type" "load")
(set_attr "length" "8")]) (set_attr "length" "8")])
...@@ -8317,17 +8321,55 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -8317,17 +8321,55 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
DONE; 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" (define_insn_and_split "call_internal"
[(call (mem:SI (match_operand 0 "call_insn_operand" "c,S")) [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(clobber (reg:SI 31))] (clobber (reg:SI 31))]
"" ""
"%*jal\t%0%/" { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%0%/"; }
"reload_completed && TARGET_SPLIT_CALLS" "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
[(const_int 0)] [(const_int 0)]
{ {
emit_call_insn (gen_call_split (operands[0], operands[1])); 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; DONE;
} }
[(set_attr "jal" "indirect,direct") [(set_attr "jal" "indirect,direct")
...@@ -8337,7 +8379,7 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -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")) [(call (mem:SI (match_operand 0 "call_insn_operand" "c"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(clobber (reg:SI 31)) (clobber (reg:SI 31))
(const_int 1)] (clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS" "TARGET_SPLIT_CALLS"
"%*jalr\t%0%/" "%*jalr\t%0%/"
[(set_attr "type" "call")]) [(set_attr "type" "call")])
...@@ -8354,19 +8396,21 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -8354,19 +8396,21 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
DONE; DONE;
}) })
;; See comment for call_internal.
(define_insn_and_split "call_value_internal" (define_insn_and_split "call_value_internal"
[(set (match_operand 0 "register_operand" "=df,df") [(set (match_operand 0 "register_operand" "=df,df")
(call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(clobber (reg:SI 31))] (clobber (reg:SI 31))]
"" ""
"%*jal\t%1%/" { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; }
"reload_completed && TARGET_SPLIT_CALLS" "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
[(const_int 0)] [(const_int 0)]
{ {
emit_call_insn (gen_call_value_split (operands[0], operands[1], emit_call_insn (gen_call_value_split (operands[0], operands[1],
operands[2])); 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; DONE;
} }
[(set_attr "jal" "indirect,direct") [(set_attr "jal" "indirect,direct")
...@@ -8377,11 +8421,12 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -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")) (call (mem:SI (match_operand 1 "call_insn_operand" "c"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(clobber (reg:SI 31)) (clobber (reg:SI 31))
(const_int 1)] (clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS" "TARGET_SPLIT_CALLS"
"%*jalr\t%1%/" "%*jalr\t%1%/"
[(set_attr "type" "call")]) [(set_attr "type" "call")])
;; See comment for call_internal.
(define_insn_and_split "call_value_multiple_internal" (define_insn_and_split "call_value_multiple_internal"
[(set (match_operand 0 "register_operand" "=df,df") [(set (match_operand 0 "register_operand" "=df,df")
(call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) (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%/" ...@@ -8391,13 +8436,14 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
(match_dup 2))) (match_dup 2)))
(clobber (reg:SI 31))] (clobber (reg:SI 31))]
"" ""
"%*jal\t%1%/" { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; }
"reload_completed && TARGET_SPLIT_CALLS" "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)"
[(const_int 0)] [(const_int 0)]
{ {
emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1],
operands[2], operands[3])); 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; DONE;
} }
[(set_attr "jal" "indirect,direct") [(set_attr "jal" "indirect,direct")
...@@ -8411,7 +8457,7 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ...@@ -8411,7 +8457,7 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
(call (mem:SI (match_dup 1)) (call (mem:SI (match_dup 1))
(match_dup 2))) (match_dup 2)))
(clobber (reg:SI 31)) (clobber (reg:SI 31))
(const_int 1)] (clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS" "TARGET_SPLIT_CALLS"
"%*jalr\t%1%/" "%*jalr\t%1%/"
[(set_attr "type" "call")]) [(set_attr "type" "call")])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment