Commit 0c433c31 by Richard Sandiford Committed by Richard Sandiford

mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.

gcc/
	* config/mips/mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.
	(mips_cprestore_address_p): Likewise.
	(mips_save_gp_to_cprestore_slot): Likewise.
	(mips_restore_gp): Rename to...
	(mips_restore_gp_from_cprestore_slot): ...this.
	(mips_must_initialize_gp_p): Declare.
	(mips_emit_save_slot_move): Likewise.
	(mips_output_load_label): Return nothing.
	(mips_eh_uses): Declare.
	* config/mips/mips.h (TARGET_SPLIT_CALLS): Require epilogue_completed.
	(TARGET_CPRESTORE_DIRECTIVE): New macro.
	(TARGET_ABSOLUTE_JUMPS): Likewise.
	(EH_USES): Likewise.
	(FIRST_PSEUDO_REGISTER): Update comment.
	(MIPS_ABSOLUTE_JUMP): New macro, extracted from...
	(MIPS_CALL): ...here.
	(REGISTER_NAMES): Add $cprestore.
	* config/mips/mips.c (machine_function): Remove has_gp_insn_p.
	Add load_label_length, has_inflexible_gp_insn_p,
	has_flexible_gp_insn_p, must_initialize_gp_p and
	must_restore_gp_when_clobbered_p.
	(mips_expand_call): Don't generate split instructions here.
	(mips_split_call): Update the call to mips_restore_gp after
	the above name change.
	(mips16_cfun_returns_in_fpr_p): Move earlier in file.
	(mips_find_gp_ref): New function.
	(mips_insn_has_inflexible_gp_ref_p): Likewise.
	(mips_cfun_has_inflexible_gp_ref_p): Likewise.
	(mips_insn_has_flexible_gp_ref_p): Likewise.
	(mips_cfun_has_flexible_gp_ref_p): Likewise.
	(mips_function_has_gp_insn): Delete.
	(mips_global_pointer): Drop the df_regs_ever_live_p check.
	Use the new functions above.  Only return INVALID_REGNUM
	for TARGET_ABSOLUTE_JUMPS.
	(mips_must_initialize_gp_p): New function.
	(mips_get_cprestore_base_and_offset): New function, extracted from...
	(mips_cprestore_slot): ...here.  Take a bool parameter.
	(mips_cfun_has_cprestore_slot_p): New function.
	(mips_cprestore_address_p): Likewise.
	(mips_save_gp_to_cprestore_slot): Likewise.
	(mips_restore_gp): Rename to...
	(mips_restore_gp_from_cprestore_slot): ...this.  Assert
	epilogue_completed.  Update the call to mips_cprestore_slot.
	Test cfun->machine->must_restore_gp_when_clobbered_p.
	(mips_direct_save_slot_move_p): New function.
	(mips_emit_save_slot_move): Likewise.
	(mips_output_cplocal): Test mips_must_initialize_gp_p () instead
	of cfun->machine->global_pointer.
	(mips_output_function_prologue): Check mips_must_initialize_gp_p ().
	(mips_save_reg): Use mips_emit_save_slot_move.
	(mips_expand_prologue): Set must_initialize_gp_p.
	Use mips_cfun_has_cprestore_slot_p.  Use gen_potential_cprestore
	for all cprestore saves.  Emit a use_cprestore instruction after
	setting up the cprestore slot.
	(mips_restore_reg): Use mips_emit_save_slot_move.
	(mips_process_load_label): New function.
	(mips_load_label_length): Likewise.
	(mips_output_load_label): Don't return asm: output it here instead.
	Use mips_process_load_label.
	(mips_adjust_insn_length): Adjust the length of branch instructions
	that have length MAX_PIC_BRANCH_LENGTH.
	(mips_output_conditional_branch): Update the call to
	mips_output_load_label.  Assume the branch target is OPERANDS[0]
	rather than OPERANDS[1].  Use MIPS_ABSOLUTE_JUMP for absolute jumps.
	(mips_output_order_conditional_branch): Swap the meaning of
	OPERANDS[0] and OPERANDS[1].
	(mips_variable_issue): Don't count ghost instructions.
	(mips_expand_ghost_gp_insns): New function.
	(mips_reorg): Rerun mips_reorg_process_insns if it returns true.
	(mips_output_mi_thunk): Set must_initialize_gp_p.
	(mips_eh_uses): New function.
	* config/mips/predicates.md (cprestore_save_slot_operand)
	(cprestore_load_slot_operand): New predicates.
	* config/mips/mips.md (UNSPEC_POTENTIAL_CPRESTORE): New unspec.
	(UNSPEC_MOVE_GP): Likewise.
	(UNSPEC_CPRESTORE, UNSPEC_RESTORE_GP, UNSPEC_EH_RETURN)
	(UNSPEC_CONSTTABLE_INT, UNSPEC_CONSTTABLE_FLOAT): Bump to make room.
	(CPRESTORE_SLOT_REGNUM): New register.
	(MAX_PIC_BRANCH_LENGTH): New constant.
	(jal_macro): Use MIPS_ABSOLUTE_JUMPS.
	(length): Use MAX_PIC_BRANCH_LENGTH as a placeholder for PIC long
	branches.  Fix commentary.
	(loadgp_newabi_<mode>): Change from unspec_volatile to unspec.
	Only split if mips_must_initialize_gp_p; expand to nothing otherwise.
	Change type to "ghost".
	(loadgp_absolute_<mode>): Likewise.
	(loadgp_rtp_<mode>): Likewise.
	(copygp_mips16): Likewise.
	(loadgp_blockage): Remove redundant mode attribute.
	(potential_cprestore): New instruction.
	(cprestore): Turn into an unspec set.
	(use_cprestore): New instruction.
	(*branch_fp): Swap operands 0 and 1.  Remove redundant mode attribute.
	(*branch_fp_inverted): Likewise.
	(*branch_order<mode>): Likewise.
	(*branch_order<mode>_inverted): Likewise.
	(*branch_equality<mode>): Likewise.
	(*branch_equality<mode>_inverted): Likewise.
	(*branch_bit<bbv><mode>): Likewise.
	(*branch_bit<bbv><mode>_inverted): Likewise.
	(*branch_equality<mode>_mips16): Remove redundant mode.
	(jump): Turn into a define_expand.
	(*jump_absolute): New instruction.
	(*jump_pic): Likewise.
	(*jump_mips16): Rename previously-unnamed pattern.  Remove
	redundant mode attribute.
	(restore_gp): Split on epilogue_completed rather than
	reload_completed.  Change type to "ghost".
	(move_gp<mode>): New instruction.
	* config/mips/mips-dsp.md (mips_bposge): Swap operands 0 and 1.
	Remove redundant mode attribute.
	* config/mips/mips-ps-3d.md (bc1any4t): Likewise.
	(bc1any4f, bc1any2t, bc1any2f): Likewise.
	(*branch_upper_lower, *branch_upper_lower_inverted): Likewise.

