diff options
author | Richard Sandiford <richard@codesourcery.com> | 2006-03-09 21:03:17 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2006-03-09 21:03:17 +0000 |
commit | a8c1d5f80e0b710089f7e5f6265bdc345c7b514f (patch) | |
tree | 158c3ae50f6fe3219c35b26ac707baac94ae4ad9 /gcc/config/mips | |
parent | 1fea4e6c4301b2b69d6e2fa72c3c62ffdc8cfb78 (diff) | |
download | gcc-a8c1d5f80e0b710089f7e5f6265bdc345c7b514f.zip gcc-a8c1d5f80e0b710089f7e5f6265bdc345c7b514f.tar.gz gcc-a8c1d5f80e0b710089f7e5f6265bdc345c7b514f.tar.bz2 |
mips-protos.h (mips_output_conditional_branch): Change interface.
* config/mips/mips-protos.h (mips_output_conditional_branch): Change
interface.
(mips_output_order_conditional_branch): Declare.
* config/mips/mips.h (MIPS_BRANCH): New macro.
* config/mips/mips.c (gen_conditional_branch): Use VOIDmode
for the comparison. Use gen_condjump.
(mips_output_conditional_branch): Rework interface to take the
asm templates for a direct branch and the inverse of a direct branch.
(mips_output_order_conditional_branch): New function.
(mips_builtin_branch_and_move): New function.
(mips_expand_builtin_compare): Use it. Use VOIDmode for the
branch condition. Use gen_single_cc as the condition for
__builtin_mips_upper_* or __builtin_mips_lower_*.
(mips_expand_builtin_bposge): Use mips_builtin_branch_and_move.
Use VOIDmode for the branch condition.
* config/mips/predicates.md (order_operator): New predicate.
* config/mips/mips.md (UNSPEC_SINGLE_CC): New constant.
(branch_fp): Rename to...
(*branch_fp): ...this. Remove mode from comparison operator.
Use new mips_output_conditional_branch interface.
(branch_fp_inverted): Rename to...
(*branch_fp_inverted): ...this and update as for *branch_fp.
(*branch_zero<mode>): Rename to...
(*branch_order<mode>): ...this. Remove mode from comparison operator.
Use mips_output_order_conditional_branch. Only accept ordered
comparisons.
(*branch_zero<mode>_inverted): Rename to...
(*branch_order<mode>_inverted): ...this and update as for
*branch_order<mode>.
(*branch_equality<mode>): Accept zero as the second operand to
the equality operator. Use the new mips_output_conditional_branch
interface.
(*branch_equality<mode>_inverted): Likewise.
(condjump): New expander.
* config/mips/mips-dsp.md (mips_bposge): Remove mode from comparison
operator.
* config/mips/mips-ps-3d.md (bc1any4t, bc1any4f): Likewise.
(bc1any2t, bc1any2f): Likewise.
(single_cc): New expander.
(*branch_upper_lower, *branch_upper_lower_inverted): New patterns.
From-SVN: r111909
Diffstat (limited to 'gcc/config/mips')
-rw-r--r-- | gcc/config/mips/mips-dsp.md | 9 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 5 | ||||
-rw-r--r-- | gcc/config/mips/mips-ps-3d.md | 69 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 443 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 6 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 100 | ||||
-rw-r--r-- | gcc/config/mips/predicates.md | 3 |
7 files changed, 277 insertions, 358 deletions
diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md index a61b23f..3fdcc59 100644 --- a/gcc/config/mips/mips-dsp.md +++ b/gcc/config/mips/mips-dsp.md @@ -1046,11 +1046,10 @@ ;; BPOSGE32 (define_insn "mips_bposge" [(set (pc) - (if_then_else - (ge:CCDSP (reg:CCDSP CCDSP_PO_REGNUM) - (match_operand:SI 0 "immediate_operand" "I")) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM) + (match_operand:SI 0 "immediate_operand" "I")) + (label_ref (match_operand 1 "" "")) + (pc)))] "TARGET_DSP" "%*bposge%0\t%1%/" [(set_attr "type" "branch") diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 9481b08..1dc31f5 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -212,8 +212,9 @@ extern int mips_register_move_cost (enum machine_mode, enum reg_class, extern int mips_adjust_insn_length (rtx, int); extern const char *mips_output_load_label (void); -extern const char *mips_output_conditional_branch (rtx, rtx *, int, int, - int, int); +extern const char *mips_output_conditional_branch (rtx, rtx *, const char *, + const char *); +extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool); extern const char *mips_output_division (const char *, rtx *); extern unsigned int mips_hard_regno_nregs (int, enum machine_mode); extern bool mips_linked_madd_p (rtx, rtx); diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md index 17dd038..6a4c2b9 100644 --- a/gcc/config/mips/mips-ps-3d.md +++ b/gcc/config/mips/mips-ps-3d.md @@ -389,8 +389,8 @@ ; Branch on Any of Four Floating Point Condition Codes True (define_insn "bc1any4t" [(set (pc) - (if_then_else (ne:CCV4 (match_operand:CCV4 0 "register_operand" "z") - (const_int 0)) + (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z") + (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_MIPS3D" @@ -401,8 +401,8 @@ ; Branch on Any of Four Floating Point Condition Codes False (define_insn "bc1any4f" [(set (pc) - (if_then_else (ne:CCV4 (match_operand:CCV4 0 "register_operand" "z") - (const_int -1)) + (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z") + (const_int -1)) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_MIPS3D" @@ -413,8 +413,8 @@ ; Branch on Any of Two Floating Point Condition Codes True (define_insn "bc1any2t" [(set (pc) - (if_then_else (ne:CCV2 (match_operand:CCV2 0 "register_operand" "z") - (const_int 0)) + (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z") + (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_MIPS3D" @@ -425,8 +425,8 @@ ; Branch on Any of Two Floating Point Condition Codes False (define_insn "bc1any2f" [(set (pc) - (if_then_else (ne:CCV2 (match_operand:CCV2 0 "register_operand" "z") - (const_int -1)) + (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z") + (const_int -1)) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_MIPS3D" @@ -434,6 +434,59 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) +; 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). +(define_expand "single_cc" + [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC) + (const_int 0))]) + +; This is a normal floating-point branch pattern, but rather than check +; a single CCmode register, it checks one register in a CCV2 pair. +; Operand 2 is the register pair and operand 3 is the index of the +; register we want. +(define_insn "*branch_upper_lower" + [(set (pc) + (if_then_else + (match_operator 0 "equality_operator" + [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") + (match_operand 3 "const_int_operand")] + UNSPEC_SINGLE_CC) + (const_int 0)]) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" +{ + operands[2] + = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%F0", "%2,%1"), + MIPS_BRANCH ("b%W0", "%2,%1")); +} + [(set_attr "type" "branch") + (set_attr "mode" "none")]) + +; As above, but with the sense of the condition reversed. +(define_insn "*branch_upper_lower_inverted" + [(set (pc) + (if_then_else + (match_operator 0 "equality_operator" + [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z") + (match_operand 3 "const_int_operand")] + UNSPEC_SINGLE_CC) + (const_int 0)]) + (pc) + (label_ref (match_operand 1 "" ""))))] + "TARGET_HARD_FLOAT" +{ + operands[2] + = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3])); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%W0", "%2,%1"), + MIPS_BRANCH ("b%F0", "%2,%1")); +} + [(set_attr "type" "branch") + (set_attr "mode" "none")]) + ;---------------------------------------------------------------------------- ; Floating Point Reduced Precision Reciprocal Square Root Instructions. ;---------------------------------------------------------------------------- diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index aed07e5..daa7488 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3186,15 +3186,11 @@ mips_emit_scc (enum rtx_code code, rtx target) void gen_conditional_branch (rtx *operands, enum rtx_code code) { - rtx op0, op1, target; + rtx op0, op1, condition; mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16); - target = gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (code, GET_MODE (op0), - op0, op1), - gen_rtx_LABEL_REF (VOIDmode, operands[0]), - pc_rtx); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, target)); + condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); + emit_jump_insn (gen_condjump (condition, operands[0])); } /* Emit the common code for conditional moves. OPERANDS is the array @@ -9127,217 +9123,126 @@ mips_output_load_label (void) } } +/* Return the assembly code for INSN, which has the operands given by + OPERANDS, and which branches to OPERANDS[1] if some condition is true. + BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[1] + is in range of a direct branch. BRANCH_IF_FALSE is an inverted + version of BRANCH_IF_TRUE. */ -/* Output assembly instructions to peform a conditional branch. - - INSN is the branch instruction. OPERANDS[0] is the condition. - OPERANDS[1] is the target of the branch. OPERANDS[2] is the target - of the first operand to the condition. If TWO_OPERANDS_P is - nonzero the comparison takes two operands; OPERANDS[3] will be the - second operand. - - If INVERTED_P is nonzero we are to branch if the condition does - not hold. If FLOAT_P is nonzero this is a floating-point comparison. - - LENGTH is the length (in bytes) of the sequence we are to generate. - That tells us whether to generate a simple conditional branch, or a - reversed conditional branch around a `jr' instruction. */ const char * -mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p, - int float_p, int inverted_p, int length) -{ - static char buffer[200]; - /* The kind of comparison we are doing. */ - enum rtx_code code = GET_CODE (operands[0]); - /* Nonzero if the opcode for the comparison needs a `z' indicating - that it is a comparison against zero. */ - int need_z_p; - /* A string to use in the assembly output to represent the first - operand. */ - const char *op1 = "%z2"; - /* A string to use in the assembly output to represent the second - operand. Use the hard-wired zero register if there's no second - operand. */ - const char *op2 = (two_operands_p ? ",%z3" : ",%."); - /* The operand-printing string for the comparison. */ - const char *const comp = (float_p ? "%F0" : "%C0"); - /* The operand-printing string for the inverted comparison. */ - const char *const inverted_comp = (float_p ? "%W0" : "%N0"); - - /* The MIPS processors (for levels of the ISA at least two), have - "likely" variants of each branch instruction. These instructions - annul the instruction in the delay slot if the branch is not - taken. */ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - - if (!two_operands_p) - { - /* To compute whether than A > B, for example, we normally - subtract B from A and then look at the sign bit. But, if we - are doing an unsigned comparison, and B is zero, we don't - have to do the subtraction. Instead, we can just check to - see if A is nonzero. Thus, we change the CODE here to - reflect the simpler comparison operation. */ - switch (code) - { - case GTU: - code = NE; - break; +mips_output_conditional_branch (rtx insn, rtx *operands, + const char *branch_if_true, + const char *branch_if_false) +{ + unsigned int length; + rtx taken, not_taken; - case LEU: - code = EQ; - break; + length = get_attr_length (insn); + if (length <= 8) + { + /* Just a simple conditional branch. */ + mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); + return branch_if_true; + } - case GEU: - /* A condition which will always be true. */ - code = EQ; - op1 = "%."; - break; + /* Generate a reversed branch around a direct jump. This fallback does + not use branch-likely instructions. */ + mips_branch_likely = false; + not_taken = gen_label_rtx (); + taken = operands[1]; - case LTU: - /* A condition which will always be false. */ - code = NE; - op1 = "%."; - break; + /* Generate the reversed branch to NOT_TAKEN. */ + operands[1] = not_taken; + output_asm_insn (branch_if_false, operands); - default: - /* Not a special case. */ - break; + /* If INSN has a delay slot, we must provide delay slots for both the + branch to NOT_TAKEN and the conditional jump. We must also ensure + that INSN's delay slot is executed in the appropriate cases. */ + if (final_sequence) + { + /* This first delay slot will always be executed, so use INSN's + delay slot if is not annulled. */ + if (!INSN_ANNULLED_BRANCH_P (insn)) + { + final_scan_insn (XVECEXP (final_sequence, 0, 1), + asm_out_file, optimize, 1, NULL); + INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1; } + else + output_asm_insn ("nop", 0); + fprintf (asm_out_file, "\n"); } - /* Relative comparisons are always done against zero. But - equality comparisons are done between two operands, and therefore - do not require a `z' in the assembly language output. */ - need_z_p = (!float_p && code != EQ && code != NE); - /* For comparisons against zero, the zero is not provided - explicitly. */ - if (need_z_p) - op2 = ""; - - /* Begin by terminating the buffer. That way we can always use - strcat to add to it. */ - buffer[0] = '\0'; + /* Output the unconditional branch to TAKEN. */ + if (length <= 16) + output_asm_insn ("j\t%0%/", &taken); + else + { + output_asm_insn (mips_output_load_label (), &taken); + output_asm_insn ("jr\t%@%]%/", 0); + } - switch (length) + /* Now deal with its delay slot; see above. */ + if (final_sequence) { - case 4: - case 8: - /* Just a simple conditional branch. */ - if (float_p) - sprintf (buffer, "%%*b%s%%?\t%%Z2%%1%%/", - inverted_p ? inverted_comp : comp); + /* This delay slot will only be executed if the branch is taken. + Use INSN's delay slot if is annulled. */ + if (INSN_ANNULLED_BRANCH_P (insn)) + { + final_scan_insn (XVECEXP (final_sequence, 0, 1), + asm_out_file, optimize, 1, NULL); + INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1; + } else - sprintf (buffer, "%%*b%s%s%%?\t%s%s,%%1%%/", - inverted_p ? inverted_comp : comp, - need_z_p ? "z" : "", - op1, - op2); - return buffer; - - case 12: - case 16: - case 24: - case 28: - { - /* Generate a reversed conditional branch around ` j' - instruction: - - .set noreorder - .set nomacro - bc l - delay_slot or #nop - j target - #nop - l: - .set macro - .set reorder - - If the original branch was a likely branch, the delay slot - must be executed only if the branch is taken, so generate: - - .set noreorder - .set nomacro - bc l - #nop - j target - delay slot or #nop - l: - .set macro - .set reorder - - When generating PIC, instead of: - - j target - - we emit: - - .set noat - la $at, target - jr $at - .set at - */ - - rtx orig_target; - rtx target = gen_label_rtx (); - - orig_target = operands[1]; - operands[1] = target; - /* Generate the reversed comparison. This takes four - bytes. */ - if (float_p) - sprintf (buffer, "%%*b%s\t%%Z2%%1", - inverted_p ? comp : inverted_comp); - else - sprintf (buffer, "%%*b%s%s\t%s%s,%%1", - inverted_p ? comp : inverted_comp, - need_z_p ? "z" : "", - op1, - op2); - output_asm_insn (buffer, operands); - - if (length != 16 && length != 28 && ! mips_branch_likely) - { - /* Output delay slot instruction. */ - rtx insn = final_sequence; - final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, - optimize, 1, NULL); - INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; - } - else - output_asm_insn ("%#", 0); + output_asm_insn ("nop", 0); + fprintf (asm_out_file, "\n"); + } - if (length <= 16) - output_asm_insn ("j\t%0", &orig_target); - else - { - output_asm_insn (mips_output_load_label (), &orig_target); - output_asm_insn ("jr\t%@%]", 0); - } + /* Output NOT_TAKEN. */ + (*targetm.asm_out.internal_label) (asm_out_file, "L", + CODE_LABEL_NUMBER (not_taken)); + return ""; +} - if (length != 16 && length != 28 && mips_branch_likely) - { - /* Output delay slot instruction. */ - rtx insn = final_sequence; - final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, - optimize, 1, NULL); - INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; - } - else - output_asm_insn ("%#", 0); +/* Return the assembly code for INSN, which branches to OPERANDS[1] + if some ordered condition is true. The condition is given by + OPERANDS[0] if !INVERTED_P, otherwise it is the inverse of + OPERANDS[0]. OPERANDS[2] is the comparison's first operand; + its second is always zero. */ - (*targetm.asm_out.internal_label) (asm_out_file, "L", - CODE_LABEL_NUMBER (target)); +const char * +mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p) +{ + const char *branch[2]; - return ""; - } + /* Make BRANCH[1] branch to OPERANDS[1] when the condition is true. + Make BRANCH[0] branch on the inverse condition. */ + switch (GET_CODE (operands[0])) + { + /* 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,%.,%1"); + branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%1"); + 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", "%.,%.,%1"); + branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%1"); + break; default: - gcc_unreachable (); + branch[!inverted_p] = MIPS_BRANCH ("b%C0z", "%2,%1"); + branch[inverted_p] = MIPS_BRANCH ("b%N0z", "%2,%1"); + break; } - - /* NOTREACHED */ - return 0; + return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); } /* Used to output div or ddiv instruction DIVISION, which has the operands @@ -10591,6 +10496,34 @@ mips_expand_builtin_movtf (enum mips_builtin_type type, return target; } +/* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE + into TARGET otherwise. Return TARGET. */ + +static rtx +mips_builtin_branch_and_move (rtx condition, rtx target, + rtx value_if_true, rtx value_if_false) +{ + rtx true_label, done_label; + + true_label = gen_label_rtx (); + done_label = gen_label_rtx (); + + /* First assume that CONDITION is false. */ + emit_move_insn (target, value_if_false); + + /* Branch to TRUE_LABEL if CONDITION is true and DONE_LABEL otherwise. */ + emit_jump_insn (gen_condjump (condition, true_label)); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + + /* Fix TARGET if CONDITION is true. */ + emit_label (true_label); + emit_move_insn (target, value_if_true); + + emit_label (done_label); + return target; +} + /* Expand a comparison builtin of type BUILTIN_TYPE. ICODE is the code of the comparison instruction and COND is the condition it should test. ARGLIST is the list of function arguments and TARGET, if nonnull, @@ -10601,10 +10534,8 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type, enum insn_code icode, enum mips_fp_condition cond, rtx target, tree arglist) { - rtx label1, label2, if_then_else; - rtx pat, cmp_result, ops[MAX_RECOG_OPERANDS]; - rtx target_if_equal, target_if_unequal; - int cmp_value, i; + rtx offset, condition, cmp_result, ops[MAX_RECOG_OPERANDS]; + int i; if (target == 0 || GET_MODE (target) != SImode) target = gen_reg_rtx (SImode); @@ -10617,12 +10548,12 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type, switch (insn_data[icode].n_operands) { case 4: - pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond)); + emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond))); break; case 6: - pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2], - ops[3], ops[4], GEN_INT (cond)); + emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], + ops[3], ops[4], GEN_INT (cond))); break; default: @@ -10631,71 +10562,35 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type, /* If the comparison sets more than one register, we define the result to be 0 if all registers are false and -1 if all registers are true. - The value of the complete result is indeterminate otherwise. It is - possible to test individual registers using SUBREGs. - - Set up CMP_RESULT, CMP_VALUE, TARGET_IF_EQUAL and TARGET_IF_UNEQUAL so - that the result should be TARGET_IF_EQUAL if (EQ CMP_RESULT CMP_VALUE) - and TARGET_IF_UNEQUAL otherwise. */ - if (builtin_type == MIPS_BUILTIN_CMP_ALL) - { - cmp_value = -1; - target_if_equal = const1_rtx; - target_if_unequal = const0_rtx; - } - else + The value of the complete result is indeterminate otherwise. */ + switch (builtin_type) { - cmp_value = 0; - target_if_equal = const0_rtx; - target_if_unequal = const1_rtx; - if (builtin_type == MIPS_BUILTIN_CMP_UPPER) - cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 4); - else if (builtin_type == MIPS_BUILTIN_CMP_LOWER) - cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 0); - } - - /* First assume that CMP_RESULT == CMP_VALUE. */ - emit_move_insn (target, target_if_equal); - - /* Branch to LABEL1 if CMP_RESULT != CMP_VALUE. */ - emit_insn (pat); - label1 = gen_label_rtx (); - label2 = gen_label_rtx (); - if_then_else - = gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (NE, GET_MODE (cmp_result), - cmp_result, GEN_INT (cmp_value)), - gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_LABEL_REF (VOIDmode, label2))); - emit_barrier (); - emit_label (label1); + case MIPS_BUILTIN_CMP_ALL: + condition = gen_rtx_NE (VOIDmode, cmp_result, constm1_rtx); + return mips_builtin_branch_and_move (condition, target, + const0_rtx, const1_rtx); - /* Fix TARGET for CMP_RESULT != CMP_VALUE. */ - emit_move_insn (target, target_if_unequal); - emit_label (label2); + case MIPS_BUILTIN_CMP_UPPER: + case MIPS_BUILTIN_CMP_LOWER: + offset = GEN_INT (builtin_type == MIPS_BUILTIN_CMP_UPPER); + condition = gen_single_cc (cmp_result, offset); + return mips_builtin_branch_and_move (condition, target, + const1_rtx, const0_rtx); - return target; + default: + condition = gen_rtx_NE (VOIDmode, cmp_result, const0_rtx); + return mips_builtin_branch_and_move (condition, target, + const1_rtx, const0_rtx); + } } /* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull, - suggests a good place to put the boolean result. - - The sequence we want is - - li target, 0 - bposge* label1 - j label2 - label1: - li target, 1 - label2: */ + suggests a good place to put the boolean result. */ static rtx mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target) { - rtx label1, label2, if_then_else; - rtx cmp_result; + rtx condition, cmp_result; int cmp_value; if (target == 0 || GET_MODE (target) != SImode) @@ -10708,29 +10603,9 @@ mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target) else gcc_assert (0); - /* Move 0 to target */ - emit_move_insn (target, const0_rtx); - - /* Generate two labels */ - label1 = gen_label_rtx (); - label2 = gen_label_rtx (); - - /* Generate if_then_else */ - if_then_else - = gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (GE, CCDSPmode, - cmp_result, GEN_INT (cmp_value)), - gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx); - - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_LABEL_REF (VOIDmode, label2))); - emit_barrier (); - emit_label (label1); - emit_move_insn (target, const1_rtx); - emit_label (label2); - - return target; + condition = gen_rtx_GE (VOIDmode, cmp_result, GEN_INT (cmp_value)); + return mips_builtin_branch_and_move (condition, target, + const1_rtx, const0_rtx); } /* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL. diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 8a993e0..b0ae120 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2272,6 +2272,12 @@ typedef struct mips_args { be updated with the correct length of the insn. */ #define ADJUST_INSN_LENGTH(INSN, LENGTH) \ ((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH))) + +/* Return the asm template for a non-MIPS16 conditional branch instruction. + OPCODE is the opcode's mnemonic and OPERANDS is the asm template for + its operands. */ +#define MIPS_BRANCH(OPCODE, OPERANDS) \ + "%*" OPCODE "%?\t" OPERANDS "%/" /* Control the assembler format that we output. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 23677f0..01653d6 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -72,6 +72,7 @@ (UNSPEC_RSQRT2 209) (UNSPEC_RECIP1 210) (UNSPEC_RECIP2 211) + (UNSPEC_SINGLE_CC 212) ;; MIPS DSP ASE Revision 0.98 3/24/2005 (UNSPEC_ADDQ 300) @@ -4272,85 +4273,65 @@ ;; Conditional branches on floating-point equality tests. -(define_insn "branch_fp" +(define_insn "*branch_fp" [(set (pc) (if_then_else - (match_operator:CC 0 "comparison_operator" - [(match_operand:CC 2 "register_operand" "z") - (const_int 0)]) + (match_operator 0 "equality_operator" + [(match_operand:CC 2 "register_operand" "z") + (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_HARD_FLOAT" { - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/1, - /*inverted_p=*/0, - get_attr_length (insn)); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%F0", "%2,%1"), + MIPS_BRANCH ("b%W0", "%2,%1")); } - [(set_attr "type" "branch") - (set_attr "mode" "none")]) + [(set_attr "type" "branch") + (set_attr "mode" "none")]) -(define_insn "branch_fp_inverted" +(define_insn "*branch_fp_inverted" [(set (pc) (if_then_else - (match_operator:CC 0 "comparison_operator" - [(match_operand:CC 2 "register_operand" "z") - (const_int 0)]) + (match_operator 0 "equality_operator" + [(match_operand:CC 2 "register_operand" "z") + (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "TARGET_HARD_FLOAT" { - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/1, - /*inverted_p=*/1, - get_attr_length (insn)); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%W0", "%2,%1"), + MIPS_BRANCH ("b%F0", "%2,%1")); } - [(set_attr "type" "branch") - (set_attr "mode" "none")]) + [(set_attr "type" "branch") + (set_attr "mode" "none")]) -;; Conditional branches on comparisons with zero. +;; Conditional branches on ordered comparisons with zero. -(define_insn "*branch_zero<mode>" +(define_insn "*branch_order<mode>" [(set (pc) (if_then_else - (match_operator 0 "comparison_operator" + (match_operator 0 "order_operator" [(match_operand:GPR 2 "register_operand" "d") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" -{ - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/0, - /*inverted_p=*/0, - get_attr_length (insn)); -} + { return mips_output_order_conditional_branch (insn, operands, false); } [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_insn "*branch_zero<mode>_inverted" +(define_insn "*branch_order<mode>_inverted" [(set (pc) (if_then_else - (match_operator 0 "comparison_operator" + (match_operator 0 "order_operator" [(match_operand:GPR 2 "register_operand" "d") (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" -{ - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/0, - /*inverted_p=*/1, - get_attr_length (insn)); -} + { return mips_output_order_conditional_branch (insn, operands, true); } [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -4361,17 +4342,14 @@ (if_then_else (match_operator 0 "equality_operator" [(match_operand:GPR 2 "register_operand" "d") - (match_operand:GPR 3 "register_operand" "d")]) + (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" { - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/1, - /*float_p=*/0, - /*inverted_p=*/0, - get_attr_length (insn)); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%C0", "%2,%z3,%1"), + MIPS_BRANCH ("b%N0", "%2,%z3,%1")); } [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -4381,17 +4359,14 @@ (if_then_else (match_operator 0 "equality_operator" [(match_operand:GPR 2 "register_operand" "d") - (match_operand:GPR 3 "register_operand" "d")]) + (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" { - return mips_output_conditional_branch (insn, - operands, - /*two_operands_p=*/1, - /*float_p=*/0, - /*inverted_p=*/1, - get_attr_length (insn)); + return mips_output_conditional_branch (insn, operands, + MIPS_BRANCH ("b%N0", "%2,%z3,%1"), + MIPS_BRANCH ("b%C0", "%2,%z3,%1")); } [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -4438,6 +4413,13 @@ gen_conditional_branch (operands, <CODE>); DONE; }) + +;; Used to implement built-in functions. +(define_expand "condjump" + [(set (pc) + (if_then_else (match_operand 0) + (label_ref (match_operand 1)) + (pc)))]) ;; ;; .................... diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index a96e017..d93621d 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -212,6 +212,9 @@ (define_predicate "trap_comparison_operator" (match_code "eq,ne,lt,ltu,ge,geu")) +(define_predicate "order_operator" + (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) + (define_predicate "small_data_pattern" (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") |