MIPS compact branch support

gcc/
	* config/mips/mips-opts.h (mips_cb_setting): New enum.
	* config/mips/mips-protos.h: Add definitions for
	mips_output_jump and mips_output_equal_conditional_branch
	* gcc/config/mips/mips.c (MIPS_JR): Change to support the
	JIC instruction.
	(mips_emit_compare): Add support for the MIPS R6 conditional
	compact branches.
	(mips_process_sync_loop): Likewise.
	(mips_output_order_conditional_branch): Likewise.
	(mips16_build_call_stub): Change MIPS_CALL to
	mips_output_jump.
	(mips_print_operand_punctuation): Update 's' case to only
	apply to micromips r2.
	(mips_adjust_insn_length): Add support for forbidden slot
	hazards.
	(mips_avoid_hazard): Likewise.
	(mips_reorg_process_insns): Likewise.
	(mips_output_jump): New function.
	(mips_output_equal_conditional_branch): Likewise.
	(mips_output_conditional_branch): Use jrc/bc if compact
	branch support is enabled.  Ensure the forbidden slots
	between the two branch instructions is filled with a nop.
	(mips_option_override): Add support to process the compact
	branch option and set the correct defaults.  Prevent
	non-explict relocs being using for MIPS R6.
	(mips_trampoline_init): Add compact branch support.
	(mips_mult_zero_zero_cost): Allow zero initialisation of
	accumulators with TARGET_DSP.
	* gcc/config/mips/mips.h (TARGET_CB_NEVER): New define.
	(TARGET_CB_MAYBE): New define.
	(TARGET_CB_ALWAYS): New define.
	(ISA_HAS_DELAY_SLOTS): New define.
	(ISA_HAS_COMPACT_BRANCHES): New define.
	(ISA_HAS_JRC): New define.
	(MIPS_BRANCH_C): New define.
	(MIPS_CALL): Removed.
	(MICROMIPS_J): Removed.
	* config/mips/mips.md (compact_form): New attr.
	(hazard): Add support for forbidden slots.
	(define_delay): Add support for compact branches.
	(*branch_order<mode>): Likewise.
	(*branch_order<mode>_inverted): Likewise.
	(*branch_equality<mode>): Likewise.
	(*branch_equality<mode>_inverted): Likewise.
	(*jump_absolute): Likewise.
	(*jump_pic): Likewise.
	(indirect_jump): Use mips_output_jump to produce assembly output.
	(tablejump_<mode>"): Likewise.
	(*<optab>"): Likewise.
	(<optab>_internal): Likewise.
	(sibcall_internal): Likewise.
	(sibcall_value_internal): Likewise.
	(sibcall_value_multiple_internal): Likewise.
	(call_internal): Likewise.
	(call_split): Likewise.
	(call_internal_direct): Likewise.
	(call_direct_split): Likewise.
	(call_value_internal): Likewise.
	(call_value_split): Likewise.
	(call_value_internal_direct): Likewise.
	(call_value_direct_split): Likewise.
	(call_value_multiple_internal): Likewise.
	(call_value_multiple_split): Likewise.
	(mips_get_fcsr_mips16_<mode>): Likewise.
	(mips_set_fcsr_mips16_<mode>): Likewise.
	(tls_get_tp_mips16_<mode>): Likewise.
	* config/mips/mips.opt: Add -mcompact-branches option.
	* config/mips/predicates.md (order_operator): Ensure the
	conditional compact branches are only used if the ISA them.
	* doc/invoke.texi: Document -mcompact-branches option.

gcc/testsuite/
	* gcc.target/mips/mips.exp (mips-dg-options): Handle the
	dependencies between ISA level and compact-branches.
	* gcc.target/mips/branch-10.c: Update expected output to allow
	compact forms of b/bal.
	* gcc.target/mips/branch-11.c: Likewise.
	* gcc.target/mips/branch-12.c: Likewise.
	* gcc.target/mips/branch-13.c: Likewise.
	* gcc.target/mips/branch-3.c: Likewise.
	* gcc.target/mips/branch-4.c: Likewise.
	* gcc.target/mips/branch-5.c: Likewise.
	* gcc.target/mips/branch-6.c: Likewise.
	* gcc.target/mips/branch-7.c: Likewise.
	* gcc.target/mips/branch-8.c: Likewise.
	* gcc.target/mips/branch-9.c: Likewise.
	* gcc.target/mips/branch-cost-1.c: Likewise.
	* gcc.target/mips/call-1.c: Likewise.
	* gcc.target/mips/call-2.c: Likewise.
	* gcc.target/mips/call-3.c: Likewise.
	* gcc.target/mips/call-4.c: Likewise.
	* gcc.target/mips/call-5.c: Likewise.
	* gcc.target/mips/call-6.c: Likewise.
	* gcc.target/mips/lazy-binding-1.c: Likewise.
	* gcc.target/mips/near-far-1.c: Likewise.
	* gcc.target/mips/near-far-2.c: Likewise.
	* gcc.target/mips/near-far-3.c: Likewise.
	* gcc.target/mips/near-far-4.c: Likewise.
	* gcc.target/mips/umips-branch-3.c: Ensure the test is
	run with compact branches allowed.
	* gcc.target/mips/compact-branches-1.c: New file.
	* gcc.target/mips/compact-branches-2.c: Likewise.
	* gcc.target/mips/compact-branches-3.c: Likewise.
	* gcc.target/mips/compact-branches-4.c: Likewise.
	* gcc.target/mips/compact-branches-5.c: Likewise.
	* gcc.target/mips/compact-branches-6.c: Likewise.
	* gcc.target/mips/compact-branches-7.c: Likewise.

Co-Authored-By: Andrew Bennett <andrew.bennett@imgtec.com>

From-SVN: r227385
This commit is contained in:
Matthew Fortune 2015-09-01 22:41:08 +00:00 committed by Matthew Fortune
parent 2503fd9e07
commit 22219d9b1a
42 changed files with 801 additions and 220 deletions

View file

@ -1,3 +1,77 @@
2015-09-01 Matthew Fortune <matthew.fortune@imgtec.com>
Andrew Bennett <andrew.bennett@imgtec.com>
* config/mips/mips-opts.h (mips_cb_setting): New enum.
* config/mips/mips-protos.h: Add definitions for
mips_output_jump and mips_output_equal_conditional_branch
* gcc/config/mips/mips.c (MIPS_JR): Change to support the
JIC instruction.
(mips_emit_compare): Add support for the MIPS R6 conditional
compact branches.
(mips_process_sync_loop): Likewise.
(mips_output_order_conditional_branch): Likewise.
(mips16_build_call_stub): Change MIPS_CALL to
mips_output_jump.
(mips_print_operand_punctuation): Update 's' case to only
apply to micromips r2.
(mips_adjust_insn_length): Add support for forbidden slot
hazards.
(mips_avoid_hazard): Likewise.
(mips_reorg_process_insns): Likewise.
(mips_output_jump): New function.
(mips_output_equal_conditional_branch): Likewise.
(mips_output_conditional_branch): Use jrc/bc if compact
branch support is enabled. Ensure the forbidden slots
between the two branch instructions is filled with a nop.
(mips_option_override): Add support to process the compact
branch option and set the correct defaults. Prevent
non-explict relocs being using for MIPS R6.
(mips_trampoline_init): Add compact branch support.
(mips_mult_zero_zero_cost): Allow zero initialisation of
accumulators with TARGET_DSP.
* gcc/config/mips/mips.h (TARGET_CB_NEVER): New define.
(TARGET_CB_MAYBE): New define.
(TARGET_CB_ALWAYS): New define.
(ISA_HAS_DELAY_SLOTS): New define.
(ISA_HAS_COMPACT_BRANCHES): New define.
(ISA_HAS_JRC): New define.
(MIPS_BRANCH_C): New define.
(MIPS_CALL): Removed.
(MICROMIPS_J): Removed.
* config/mips/mips.md (compact_form): New attr.
(hazard): Add support for forbidden slots.
(define_delay): Add support for compact branches.
(*branch_order<mode>): Likewise.
(*branch_order<mode>_inverted): Likewise.
(*branch_equality<mode>): Likewise.
(*branch_equality<mode>_inverted): Likewise.
(*jump_absolute): Likewise.
(*jump_pic): Likewise.
(indirect_jump): Use mips_output_jump to produce assembly output.
(tablejump_<mode>"): Likewise.
(*<optab>"): Likewise.
(<optab>_internal): Likewise.
(sibcall_internal): Likewise.
(sibcall_value_internal): Likewise.
(sibcall_value_multiple_internal): Likewise.
(call_internal): Likewise.
(call_split): Likewise.
(call_internal_direct): Likewise.
(call_direct_split): Likewise.
(call_value_internal): Likewise.
(call_value_split): Likewise.
(call_value_internal_direct): Likewise.
(call_value_direct_split): Likewise.
(call_value_multiple_internal): Likewise.
(call_value_multiple_split): Likewise.
(mips_get_fcsr_mips16_<mode>): Likewise.
(mips_set_fcsr_mips16_<mode>): Likewise.
(tls_get_tp_mips16_<mode>): Likewise.
* config/mips/mips.opt: Add -mcompact-branches option.
* config/mips/predicates.md (order_operator): Ensure the
conditional compact branches are only used if the ISA them.
* doc/invoke.texi: Document -mcompact-branches option.
2015-09-01 Vladimir Makarov <vmakarov@redhat.com>
PR target/61578

View file

@ -47,4 +47,10 @@ enum mips_r10k_cache_barrier_setting {
#define MIPS_ARCH_OPTION_FROM_ABI -1
#define MIPS_ARCH_OPTION_NATIVE -2
/* Enumerates the setting of the -mcompact-branches= option. */
enum mips_cb_setting {
MIPS_CB_NEVER,
MIPS_CB_OPTIMAL,
MIPS_CB_ALWAYS
};
#endif

View file

@ -298,6 +298,9 @@ extern const char *mips_output_conditional_branch (rtx_insn *, rtx *,
const char *, const char *);
extern const char *mips_output_order_conditional_branch (rtx_insn *, rtx *,
bool);
extern const char *mips_output_equal_conditional_branch (rtx_insn *, rtx *,
bool);
extern const char *mips_output_jump (rtx *, int, int, bool);
extern const char *mips_output_sync (void);
extern const char *mips_output_sync_loop (rtx_insn *, rtx *);
extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *);

View file

@ -176,7 +176,8 @@ along with GCC; see the file COPYING3. If not see
/* Return the opcode to jump to register DEST. When the JR opcode is not
available use JALR $0, DEST. */
#define MIPS_JR(DEST) \
(((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9))
(TARGET_CB_ALWAYS ? ((0x1b << 27) | ((DEST) << 16)) \
: (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9)))
/* Return the opcode for:
@ -5181,7 +5182,8 @@ mips_allocate_fcc (machine_mode mode)
conditions are:
- EQ or NE between two registers.
- any comparison between a register and zero. */
- any comparison between a register and zero.
- if compact branches are available then any condition is valid. */
static void
mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
@ -5203,6 +5205,44 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
else
*op1 = force_reg (GET_MODE (cmp_op0), cmp_op1);
}
else if (!need_eq_ne_p && TARGET_CB_MAYBE)
{
bool swap = false;
switch (*code)
{
case LE:
swap = true;
*code = GE;
break;
case GT:
swap = true;
*code = LT;
break;
case LEU:
swap = true;
*code = GEU;
break;
case GTU:
swap = true;
*code = LTU;
break;
case GE:
case LT:
case GEU:
case LTU:
/* Do nothing. */
break;
default:
gcc_unreachable ();
}
*op1 = force_reg (GET_MODE (cmp_op0), cmp_op1);
if (swap)
{
rtx tmp = *op1;
*op1 = *op0;
*op0 = tmp;
}
}
else
{
/* The comparison needs a separate scc instruction. Store the
@ -7260,7 +7300,7 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code)
if (fp_ret_p)
{
/* Now call the non-MIPS16 function. */
output_asm_insn (MIPS_CALL ("jal", &fn, 0, -1), &fn);
output_asm_insn (mips_output_jump (&fn, 0, -1, true), &fn);
fprintf (asm_out_file, "\t.cfi_register 31,18\n");
/* Move the result from floating-point registers to
@ -8378,7 +8418,7 @@ mips_pop_asm_switch (struct mips_asm_switch *asm_switch)
'!' Print "s" to use the short version if the delay slot contains a
16-bit instruction.
See also mips_init_print_operand_pucnt. */
See also mips_init_print_operand_punct. */
static void
mips_print_operand_punctuation (FILE *file, int ch)
@ -8462,7 +8502,8 @@ mips_print_operand_punctuation (FILE *file, int ch)
case ':':
/* When final_sequence is 0, the delay slot will be a nop. We can
use the compact version for microMIPS. */
use the compact version where available. The %: formatter will
only be present if a compact form of the branch is available. */
if (final_sequence == 0)
putc ('c', file);
break;
@ -8470,8 +8511,9 @@ mips_print_operand_punctuation (FILE *file, int ch)
case '!':
/* If the delay slot instruction is short, then use the
compact version. */
if (final_sequence == 0
|| get_attr_length (final_sequence->insn (1)) == 2)
if (TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED && mips_isa_rev <= 5
&& (final_sequence == 0
|| get_attr_length (final_sequence->insn (1)) == 2))
putc ('s', file);
break;
@ -12969,6 +13011,7 @@ mips_adjust_insn_length (rtx_insn *insn, int length)
break;
case HAZARD_DELAY:
case HAZARD_FORBIDDEN_SLOT:
length += NOP_INSN_LENGTH;
break;
@ -12980,6 +13023,78 @@ mips_adjust_insn_length (rtx_insn *insn, int length)
return length;
}
/* Return the asm template for a call. OPERANDS are the operands, TARGET_OPNO
is the operand number of the target. SIZE_OPNO is the operand number of
the argument size operand that can optionally hold the call attributes. If
SIZE_OPNO is not -1 and the call is indirect, use the function symbol from
the call attributes to attach a R_MIPS_JALR relocation to the call. LINK_P
indicates whether the jump is a call and needs to set the link register.
When generating GOT code without explicit relocation operators, all calls
should use assembly macros. Otherwise, all indirect calls should use "jr"
or "jalr"; we will arrange to restore $gp afterwards if necessary. Finally,
we can only generate direct calls for -mabicalls by temporarily switching
to non-PIC mode.
For microMIPS jal(r), we try to generate jal(r)s when a 16-bit
instruction is in the delay slot of jal(r).
Where compact branches are available, we try to use them if the delay slot
has a NOP (or equivalently delay slots were not enabled for the instruction
anyway). */
const char *
mips_output_jump (rtx *operands, int target_opno, int size_opno, bool link_p)
{
static char buffer[300];
char *s = buffer;
bool reg_p = REG_P (operands[target_opno]);
const char *and_link = link_p ? "al" : "";
const char *reg = reg_p ? "r" : "";
const char *compact = "";
const char *nop = "%/";
const char *short_delay = link_p ? "%!" : "";
const char *insn_name = TARGET_CB_NEVER || reg_p ? "j" : "b";
/* Compact branches can only be described when the ISA has support for them
as both the compact formatter '%:' and the delay slot NOP formatter '%/'
work as a mutually exclusive pair. I.e. a NOP is never required if a
compact form is available. */
if (!final_sequence
&& (TARGET_CB_MAYBE
|| (ISA_HAS_JRC && !link_p && reg_p)))
{
compact = "c";
nop = "";
}
if (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS)
sprintf (s, "%%*%s%s\t%%%d%%/", insn_name, and_link, target_opno);
else
{
if (!reg_p && TARGET_ABICALLS_PIC2)
s += sprintf (s, ".option\tpic0\n\t");
if (reg_p && mips_get_pic_call_symbol (operands, size_opno))
{
s += sprintf (s, "%%*.reloc\t1f,R_MIPS_JALR,%%%d\n1:\t", size_opno);
/* Not sure why this shouldn't permit a short delay but it did not
allow it before so we still don't allow it. */
short_delay = "";
}
else
s += sprintf (s, "%%*");
s += sprintf (s, "%s%s%s%s%s\t%%%d%s", insn_name, and_link, reg, compact, short_delay,
target_opno, nop);
if (!reg_p && TARGET_ABICALLS_PIC2)
s += sprintf (s, "\n\t.option\tpic2");
}
return buffer;
}
/* Return the assembly code for INSN, which has the operands given by
OPERANDS, and which branches to OPERANDS[0] if some condition is true.
BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0]
@ -13033,12 +13148,25 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands,
}
/* Output the unconditional branch to TAKEN. */
if (TARGET_ABSOLUTE_JUMPS)
if (TARGET_ABSOLUTE_JUMPS && TARGET_CB_MAYBE)
{
/* Add a hazard nop. */
if (!final_sequence)
{
output_asm_insn ("nop\t\t# hazard nop", 0);
fprintf (asm_out_file, "\n");
}
output_asm_insn (MIPS_ABSOLUTE_JUMP ("bc\t%0"), &taken);
}
else if (TARGET_ABSOLUTE_JUMPS)
output_asm_insn (MIPS_ABSOLUTE_JUMP ("j\t%0%/"), &taken);
else
{
mips_output_load_label (taken);
output_asm_insn ("jr\t%@%]%/", 0);
if (TARGET_CB_MAYBE)
output_asm_insn ("jrc\t%@%]", 0);
else
output_asm_insn ("jr\t%@%]%/", 0);
}
/* Now deal with its delay slot; see above. */
@ -13052,7 +13180,7 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands,
asm_out_file, optimize, 1, NULL);
final_sequence->insn (1)->set_deleted ();
}
else
else if (TARGET_CB_NEVER)
output_asm_insn ("nop", 0);
fprintf (asm_out_file, "\n");
}
@ -13063,43 +13191,156 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands,
return "";
}
/* Return the assembly code for INSN, which branches to OPERANDS[0]
if some equality condition is true. The condition is given by
OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
OPERANDS[1]. OPERANDS[2] is the comparison's first operand;
OPERANDS[3] is the second operand and may be zero or a register. */
const char *
mips_output_equal_conditional_branch (rtx_insn* insn, rtx *operands,
bool inverted_p)
{
const char *branch[2];
/* For a simple BNEZ or BEQZ microMIPSr3 branch. */
if (TARGET_MICROMIPS
&& mips_isa_rev <= 5
&& operands[3] == const0_rtx
&& get_attr_length (insn) <= 8)
{
if (mips_cb == MIPS_CB_OPTIMAL)
{
branch[!inverted_p] = "%*b%C1z%:\t%2,%0";
branch[inverted_p] = "%*b%N1z%:\t%2,%0";
}
else
{
branch[!inverted_p] = "%*b%C1z\t%2,%0%/";
branch[inverted_p] = "%*b%N1z\t%2,%0%/";
}
}
else if (TARGET_CB_MAYBE)
{
if (operands[3] == const0_rtx)
{
branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0");
branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0");
}
else if (REGNO (operands[2]) != REGNO (operands[3]))
{
branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0");
branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0");
}
else
{
/* This case is degenerate. It should not happen, but does. */
if (GET_CODE (operands[1]) == NE)
inverted_p = !inverted_p;
branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0");
branch[inverted_p] = "%*\t\t# branch never";
}
}
else
{
branch[!inverted_p] = MIPS_BRANCH ("b%C1", "%2,%z3,%0");
branch[inverted_p] = MIPS_BRANCH ("b%N1", "%2,%z3,%0");
}
return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
}
/* Return the assembly code for INSN, which branches to OPERANDS[0]
if some ordering condition is true. The condition is given by
OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
OPERANDS[1]. OPERANDS[2] is the comparison's first operand;
its second is always zero. */
OPERANDS[3] is the second operand and may be zero or a register. */
const char *
mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, bool inverted_p)
mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands,
bool inverted_p)
{
const char *branch[2];
/* Make BRANCH[1] branch to OPERANDS[0] when the condition is true.
Make BRANCH[0] branch on the inverse condition. */
switch (GET_CODE (operands[1]))
if (operands[3] != const0_rtx)
{
/* These cases are equivalent to comparisons against zero. */
case LEU:
inverted_p = !inverted_p;
/* Fall through. */
case GTU:
branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0");
branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0");
break;
/* Handle degenerate cases that should not, but do, occur. */
if (REGNO (operands[2]) == REGNO (operands[3]))
{
switch (GET_CODE (operands[1]))
{
case LT:
case LTU:
inverted_p = !inverted_p;
/* Fall through. */
case GE:
case GEU:
branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0");
branch[inverted_p] = "%*\t\t# branch never";
break;
default:
gcc_unreachable ();
}
}
else
{
branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0");
branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0");
}
}
else
{
switch (GET_CODE (operands[1]))
{
/* These cases are equivalent to comparisons against zero. */
case LEU:
inverted_p = !inverted_p;
/* Fall through. */
case GTU:
if (TARGET_CB_MAYBE)
{
branch[!inverted_p] = MIPS_BRANCH_C ("bnez", "%2,%0");
branch[inverted_p] = MIPS_BRANCH_C ("beqz", "%2,%0");
}
else
{
branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0");
branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0");
}
break;
/* These cases are always true or always false. */
case LTU:
inverted_p = !inverted_p;
/* Fall through. */
case GEU:
branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0");
branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0");
break;
/* These cases are always true or always false. */
case LTU:
inverted_p = !inverted_p;
/* Fall through. */
case GEU:
if (TARGET_CB_MAYBE)
{
branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0");
branch[inverted_p] = "%*\t\t# branch never";
}
else
{
branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0");
branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0");
}
break;
default:
branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0");
branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0");
break;
default:
if (TARGET_CB_MAYBE)
{
branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0");
branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0");
}
else
{
branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0");
branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0");
}
break;
}
}
return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
}
@ -13302,11 +13543,18 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
at, oldval, inclusive_mask, NULL);
tmp1 = at;
}
mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL);
if (TARGET_CB_NEVER)
mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL);
/* CMP = 0 [delay slot]. */
if (cmp)
mips_multi_add_insn ("li\t%0,0", cmp, NULL);
if (TARGET_CB_MAYBE && required_oldval == const0_rtx)
mips_multi_add_insn ("bnezc\t%0,2f", tmp1, NULL);
else if (TARGET_CB_MAYBE)
mips_multi_add_insn ("bnec\t%0,%1,2f", tmp1, required_oldval, NULL);
}
/* $TMP1 = OLDVAL & EXCLUSIVE_MASK. */
@ -13369,7 +13617,10 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
be annulled. To ensure this behaviour unconditionally use a NOP
in the delay slot for the branch likely case. */
mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL);
if (TARGET_CB_MAYBE)
mips_multi_add_insn ("beqzc\t%0,1b", at, NULL);
else
mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL);
/* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]. */
if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval)
@ -16651,7 +16902,7 @@ mips_orphaned_high_part_p (mips_offset_table *htab, rtx_insn *insn)
static void
mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
rtx *delayed_reg, rtx lo_reg)
rtx *delayed_reg, rtx lo_reg, bool *fs_delay)
{
rtx pattern, set;
int nops, ninsns;
@ -16677,6 +16928,15 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
nops = 2 - *hilo_delay;
else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern))
nops = 1;
/* If processing a forbidden slot hazard then a NOP is required if the
branch instruction was not in a sequence (as the sequence would
imply it is not actually a compact branch anyway) and the current
insn is not an inline asm, and can't go in a delay slot. */
else if (*fs_delay && get_attr_can_delay (insn) == CAN_DELAY_NO
&& GET_CODE (PATTERN (after)) != SEQUENCE
&& GET_CODE (pattern) != ASM_INPUT
&& asm_noperands (pattern) < 0)
nops = 1;
else
nops = 0;
@ -16689,12 +16949,18 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
/* Set up the state for the next instruction. */
*hilo_delay += ninsns;
*delayed_reg = 0;
*fs_delay = false;
if (INSN_CODE (insn) >= 0)
switch (get_attr_hazard (insn))
{
case HAZARD_NONE:
break;
case HAZARD_FORBIDDEN_SLOT:
if (TARGET_CB_MAYBE)
*fs_delay = true;
break;
case HAZARD_HILO:
*hilo_delay = 0;
break;
@ -16718,6 +16984,7 @@ mips_reorg_process_insns (void)
rtx_insn *insn, *last_insn, *subinsn, *next_insn;
rtx lo_reg, delayed_reg;
int hilo_delay;
bool fs_delay;
/* Force all instructions to be split into their final form. */
split_all_insns_noflow ();
@ -16786,6 +17053,7 @@ mips_reorg_process_insns (void)
hilo_delay = 2;
delayed_reg = 0;
lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
fs_delay = false;
/* Make a second pass over the instructions. Delete orphaned
high-part relocations or turn them into NOPs. Avoid hazards
@ -16809,7 +17077,7 @@ mips_reorg_process_insns (void)
INSN_CODE (subinsn) = CODE_FOR_nop;
}
mips_avoid_hazard (last_insn, subinsn, &hilo_delay,
&delayed_reg, lo_reg);
&delayed_reg, lo_reg, &fs_delay);
}
last_insn = insn;
}
@ -16830,7 +17098,7 @@ mips_reorg_process_insns (void)
else
{
mips_avoid_hazard (last_insn, insn, &hilo_delay,
&delayed_reg, lo_reg);
&delayed_reg, lo_reg, &fs_delay);
last_insn = insn;
}
}
@ -17695,6 +17963,27 @@ mips_option_override (void)
target_flags |= MASK_ODD_SPREG;
}
if (!ISA_HAS_COMPACT_BRANCHES && mips_cb == MIPS_CB_ALWAYS)
{
error ("unsupported combination: %qs%s %s",
mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "",
"-mcompact-branches=always");
}
else if (!ISA_HAS_DELAY_SLOTS && mips_cb == MIPS_CB_NEVER)
{
error ("unsupported combination: %qs%s %s",
mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "",
"-mcompact-branches=never");
}
/* Require explicit relocs for MIPS R6 onwards. This enables simplification
of the compact branch and jump support through the backend. */
if (!TARGET_EXPLICIT_RELOCS && mips_isa_rev >= 6)
{
error ("unsupported combination: %qs %s",
mips_arch_info->name, "-mno-explicit-relocs");
}
/* The effect of -mabicalls isn't defined for the EABI. */
if (mips_abi == ABI_EABI && TARGET_ABICALLS)
{
@ -18714,6 +19003,18 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
#undef OP
/* If we are using compact branches we don't have delay slots so
place the instruction that was in the delay slot before the JRC
instruction. */
if (TARGET_CB_ALWAYS)
{
rtx temp;
temp = trampoline[i-2];
trampoline[i-2] = trampoline[i-1];
trampoline[i-1] = temp;
}
/* Copy the trampoline code. Leave any padding uninitialized. */
for (j = 0; j < i; j++)
{

View file

@ -92,6 +92,33 @@ struct mips_cpu_info {
/* True if we are generating position-independent VxWorks RTP code. */
#define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic)
/* Compact branches must not be used if the user either selects the
'never' policy or the 'optimal' policy on a core that lacks
compact branch instructions. */
#define TARGET_CB_NEVER (mips_cb == MIPS_CB_NEVER \
|| (mips_cb == MIPS_CB_OPTIMAL \
&& !ISA_HAS_COMPACT_BRANCHES))
/* Compact branches may be used if the user either selects the
'always' policy or the 'optimal' policy on a core that supports
compact branch instructions. */
#define TARGET_CB_MAYBE (TARGET_CB_ALWAYS \
|| (mips_cb == MIPS_CB_OPTIMAL \
&& ISA_HAS_COMPACT_BRANCHES))
/* Compact branches must always be generated if the user selects
the 'always' policy or the 'optimal' policy om a core that
lacks delay slot branch instructions. */
#define TARGET_CB_ALWAYS (mips_cb == MIPS_CB_ALWAYS \
|| (mips_cb == MIPS_CB_OPTIMAL \
&& !ISA_HAS_DELAY_SLOTS))
/* Special handling for JRC that exists in microMIPSR3 as well as R6
ISAs with full compact branch support. */
#define ISA_HAS_JRC ((ISA_HAS_COMPACT_BRANCHES \
|| TARGET_MICROMIPS) \
&& mips_cb != MIPS_CB_NEVER)
/* True if the output file is marked as ".abicalls; .option pic0"
(-call_nonpic). */
#define TARGET_ABICALLS_PIC0 \
@ -872,6 +899,10 @@ struct mips_cpu_info {
#define ISA_HAS_JR (mips_isa_rev <= 5)
#define ISA_HAS_DELAY_SLOTS 1
#define ISA_HAS_COMPACT_BRANCHES (mips_isa_rev >= 6)
/* ISA has branch likely instructions (e.g. mips2). */
/* Disable branchlikely for tx39 until compare rewrite. They haven't
been generated up to this point. */
@ -2645,6 +2676,9 @@ typedef struct mips_args {
#define MIPS_BRANCH(OPCODE, OPERANDS) \
"%*" OPCODE "%?\t" OPERANDS "%/"
#define MIPS_BRANCH_C(OPCODE, 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) \
@ -2652,45 +2686,6 @@ typedef struct mips_args {
? ".option\tpic0\n\t" INSN "\n\t.option\tpic2" \
: INSN)
/* Return the asm template for a call. INSN is the instruction's mnemonic
("j" or "jal"), OPERANDS are its operands, TARGET_OPNO is the operand
number of the target. SIZE_OPNO is the operand number of the argument size
operand that can optionally hold the call attributes. If SIZE_OPNO is not
-1 and the call is indirect, use the function symbol from the call
attributes to attach a R_MIPS_JALR relocation to the call.
When generating GOT code without explicit relocation operators,
all calls should use assembly macros. Otherwise, all indirect
calls should use "jr" or "jalr"; we will arrange to restore $gp
afterwards if necessary. Finally, we can only generate direct
calls for -mabicalls by temporarily switching to non-PIC mode.
For microMIPS jal(r), we try to generate jal(r)s when a 16-bit
instruction is in the delay slot of jal(r). */
#define MIPS_CALL(INSN, OPERANDS, TARGET_OPNO, SIZE_OPNO) \
(TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
? "%*" INSN "\t%" #TARGET_OPNO "%/" \
: REG_P (OPERANDS[TARGET_OPNO]) \
? (mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO) \
? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n" \
"1:\t" INSN "r\t%" #TARGET_OPNO "%/") \
: TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \
? "%*" INSN "r%!\t%" #TARGET_OPNO "%/" \
: "%*" INSN "r\t%" #TARGET_OPNO "%/") \
: TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \
? MIPS_ABSOLUTE_JUMP ("%*" INSN "%!\t%" #TARGET_OPNO "%/") \
: MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/")) \
/* Similar to MIPS_CALL, but this is for MICROMIPS "j" to generate
"jrc" when nop is in the delay slot of "jr". */
#define MICROMIPS_J(INSN, OPERANDS, OPNO) \
(TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
? "%*j\t%" #OPNO "%/" \
: REG_P (OPERANDS[OPNO]) \
? "%*jr%:\t%" #OPNO \
: MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/"))
/* Control the assembler format that we output. */

View file

@ -409,6 +409,15 @@
(eq_attr "sync_mem" "!none") (const_string "syncloop")]
(const_string "unknown")))
(define_attr "compact_form" "always,maybe,never"
(cond [(eq_attr "jal" "direct")
(const_string "always")
(eq_attr "jal" "indirect")
(const_string "maybe")
(eq_attr "type" "jump")
(const_string "maybe")]
(const_string "never")))
;; Mode for conversion types (fcvt)
;; I2S integer to float single (SI/DI to SF)
;; I2D integer to float double (SI/DI to DF)
@ -694,7 +703,7 @@
;; DELAY means that the next instruction cannot read the result
;; of this one. HILO means that the next two instructions cannot
;; write to HI or LO.
(define_attr "hazard" "none,delay,hilo"
(define_attr "hazard" "none,delay,hilo,forbidden_slot"
(cond [(and (eq_attr "type" "load,fpload,fpidxload")
(match_test "ISA_HAS_LOAD_DELAY"))
(const_string "delay")
@ -1045,21 +1054,37 @@
(nil)
(eq_attr "can_delay" "yes")])
;; Branches that don't have likely variants do not annul on false.
;; Branches that have delay slots and don't have likely variants do
;; not annul on false.
(define_delay (and (eq_attr "type" "branch")
(not (match_test "TARGET_MIPS16"))
(ior (match_test "TARGET_CB_NEVER")
(and (eq_attr "compact_form" "maybe")
(not (match_test "TARGET_CB_ALWAYS")))
(eq_attr "compact_form" "never"))
(eq_attr "branch_likely" "no"))
[(eq_attr "can_delay" "yes")
(nil)
(nil)])
(define_delay (eq_attr "type" "jump")
(define_delay (and (eq_attr "type" "jump")
(ior (match_test "TARGET_CB_NEVER")
(and (eq_attr "compact_form" "maybe")
(not (match_test "TARGET_CB_ALWAYS")))
(eq_attr "compact_form" "never")))
[(eq_attr "can_delay" "yes")
(nil)
(nil)])
;; Call type instructions should never have a compact form as the
;; type is only used for MIPS16 patterns. For safety put the compact
;; branch detection condition in anyway.
(define_delay (and (eq_attr "type" "call")
(eq_attr "jal_macro" "no"))
(eq_attr "jal_macro" "no")
(ior (match_test "TARGET_CB_NEVER")
(and (eq_attr "compact_form" "maybe")
(not (match_test "TARGET_CB_ALWAYS")))
(eq_attr "compact_form" "never")))
[(eq_attr "can_delay" "yes")
(nil)
(nil)])
@ -5813,25 +5838,29 @@
[(set (pc)
(if_then_else
(match_operator 1 "order_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
[(match_operand:GPR 2 "register_operand" "d,d")
(match_operand:GPR 3 "reg_or_0_operand" "J,d")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_MIPS16"
{ return mips_output_order_conditional_branch (insn, operands, false); }
[(set_attr "type" "branch")])
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe,always")
(set_attr "hazard" "forbidden_slot")])
(define_insn "*branch_order<mode>_inverted"
[(set (pc)
(if_then_else
(match_operator 1 "order_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
[(match_operand:GPR 2 "register_operand" "d,d")
(match_operand:GPR 3 "reg_or_0_operand" "J,d")])
(pc)
(label_ref (match_operand 0 "" ""))))]
"!TARGET_MIPS16"
{ return mips_output_order_conditional_branch (insn, operands, true); }
[(set_attr "type" "branch")])
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe,always")
(set_attr "hazard" "forbidden_slot")])
;; Conditional branch on equality comparison.
@ -5844,20 +5873,10 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_MIPS16"
{
/* For a simple BNEZ or BEQZ microMIPS branch. */
if (TARGET_MICROMIPS
&& operands[3] == const0_rtx
&& get_attr_length (insn) <= 8)
return mips_output_conditional_branch (insn, operands,
"%*b%C1z%:\t%2,%0",
"%*b%N1z%:\t%2,%0");
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%C1", "%2,%z3,%0"),
MIPS_BRANCH ("b%N1", "%2,%z3,%0"));
}
[(set_attr "type" "branch")])
{ return mips_output_equal_conditional_branch (insn, operands, false); }
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe")
(set_attr "hazard" "forbidden_slot")])
(define_insn "*branch_equality<mode>_inverted"
[(set (pc)
@ -5868,20 +5887,10 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
"!TARGET_MIPS16"
{
/* For a simple BNEZ or BEQZ microMIPS branch. */
if (TARGET_MICROMIPS
&& operands[3] == const0_rtx
&& get_attr_length (insn) <= 8)
return mips_output_conditional_branch (insn, operands,
"%*b%N0z%:\t%2,%1",
"%*b%C0z%:\t%2,%1");
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%N1", "%2,%z3,%0"),
MIPS_BRANCH ("b%C1", "%2,%z3,%0"));
}
[(set_attr "type" "branch")])
{ return mips_output_equal_conditional_branch (insn, operands, true); }
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe")
(set_attr "hazard" "forbidden_slot")])
;; MIPS16 branches
@ -6176,11 +6185,22 @@
"!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS"
{
if (get_attr_length (insn) <= 8)
return "%*b\t%l0%/";
{
if (TARGET_CB_MAYBE)
return MIPS_ABSOLUTE_JUMP ("%*b%:\t%l0");
else
return MIPS_ABSOLUTE_JUMP ("%*b\t%l0%/");
}
else
return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/");
{
if (TARGET_CB_MAYBE && !final_sequence)
return MIPS_ABSOLUTE_JUMP ("%*bc\t%l0");
else
return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/");
}
}
[(set_attr "type" "branch")])
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe")])
(define_insn "*jump_pic"
[(set (pc)
@ -6188,14 +6208,23 @@
"!TARGET_MIPS16 && !TARGET_ABSOLUTE_JUMPS"
{
if (get_attr_length (insn) <= 8)
return "%*b\t%l0%/";
{
if (TARGET_CB_MAYBE)
return "%*b%:\t%l0";
else
return "%*b\t%l0%/";
}
else
{
mips_output_load_label (operands[0]);
return "%*jr\t%@%/%]";
if (TARGET_CB_MAYBE)
return "%*jr%:\t%@%]";
else
return "%*jr\t%@%/%]";
}
}
[(set_attr "type" "branch")])
[(set_attr "type" "branch")
(set_attr "compact_form" "maybe")])
;; We need a different insn for the mips16, because a mips16 branch
;; does not have a delay slot.
@ -6242,12 +6271,9 @@
(define_insn "indirect_jump_<mode>"
[(set (pc) (match_operand:P 0 "register_operand" "d"))]
""
{
if (TARGET_MICROMIPS)
return "%*jr%:\t%0";
else
return "%*j\t%0%/";
}
{
return mips_output_jump (operands, 0, -1, false);
}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@ -6291,12 +6317,9 @@
(match_operand:P 0 "register_operand" "d"))
(use (label_ref (match_operand 1 "" "")))]
""
{
if (TARGET_MICROMIPS)
return "%*jr%:\t%0";
else
return "%*j\t%0%/";
}
{
return mips_output_jump (operands, 0, -1, false);
}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@ -6508,10 +6531,8 @@
[(any_return)]
""
{
if (TARGET_MICROMIPS)
return "%*jr%:\t$31";
else
return "%*j\t$31%/";
operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
return mips_output_jump (operands, 0, -1, false);
}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@ -6522,12 +6543,10 @@
[(any_return)
(use (match_operand 0 "pmode_register_operand" ""))]
""
{
if (TARGET_MICROMIPS)
return "%*jr%:\t%0";
else
return "%*j\t%0%/";
}
{
operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
return mips_output_jump (operands, 0, -1, false);
}
[(set_attr "type" "jump")
(set_attr "mode" "none")])
@ -6783,12 +6802,7 @@
[(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
(match_operand 1 "" ""))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
{
if (TARGET_MICROMIPS)
return MICROMIPS_J ("j", operands, 0);
else
return MIPS_CALL ("j", operands, 0, 1);
}
{ return mips_output_jump (operands, 0, 1, false); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -6809,12 +6823,7 @@
(call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
(match_operand 2 "" "")))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
{
if (TARGET_MICROMIPS)
return MICROMIPS_J ("j", operands, 1);
else
return MIPS_CALL ("j", operands, 1, 2);
}
{ return mips_output_jump (operands, 1, 2, false); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -6826,12 +6835,7 @@
(call (mem:SI (match_dup 1))
(match_dup 2)))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
{
if (TARGET_MICROMIPS)
return MICROMIPS_J ("j", operands, 1);
else
return MIPS_CALL ("j", operands, 1, 2);
}
{ return mips_output_jump (operands, 1, 2, false); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -6887,7 +6891,10 @@
(match_operand 1 "" ""))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
{ return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, 1); }
{
return (TARGET_SPLIT_CALLS ? "#"
: mips_output_jump (operands, 0, 1, true));
}
"reload_completed && TARGET_SPLIT_CALLS"
[(const_int 0)]
{
@ -6902,7 +6909,7 @@
(clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
{ return MIPS_CALL ("jal", operands, 0, 1); }
{ return mips_output_jump (operands, 0, 1, true); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -6916,7 +6923,10 @@
(const_int 1)
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
{ return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, -1); }
{
return (TARGET_SPLIT_CALLS ? "#"
: mips_output_jump (operands, 0, -1, true));
}
"reload_completed && TARGET_SPLIT_CALLS"
[(const_int 0)]
{
@ -6933,7 +6943,7 @@
(clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
{ return MIPS_CALL ("jal", operands, 0, -1); }
{ return mips_output_jump (operands, 0, -1, true); }
[(set_attr "jal" "direct")
(set_attr "jal_macro" "no")])
@ -6956,7 +6966,10 @@
(match_operand 2 "" "")))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
{ return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); }
{
return (TARGET_SPLIT_CALLS ? "#"
: mips_output_jump (operands, 1, 2, true));
}
"reload_completed && TARGET_SPLIT_CALLS"
[(const_int 0)]
{
@ -6974,7 +6987,7 @@
(clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
{ return MIPS_CALL ("jal", operands, 1, 2); }
{ return mips_output_jump (operands, 1, 2, true); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -6986,7 +6999,10 @@
(const_int 1)
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
{ return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, -1); }
{
return (TARGET_SPLIT_CALLS ? "#"
: mips_output_jump (operands, 1, -1, true));
}
"reload_completed && TARGET_SPLIT_CALLS"
[(const_int 0)]
{
@ -7005,7 +7021,7 @@
(clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
{ return MIPS_CALL ("jal", operands, 1, -1); }
{ return mips_output_jump (operands, 1, -1, true); }
[(set_attr "jal" "direct")
(set_attr "jal_macro" "no")])
@ -7019,7 +7035,10 @@
(match_dup 2)))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
{ return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); }
{
return (TARGET_SPLIT_CALLS ? "#"
: mips_output_jump (operands, 1, 2, true));
}
"reload_completed && TARGET_SPLIT_CALLS"
[(const_int 0)]
{
@ -7040,7 +7059,7 @@
(clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
{ return MIPS_CALL ("jal", operands, 1, 2); }
{ return mips_output_jump (operands, 1, 2, true); }
[(set_attr "jal" "indirect,direct")
(set_attr "jal_macro" "no")])
@ -7411,7 +7430,7 @@
(clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
(clobber (reg:P RETURN_ADDR_REGNUM))]
"HAVE_AS_TLS && TARGET_MIPS16"
{ return MIPS_CALL ("jal", operands, 0, -1); }
{ return mips_output_jump (operands, 0, -1, true); }
[(set_attr "type" "call")
(set_attr "insn_count" "3")
(set_attr "mode" "<MODE>")])
@ -7452,7 +7471,7 @@
(clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
(clobber (reg:P RETURN_ADDR_REGNUM))]
"TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
{ return MIPS_CALL ("jal", operands, 0, -1); }
{ return mips_output_jump (operands, 0, -1, true); }
[(set_attr "type" "call")
(set_attr "insn_count" "3")])
@ -7482,7 +7501,7 @@
(clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
(clobber (reg:P RETURN_ADDR_REGNUM))]
"TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
{ return MIPS_CALL ("jal", operands, 0, -1); }
{ return mips_output_jump (operands, 0, -1, true); }
[(set_attr "type" "call")
(set_attr "insn_count" "3")])

