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
This commit is contained in:
parent
3c44a3c4b7
commit
573850d4cb
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")])
|
||||
|
|
Loading…
Reference in New Issue