gcc/testsuite/
	* gcc.target/mips/branch-helper.h: New file.
	* gcc.target/mips/branch-2.c,
	* gcc.target/mips/branch-3.c,
	* gcc.target/mips/branch-4.c,
	* gcc.target/mips/branch-5.c,
	* gcc.target/mips/branch-6.c,
	* gcc.target/mips/branch-7.c,
	* gcc.target/mips/branch-8.c,
	* gcc.target/mips/branch-9.c,
	* gcc.target/mips/branch-10.c,
	* gcc.target/mips/branch-11.c,
	* gcc.target/mips/branch-12.c,
	* gcc.target/mips/branch-13.c,
	* gcc.target/mips/branch-14.c,
	* gcc.target/mips/branch-15.c: New tests.

From-SVN: r151695
parent af0b8d73
2009-09-14 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.
(mips_cprestore_address_p): Likewise.
(mips_save_gp_to_cprestore_slot): Likewise.
(mips_restore_gp): Rename to...
(mips_restore_gp_from_cprestore_slot): ...this.
(mips_must_initialize_gp_p): Declare.
(mips_emit_save_slot_move): Likewise.
(mips_output_load_label): Return nothing.
(mips_eh_uses): Declare.
* config/mips/mips.h (TARGET_SPLIT_CALLS): Require epilogue_completed.
(TARGET_CPRESTORE_DIRECTIVE): New macro.
(TARGET_ABSOLUTE_JUMPS): Likewise.
(EH_USES): Likewise.
(FIRST_PSEUDO_REGISTER): Update comment.
(MIPS_ABSOLUTE_JUMP): New macro, extracted from...
(MIPS_CALL): ...here.
(REGISTER_NAMES): Add $cprestore.
* config/mips/mips.c (machine_function): Remove has_gp_insn_p.
Add load_label_length, has_inflexible_gp_insn_p,
has_flexible_gp_insn_p, must_initialize_gp_p and
must_restore_gp_when_clobbered_p.
(mips_expand_call): Don't generate split instructions here.
(mips_split_call): Update the call to mips_restore_gp after
the above name change.
(mips16_cfun_returns_in_fpr_p): Move earlier in file.
(mips_find_gp_ref): New function.
(mips_insn_has_inflexible_gp_ref_p): Likewise.
(mips_cfun_has_inflexible_gp_ref_p): Likewise.
(mips_insn_has_flexible_gp_ref_p): Likewise.
(mips_cfun_has_flexible_gp_ref_p): Likewise.
(mips_function_has_gp_insn): Delete.
(mips_global_pointer): Drop the df_regs_ever_live_p check.
Use the new functions above. Only return INVALID_REGNUM
for TARGET_ABSOLUTE_JUMPS.
(mips_must_initialize_gp_p): New function.
(mips_get_cprestore_base_and_offset): New function, extracted from...
(mips_cprestore_slot): ...here. Take a bool parameter.
(mips_cfun_has_cprestore_slot_p): New function.
(mips_cprestore_address_p): Likewise.
(mips_save_gp_to_cprestore_slot): Likewise.
(mips_restore_gp): Rename to...
(mips_restore_gp_from_cprestore_slot): ...this. Assert
epilogue_completed. Update the call to mips_cprestore_slot.
Test cfun->machine->must_restore_gp_when_clobbered_p.
(mips_direct_save_slot_move_p): New function.
(mips_emit_save_slot_move): Likewise.
(mips_output_cplocal): Test mips_must_initialize_gp_p () instead
of cfun->machine->global_pointer.
(mips_output_function_prologue): Check mips_must_initialize_gp_p ().
(mips_save_reg): Use mips_emit_save_slot_move.
(mips_expand_prologue): Set must_initialize_gp_p.
Use mips_cfun_has_cprestore_slot_p. Use gen_potential_cprestore
for all cprestore saves. Emit a use_cprestore instruction after
setting up the cprestore slot.
(mips_restore_reg): Use mips_emit_save_slot_move.
(mips_process_load_label): New function.
(mips_load_label_length): Likewise.
(mips_output_load_label): Don't return asm: output it here instead.
Use mips_process_load_label.
(mips_adjust_insn_length): Adjust the length of branch instructions
that have length MAX_PIC_BRANCH_LENGTH.
(mips_output_conditional_branch): Update the call to
mips_output_load_label. Assume the branch target is OPERANDS[0]
rather than OPERANDS[1]. Use MIPS_ABSOLUTE_JUMP for absolute jumps.
(mips_output_order_conditional_branch): Swap the meaning of
OPERANDS[0] and OPERANDS[1].
(mips_variable_issue): Don't count ghost instructions.
(mips_expand_ghost_gp_insns): New function.
(mips_reorg): Rerun mips_reorg_process_insns if it returns true.
(mips_output_mi_thunk): Set must_initialize_gp_p.
(mips_eh_uses): New function.
* config/mips/predicates.md (cprestore_save_slot_operand)
(cprestore_load_slot_operand): New predicates.
* config/mips/mips.md (UNSPEC_POTENTIAL_CPRESTORE): New unspec.
(UNSPEC_MOVE_GP): Likewise.
(UNSPEC_CPRESTORE, UNSPEC_RESTORE_GP, UNSPEC_EH_RETURN)
(UNSPEC_CONSTTABLE_INT, UNSPEC_CONSTTABLE_FLOAT): Bump to make room.
(CPRESTORE_SLOT_REGNUM): New register.
(MAX_PIC_BRANCH_LENGTH): New constant.
(jal_macro): Use MIPS_ABSOLUTE_JUMPS.
(length): Use MAX_PIC_BRANCH_LENGTH as a placeholder for PIC long
branches. Fix commentary.
(loadgp_newabi_<mode>): Change from unspec_volatile to unspec.
Only split if mips_must_initialize_gp_p; expand to nothing otherwise.
Change type to "ghost".
(loadgp_absolute_<mode>): Likewise.
(loadgp_rtp_<mode>): Likewise.
(copygp_mips16): Likewise.
(loadgp_blockage): Remove redundant mode attribute.
(potential_cprestore): New instruction.
(cprestore): Turn into an unspec set.
(use_cprestore): New instruction.
(*branch_fp): Swap operands 0 and 1. Remove redundant mode attribute.
(*branch_fp_inverted): Likewise.
(*branch_order<mode>): Likewise.
(*branch_order<mode>_inverted): Likewise.
(*branch_equality<mode>): Likewise.
(*branch_equality<mode>_inverted): Likewise.
(*branch_bit<bbv><mode>): Likewise.
(*branch_bit<bbv><mode>_inverted): Likewise.
(*branch_equality<mode>_mips16): Remove redundant mode.
(jump): Turn into a define_expand.
(*jump_absolute): New instruction.
(*jump_pic): Likewise.
(*jump_mips16): Rename previously-unnamed pattern. Remove
redundant mode attribute.
(restore_gp): Split on epilogue_completed rather than
reload_completed. Change type to "ghost".
(move_gp<mode>): New instruction.
* config/mips/mips-dsp.md (mips_bposge): Swap operands 0 and 1.
Remove redundant mode attribute.
* config/mips/mips-ps-3d.md (bc1any4t): Likewise.
(bc1any4f, bc1any2t, bc1any2f): Likewise.
(*branch_upper_lower, *branch_upper_lower_inverted): Likewise.
2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com> 2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/41210 PR target/41210
......
...@@ -1102,11 +1102,10 @@ ...@@ -1102,11 +1102,10 @@
(define_insn "mips_bposge" (define_insn "mips_bposge"
[(set (pc) [(set (pc)
(if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM) (if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM)
(match_operand:SI 0 "immediate_operand" "I")) (match_operand:SI 1 "immediate_operand" "I"))
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"ISA_HAS_DSP" "ISA_HAS_DSP"
"%*bposge%0\t%1%/" "%*bposge%1\t%0%/"
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
...@@ -219,7 +219,10 @@ extern rtx mips_subword (rtx, bool); ...@@ -219,7 +219,10 @@ extern rtx mips_subword (rtx, bool);
extern bool mips_split_64bit_move_p (rtx, rtx); extern bool mips_split_64bit_move_p (rtx, rtx);
extern void mips_split_doubleword_move (rtx, rtx); extern void mips_split_doubleword_move (rtx, rtx);
extern const char *mips_output_move (rtx, rtx); extern const char *mips_output_move (rtx, rtx);
extern void mips_restore_gp (rtx); extern bool mips_cfun_has_cprestore_slot_p (void);
extern bool mips_cprestore_address_p (rtx, bool);
extern void mips_save_gp_to_cprestore_slot (rtx, rtx, rtx, rtx);
extern void mips_restore_gp_from_cprestore_slot (rtx);
#ifdef RTX_CODE #ifdef RTX_CODE
extern void mips_expand_scc (rtx *); extern void mips_expand_scc (rtx *);
extern void mips_expand_conditional_branch (rtx *); extern void mips_expand_conditional_branch (rtx *);
...@@ -276,7 +279,9 @@ extern bool mips_small_data_pattern_p (rtx); ...@@ -276,7 +279,9 @@ extern bool mips_small_data_pattern_p (rtx);
extern rtx mips_rewrite_small_data (rtx); extern rtx mips_rewrite_small_data (rtx);
extern HOST_WIDE_INT mips_initial_elimination_offset (int, int); extern HOST_WIDE_INT mips_initial_elimination_offset (int, int);
extern rtx mips_return_addr (int, rtx); extern rtx mips_return_addr (int, rtx);
extern bool mips_must_initialize_gp_p (void);
extern enum mips_loadgp_style mips_current_loadgp_style (void); extern enum mips_loadgp_style mips_current_loadgp_style (void);
extern void mips_emit_save_slot_move (rtx, rtx, rtx);
extern void mips_expand_prologue (void); extern void mips_expand_prologue (void);
extern void mips_expand_before_return (void); extern void mips_expand_before_return (void);
extern void mips_expand_epilogue (bool); extern void mips_expand_epilogue (bool);
...@@ -296,7 +301,7 @@ extern int mips_register_move_cost (enum machine_mode, enum reg_class, ...@@ -296,7 +301,7 @@ extern int mips_register_move_cost (enum machine_mode, enum reg_class,
enum reg_class); enum reg_class);
extern int mips_adjust_insn_length (rtx, int); extern int mips_adjust_insn_length (rtx, int);
extern const char *mips_output_load_label (void); extern void mips_output_load_label (rtx);
extern const char *mips_output_conditional_branch (rtx, rtx *, const char *, extern const char *mips_output_conditional_branch (rtx, rtx *, const char *,
const char *); const char *);
extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool); extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool);
...@@ -334,6 +339,7 @@ extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs, ...@@ -334,6 +339,7 @@ extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs,
extern void mips_expand_vector_init (rtx, rtx); extern void mips_expand_vector_init (rtx, rtx);
extern bool mips_eh_uses (unsigned int);
extern bool mips_epilogue_uses (unsigned int); extern bool mips_epilogue_uses (unsigned int);
extern void mips_final_prescan_insn (rtx, rtx *, int); extern void mips_final_prescan_insn (rtx, rtx *, int);
......
...@@ -439,50 +439,46 @@ ...@@ -439,50 +439,46 @@
; Branch on Any of Four Floating Point Condition Codes True ; Branch on Any of Four Floating Point Condition Codes True
(define_insn "bc1any4t" (define_insn "bc1any4t"
[(set (pc) [(set (pc)
(if_then_else (ne (match_operand:CCV4 0 "register_operand" "z") (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
(const_int 0)) (const_int 0))
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any4t\t%0,%1%/" "%*bc1any4t\t%1,%0%/"
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
; Branch on Any of Four Floating Point Condition Codes False ; Branch on Any of Four Floating Point Condition Codes False
(define_insn "bc1any4f" (define_insn "bc1any4f"
[(set (pc) [(set (pc)
(if_then_else (ne (match_operand:CCV4 0 "register_operand" "z") (if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
(const_int -1)) (const_int -1))
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any4f\t%0,%1%/" "%*bc1any4f\t%1,%0%/"
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
; Branch on Any of Two Floating Point Condition Codes True ; Branch on Any of Two Floating Point Condition Codes True
(define_insn "bc1any2t" (define_insn "bc1any2t"
[(set (pc) [(set (pc)
(if_then_else (ne (match_operand:CCV2 0 "register_operand" "z") (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
(const_int 0)) (const_int 0))
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any2t\t%0,%1%/" "%*bc1any2t\t%1,%0%/"
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
; Branch on Any of Two Floating Point Condition Codes False ; Branch on Any of Two Floating Point Condition Codes False
(define_insn "bc1any2f" (define_insn "bc1any2f"
[(set (pc) [(set (pc)
(if_then_else (ne (match_operand:CCV2 0 "register_operand" "z") (if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
(const_int -1)) (const_int -1))
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any2f\t%0,%1%/" "%*bc1any2f\t%1,%0%/"
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
; Used to access one register in a CCV2 pair. Operand 0 is the register ; Used to access one register in a CCV2 pair. Operand 0 is the register
; pair and operand 1 is the index of the register we want (a CONST_INT). ; pair and operand 1 is the index of the register we want (a CONST_INT).
...@@ -497,45 +493,43 @@ ...@@ -497,45 +493,43 @@
(define_insn "*branch_upper_lower" (define_insn "*branch_upper_lower"
[(set (pc) [(set (pc)
(if_then_else (if_then_else
(match_operator 0 "equality_operator" (match_operator 1 "equality_operator"
[(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
(match_operand 3 "const_int_operand")] (match_operand 3 "const_int_operand")]
UNSPEC_SINGLE_CC) UNSPEC_SINGLE_CC)
(const_int 0)]) (const_int 0)])
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_HARD_FLOAT" "TARGET_HARD_FLOAT"
{ {
operands[2] operands[2]
= gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
return mips_output_conditional_branch (insn, operands, return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%F0", "%2,%1"), MIPS_BRANCH ("b%F1", "%2,%0"),
MIPS_BRANCH ("b%W0", "%2,%1")); MIPS_BRANCH ("b%W1", "%2,%0"));
} }
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
; As above, but with the sense of the condition reversed. ; As above, but with the sense of the condition reversed.
(define_insn "*branch_upper_lower_inverted" (define_insn "*branch_upper_lower_inverted"
[(set (pc) [(set (pc)
(if_then_else (if_then_else
(match_operator 0 "equality_operator" (match_operator 1 "equality_operator"
[(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
(match_operand 3 "const_int_operand")] (match_operand 3 "const_int_operand")]
UNSPEC_SINGLE_CC) UNSPEC_SINGLE_CC)
(const_int 0)]) (const_int 0)])
(pc) (pc)
(label_ref (match_operand 1 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"TARGET_HARD_FLOAT" "TARGET_HARD_FLOAT"
{ {
operands[2] operands[2]
= gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
return mips_output_conditional_branch (insn, operands, return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%W0", "%2,%1"), MIPS_BRANCH ("b%W1", "%2,%0"),
MIPS_BRANCH ("b%F0", "%2,%1")); MIPS_BRANCH ("b%F1", "%2,%0"));
} }
[(set_attr "type" "branch") [(set_attr "type" "branch")])
(set_attr "mode" "none")])
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
; Floating Point Reduced Precision Reciprocal Square Root Instructions. ; Floating Point Reduced Precision Reciprocal Square Root Instructions.
......
...@@ -161,10 +161,13 @@ enum mips_code_readable_setting { ...@@ -161,10 +161,13 @@ enum mips_code_readable_setting {
/* True if the call patterns should be split into a jalr followed by /* True if the call patterns should be split into a jalr followed by
an instruction to restore $gp. It is only safe to split the load an instruction to restore $gp. It is only safe to split the load
from the call when every use of $gp is explicit. */ from the call when every use of $gp is explicit.
See mips_must_initialize_gp_p for details about how we manage the
global pointer. */
#define TARGET_SPLIT_CALLS \ #define TARGET_SPLIT_CALLS \
(TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP) (TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP && epilogue_completed)
/* True if we're generating a form of -mabicalls in which we can use /* True if we're generating a form of -mabicalls in which we can use
operators like %hi and %lo to refer to locally-binding symbols. operators like %hi and %lo to refer to locally-binding symbols.
...@@ -202,6 +205,17 @@ enum mips_code_readable_setting { ...@@ -202,6 +205,17 @@ enum mips_code_readable_setting {
/* True if TARGET_USE_GOT and if $gp is a call-saved register. */ /* True if TARGET_USE_GOT and if $gp is a call-saved register. */
#define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP) #define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP)
/* True if we should use .cprestore to store to the cprestore slot.
We continue to use .cprestore for explicit-reloc code so that JALs
inside inline asms will work correctly. */
#define TARGET_CPRESTORE_DIRECTIVE \
(TARGET_ABICALLS_PIC2 && !TARGET_MIPS16)
/* True if we can use the J and JAL instructions. */
#define TARGET_ABSOLUTE_JUMPS \
(!flag_pic || TARGET_ABSOLUTE_ABICALLS)
/* True if indirect calls must use register class PIC_FN_ADDR_REG. /* True if indirect calls must use register class PIC_FN_ADDR_REG.
This is true for both the PIC and non-PIC VxWorks RTP modes. */ This is true for both the PIC and non-PIC VxWorks RTP modes. */
#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP) #define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
...@@ -1300,6 +1314,8 @@ enum mips_code_readable_setting { ...@@ -1300,6 +1314,8 @@ enum mips_code_readable_setting {
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3) #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
#define EH_USES(N) mips_eh_uses (N)
/* Offsets recorded in opcodes are a multiple of this alignment factor. /* Offsets recorded in opcodes are a multiple of this alignment factor.
The default for this in 64-bit mode is 8, which causes problems with The default for this in 64-bit mode is 8, which causes problems with
SFmode register saves. */ SFmode register saves. */
...@@ -1543,11 +1559,12 @@ enum mips_code_readable_setting { ...@@ -1543,11 +1559,12 @@ enum mips_code_readable_setting {
- 8 condition code registers - 8 condition code registers
- 2 accumulator registers (hi and lo) - 2 accumulator registers (hi and lo)
- 32 registers each for coprocessors 0, 2 and 3 - 32 registers each for coprocessors 0, 2 and 3
- 3 fake registers: - 4 fake registers:
- ARG_POINTER_REGNUM - ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM - FRAME_POINTER_REGNUM
- GOT_VERSION_REGNUM (see the comment above load_call<mode> for details) - GOT_VERSION_REGNUM (see the comment above load_call<mode> for details)
- 3 dummy entries that were used at various times in the past. - CPRESTORE_SLOT_REGNUM
- 2 dummy entries that were used at various times in the past.
- 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
- 6 DSP control registers */ - 6 DSP control registers */
...@@ -2661,6 +2678,13 @@ typedef struct mips_args { ...@@ -2661,6 +2678,13 @@ typedef struct mips_args {
#define MIPS_BRANCH(OPCODE, OPERANDS) \ #define MIPS_BRANCH(OPCODE, OPERANDS) \
"%*" OPCODE "%?\t" OPERANDS "%/" "%*" OPCODE "%?\t" OPERANDS "%/"
/* Return an asm string that forces INSN to be treated as an absolute
J or JAL instruction instead of an assembler macro. */
#define MIPS_ABSOLUTE_JUMP(INSN) \
(TARGET_ABICALLS_PIC2 \
? ".option\tpic0\n\t" INSN "\n\t.option\tpic2" \
: INSN)
/* Return the asm template for a call. INSN is the instruction's mnemonic /* Return the asm template for a call. INSN is the instruction's mnemonic
("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number ("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number
of the target. of the target.
...@@ -2675,11 +2699,7 @@ typedef struct mips_args { ...@@ -2675,11 +2699,7 @@ typedef struct mips_args {
? "%*" INSN "\t%" #OPNO "%/" \ ? "%*" INSN "\t%" #OPNO "%/" \
: REG_P (OPERANDS[OPNO]) \ : REG_P (OPERANDS[OPNO]) \
? "%*" INSN "r\t%" #OPNO "%/" \ ? "%*" INSN "r\t%" #OPNO "%/" \
: TARGET_ABICALLS_PIC2 \ : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/"))
? (".option\tpic0\n\t" \
"%*" INSN "\t%" #OPNO "%/\n\t" \
".option\tpic2") \
: "%*" INSN "\t%" #OPNO "%/")
/* Control the assembler format that we output. */ /* Control the assembler format that we output. */
...@@ -2707,7 +2727,7 @@ typedef struct mips_args { ...@@ -2707,7 +2727,7 @@ typedef struct mips_args {
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
"hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \ "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
"$fcc5","$fcc6","$fcc7","", "", "$arg", "$frame", "$fakec", \ "$fcc5","$fcc6","$fcc7","", "$cprestore", "$arg", "$frame", "$fakec", \
"$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \ "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \
"$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \ "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \
"$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \ "$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \
......
...@@ -244,6 +244,14 @@ ...@@ -244,6 +244,14 @@
} }
}) })
(define_predicate "cprestore_save_slot_operand"
(and (match_code "mem")
(match_test "mips_cprestore_address_p (XEXP (op, 0), false)")))
(define_predicate "cprestore_load_slot_operand"
(and (match_code "mem")
(match_test "mips_cprestore_address_p (XEXP (op, 0), true)")))
(define_predicate "consttable_operand" (define_predicate "consttable_operand"
(match_test "CONSTANT_P (op)")) (match_test "CONSTANT_P (op)"))
......
2009-09-14 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.target/mips/branch-helper.h: New file.
* gcc.target/mips/branch-2.c,
* gcc.target/mips/branch-3.c,
* gcc.target/mips/branch-4.c,
* gcc.target/mips/branch-5.c,
* gcc.target/mips/branch-6.c,
* gcc.target/mips/branch-7.c,
* gcc.target/mips/branch-8.c,
* gcc.target/mips/branch-9.c,
* gcc.target/mips/branch-10.c,
* gcc.target/mips/branch-11.c,
* gcc.target/mips/branch-12.c,
* gcc.target/mips/branch-13.c,
* gcc.target/mips/branch-14.c,
* gcc.target/mips/branch-15.c: New tests.
2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com> 2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/41331 PR target/41331
......
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler "\tsd\t\\\$28," } } */
/* { dg-final { scan-assembler "\tld\t\\\$28," } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler "\tsd\t\\\$28," } } */
/* { dg-final { scan-assembler "\tld\t\\\$28," } } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* An executable version of branch-2.c. */
/* { dg-do run } */
#include "branch-helper.h"
void __attribute__((noinline))
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
int
main (void)
{
int x = 0;
int y = 1;
foo (&x);
foo (&y);
return 0;
}
/* An executable version of branch-3.c. */
/* { dg-do run } */
#include "branch-helper.h"
void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
int
main (void)
{
int x = 0;
int y = 1;
foo (&x);
foo (&y);
return 0;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|cpload)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "cprestore" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "cprestore" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler "\taddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */
/* { dg-final { scan-assembler "\t\\.cprestore\t16\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$fp\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got\\(\[^)\]*\\)\\(\\\$1\\)\n" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%lo\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tlw\t\\\$28,16\\(\\\$sp\\)\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* DN(X) generates 2**N copies of asm instruction X. */
#define D0(X) X
#define D1(X) X "\n\t" X
#define D2(X) D1 (D1 (X))
#define D3(X) D2 (D1 (X))
#define D4(X) D2 (D2 (X))
#define D5(X) D4 (D1 (X))
#define D6(X) D4 (D2 (X))
#define D7(X) D4 (D2 (D1 (X)))
#define D8(X) D4 (D4 (X))
#define D9(X) D8 (D1 (X))
#define D10(X) D8 (D2 (X))
#define D11(X) D8 (D2 (D1 (X)))
#define D12(X) D8 (D4 (X))
#define D13(X) D8 (D4 (D1 (X)))
#define D14(X) D8 (D4 (D2 (X)))
/* Emit something that is 0x1fff8 bytes long, which is the largest
permissible range for non-MIPS16 forward branches. */
#define OCCUPY_0x1fff8 \
asm (D14 ("nop") "\n\t" \
D13 ("nop") "\n\t" \
D12 ("nop") "\n\t" \
D11 ("nop") "\n\t" \
D10 ("nop") "\n\t" \
D9 ("nop") "\n\t" \
D8 ("nop") "\n\t" \
D7 ("nop") "\n\t" \
D6 ("nop") "\n\t" \
D5 ("nop") "\n\t" \
D4 ("nop") "\n\t" \
D3 ("nop") "\n\t" \
D2 ("nop") "\n\t" \
D1 ("nop"))
/* Likewise emit something that is 0x1fffc bytes long. */
#define OCCUPY_0x1fffc do { asm ("nop"); OCCUPY_0x1fff8; } while (0)
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