View file

@ -418,3 +418,20 @@ Driver
mload-store-pairs
Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1)
Enable load/store bonding.
mcompact-branches=
Target RejectNegative JoinedOrMissing Var(mips_cb) Report Enum(mips_cb_setting) Init(MIPS_CB_OPTIMAL)
Specify the compact branch usage policy
Enum
Name(mips_cb_setting) Type(enum mips_cb_setting)
Policies available for use with -mcompact-branches=:
EnumValue
Enum(mips_cb_setting) String(never) Value(MIPS_CB_NEVER)
EnumValue
Enum(mips_cb_setting) String(optimal) Value(MIPS_CB_OPTIMAL)
EnumValue
Enum(mips_cb_setting) String(always) Value(MIPS_CB_ALWAYS)

View file

@ -475,7 +475,18 @@
(match_code "eq,ne,lt,ltu,ge,geu"))
(define_predicate "order_operator"
(match_code "lt,ltu,le,leu,ge,geu,gt,gtu"))
(match_code "lt,ltu,le,leu,ge,geu,gt,gtu")
{
if (XEXP (op, 1) == const0_rtx)
return true;
if (TARGET_CB_MAYBE
&& (GET_CODE (op) == LT || GET_CODE (op) == LTU
|| GET_CODE (op) == GE || GET_CODE (op) == GEU))
return true;
return false;
})
;; For NE, cstore uses sltu instructions in which the first operand is $0.
;; This isn't possible in mips16 code.

View file

@ -782,6 +782,7 @@ Objective-C and Objective-C++ Dialects}.
-mgp32 -mgp64 -mfp32 -mfpxx -mfp64 -mhard-float -msoft-float @gol
-mno-float -msingle-float -mdouble-float @gol
-modd-spreg -mno-odd-spreg @gol
-mcompact-branches=@var{policy} @gol
-mabs=@var{mode} -mnan=@var{encoding} @gol
-mdsp -mno-dsp -mdspr2 -mno-dspr2 @gol
-mmcu -mmno-mcu @gol
@ -17303,6 +17304,30 @@ for the o32 ABI. This is the default for processors that are known to
support these registers. When using the o32 FPXX ABI, @option{-mno-odd-spreg}
is set by default.
@item -mcompact-branches=never
@itemx -mcompact-branches=optimal
@itemx -mcompact-branches=always
@opindex mcompact-branches=never
@opindex mcompact-branches=optimal
@opindex mcompact-branches=always
These options control which form of branches will be generated. The
default is @option{-mcompact-branches=optimal}.
The @option{-mcompact-branches=never} option ensures that compact branch
instructions will never be generated.
The @option{-mcompact-branches=always} option ensures that a compact
branch instruction will be generated if available. If a compact branch
instruction is not available, a delay slot form of the branch will be
used instead.
This option is supported from MIPS Release 6 onwards.
The @option{-mcompact-branches=optimal} option will cause a delay slot
branch to be used if one is available in the current ISA and the delay
slot is successfully filled. If the delay slot is not filled, a compact
branch will be chosen if one is available.
@item -mabs=2008
@itemx -mabs=legacy
@opindex mabs=2008

View file

@ -1,3 +1,42 @@
2015-09-01 Matthew Fortune <matthew.fortune@imgtec.com>
Andrew Bennett <andrew.bennett@imgtec.com>
* gcc.target/mips/mips.exp (mips-dg-options): Handle the
dependencies between ISA level and compact-branches.
* gcc.target/mips/branch-10.c: Update expected output to allow
compact forms of b/bal.
* gcc.target/mips/branch-11.c: Likewise.
* gcc.target/mips/branch-12.c: Likewise.
* gcc.target/mips/branch-13.c: Likewise.
* gcc.target/mips/branch-3.c: Likewise.
* gcc.target/mips/branch-4.c: Likewise.
* gcc.target/mips/branch-5.c: Likewise.
* gcc.target/mips/branch-6.c: Likewise.
* gcc.target/mips/branch-7.c: Likewise.
* gcc.target/mips/branch-8.c: Likewise.
* gcc.target/mips/branch-9.c: Likewise.
* gcc.target/mips/branch-cost-1.c: Likewise.
* gcc.target/mips/call-1.c: Likewise.
* gcc.target/mips/call-2.c: Likewise.
* gcc.target/mips/call-3.c: Likewise.
* gcc.target/mips/call-4.c: Likewise.
* gcc.target/mips/call-5.c: Likewise.
* gcc.target/mips/call-6.c: Likewise.
* gcc.target/mips/lazy-binding-1.c: Likewise.
* gcc.target/mips/near-far-1.c: Likewise.
* gcc.target/mips/near-far-2.c: Likewise.
* gcc.target/mips/near-far-3.c: Likewise.
* gcc.target/mips/near-far-4.c: Likewise.
* gcc.target/mips/umips-branch-3.c: Ensure the test is
run with compact branches allowed.
* gcc.target/mips/compact-branches-1.c: New file.
* gcc.target/mips/compact-branches-2.c: Likewise.
* gcc.target/mips/compact-branches-3.c: Likewise.
* gcc.target/mips/compact-branches-4.c: Likewise.
* gcc.target/mips/compact-branches-5.c: Likewise.
* gcc.target/mips/compact-branches-6.c: Likewise.
* gcc.target/mips/compact-branches-7.c: Likewise.
2015-09-01 Steven G. Kargl <kargl@gcc.gnu.org>
* gfortran.dg/read_dir.f90: XFAIL this testcase on FreeBSD.

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -4,7 +4,7 @@
/* { 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" } } */
/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -4,7 +4,7 @@
/* { 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" } } */
/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=32" } */
/* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\.cprestore" } } */
#include "branch-helper.h"

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -1,7 +1,7 @@
/* { dg-options "-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 "\tjrc?\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -1,7 +1,7 @@
/* { dg-options "-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 "\tjrc?\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"

View file

@ -1,6 +1,6 @@
/* { dg-options "-mshared -mabi=32" } */
/* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */
#include "branch-helper.h"

View file

@ -4,7 +4,7 @@
/* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$(fp|sp)\\)\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 "\tjrc?\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"

View file

@ -6,4 +6,4 @@ foo (int x, int y, int z, int k)
return x == k ? x + y : z - x;
}
/* { dg-final { scan-assembler-not "\t(movz|movn)\t" } } */
/* { dg-final { scan-assembler "\t(bne|beq)\t" } } */
/* { dg-final { scan-assembler "\t(bnec?|beqc?)\t" } } */

View file

@ -1,12 +1,12 @@
/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */
/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrs?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrs?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail2\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?s?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?s?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?s?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */
__attribute__ ((noinline)) static void staticfunc () { asm (""); }
int normal ();

View file

@ -1,6 +1,6 @@
/* See through some simple data-flow. */
/* { dg-options "-mrelax-pic-calls" } */
/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" 2 } } */
/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" 2 } } */
extern void g (void);

View file

@ -1,5 +1,5 @@
/* { dg-options "-mrelax-pic-calls -mno-shared" } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" } } */
/* { dg-require-visibility "" } */
__attribute__ ((visibility ("hidden"))) void g ();

View file

@ -1,6 +1,6 @@
/* See through some simple data-flow. */
/* { dg-options "-mrelax-pic-calls" } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" } } */
extern void g (void);

View file

@ -2,13 +2,13 @@
in this case (PR target/57260). */
/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */
/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */
__attribute__ ((noinline)) static void staticfunc () { asm (""); }
int normal ();

View file

@ -1,13 +1,13 @@
/* Like call-5.c, but for n64. */
/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */
/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */
/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */
__attribute__ ((noinline)) static void staticfunc () { asm (""); }
int normal ();

View file

@ -0,0 +1,12 @@
/* { dg-options "-mcompact-branches=always -mno-micromips" } */
int glob;
void
foo (int a, int b)
{
if (a < b)
glob = 1;
}
/* { dg-final { scan-assembler "\tbgec\t\\\$\[0-9\]*,\\\$\[0-9\]*" } } */
/* { dg-final { scan-assembler "\tjrc\t\\\$31" } } */

View file

@ -0,0 +1,12 @@
/* { dg-options "-mcompact-branches=never" } */
int glob;
void
foo (int a, int b)
{
if (a < b)
glob = 1;
}
/* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */
/* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */

View file

@ -0,0 +1,13 @@
/* { dg-options "-mcompact-branches=never isa_rev>=6" } */
int glob;
void
foo (int a, int b, volatile int * bar)
{
if (a < b)
glob = *bar;
}
/* { dg-final { scan-assembler "\tnop" } } */
/* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */
/* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */

View file

@ -0,0 +1,11 @@
/* { dg-options "-mcompact-branches=optimal isa_rev>=6" } */
int glob;
void
foo (int a, int b, volatile int * bar)
{
if (a < b)
glob = *bar;
}
/* { dg-final { scan-assembler "\tb\[^ \t\]*c" } } */

View file

@ -0,0 +1,10 @@
/* { dg-options "-mno-abicalls -mcompact-branches=never isa_rev>=6" } */
void bar (int);
void
foo ()
{
bar (1);
}
/* { dg-final { scan-assembler "\t(j|jal)\t" } } */

View file

@ -0,0 +1,10 @@
/* { dg-options "-mno-abicalls -mcompact-branches=optimal isa_rev>=6" } */
void bar (int);
void
foo ()
{
bar (1);
}
/* { dg-final { scan-assembler "\t(bc|balc)\t" } } */

View file

@ -0,0 +1,12 @@
/* { dg-options "-mhard-float -mcompact-branches=always isa_rev>=6 -mno-micromips" } */
int bar;
void
foo (float a, volatile int * b)
{
if (a < 0.1)
bar = *b;
}
/* { dg-final { scan-assembler "\t(bc1eqz|bc1nez)\t" } } */
/* { dg-final { scan-assembler "\tnop" } } */

View file

@ -19,6 +19,6 @@ foo (int n)
/* There should be exactly five uses of $25: one to set up $gp, two to
load the address of bar (), and two to call it. */
/* { dg-final { scan-assembler-times "\tl.\t\\\$25,%call16\\\(bar\\\)" 2 } } */
/* { dg-final { scan-assembler-times "\tjalrs?\t\\\$25" 2 } } */
/* { dg-final { scan-assembler-times "\tjalrc?s?\t\\\$25" 2 } } */
/* { dg-final { scan-assembler "(\\\$28,|\t.cpload\t)\\\$25" } } */
/* { dg-final { scan-assembler-times "\\\$25" 5 } } */

View file

@ -243,6 +243,7 @@ set mips_option_groups {
mips16 "-mips16|-mno-mips16|-mflip-mips16"
mips3d "-mips3d|-mno-mips3d"
pic "-f(no-|)(pic|PIC)"
cb "-mcompact-branches=.*"
profiling "-pg"
small-data "-G[0-9]+"
warnings "-w"
@ -1068,8 +1069,10 @@ proc mips-dg-options { args } {
# We need a revision 6 or better ISA for:
#
# - When the LSA instruction is required
# - When only using compact branches
if { $isa_rev < 6
&& ([mips_have_test_option_p options "HAS_LSA"]) } {
&& ([mips_have_test_option_p options "HAS_LSA"]
|| [mips_have_test_option_p options "-mcompact-branches=always"]) } {
if { $gp_size == 32 } {
mips_make_test_option options "-mips32r6"
} else {
@ -1164,6 +1167,9 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mips64r5"
}
mips_make_test_option options "-mnan=2008"
if { [mips_have_option_p options "-mcompact-branches=always"] } {
mips_make_test_option options "-mcompact-branches=optimal"
}
# Check whether we need to switch from a 32-bit processor to the
# "nearest" 64-bit processor.
} elseif { $gp_size == 64 && [mips_32bit_arch_p $arch] } {
@ -1308,6 +1314,11 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mno-micromips"
mips_make_test_option options "-mnan=legacy"
}
if { $isa_rev < 6 } {
if { [mips_have_option_p options "-mcompact-branches=always"] } {
mips_make_test_option options "-mcompact-branches=optimal"
}
}
if { $isa_rev > 5 } {
mips_make_test_option options "-mno-dsp"
mips_make_test_option options "-mno-mips16"

View file

@ -16,5 +16,5 @@ int test ()
/* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */
/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnear_func\n" } } */
/* { dg-final { scan-assembler-not "\tjal\tnormal_func\n" } } */

View file

@ -16,5 +16,5 @@ int test ()
/* { dg-final { scan-assembler-not "\tjal(|s)\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tjal(|s)\tfar_func\n" } } */
/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\tjal(|s)\tnormal_func\n" } } */
/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnormal_func\n" } } */

View file

@ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); }
/* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */
/* { dg-final { scan-assembler "\tj(|al|als)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */
/* { dg-final { scan-assembler-not "\tj\tnormal_func\n" } } */

View file

@ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); }
/* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */
/* { dg-final { scan-assembler "\tj(|al|als)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\tj(|al|als)\tnormal_func\n" } } */
/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */
/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnormal_func\n" } } */

View file

@ -1,4 +1,4 @@
/* { dg-options "(-mmicromips)" } */
/* { dg-options "(-mmicromips) -mcompact-branches=optimal" } */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
void MICROMIPS