From a012718f1d0470cd1a19b4c8c5200de06ba47b0a Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 16 Jul 2004 07:51:31 +0000 Subject: [PATCH] mips-protos.h (gen_int_relational): Delete. * config/mips/mips-protos.h (gen_int_relational): Delete. (mips_emit_scc): Declare. * config/mips/mips.c (internal_test): Delete. (sle_operand, sleu_operand): New functions. (map_test_to_internal_test, gen_int_relational): Delete. (mips_emit_binary, mips_relational_operand_ok_p) (mips_emit_int_relational, mips_zero_if_equal) (mips_emit_scc): New functions. (gen_conditional_branch): Rework to use mips_emit_int_relational. * config/mips/mips.h (PREDICATE_CODES): Add sle_operand and sleu_operand. * config/mips/mips.md (seq, sne, sgt, sge, slt, sle, sgtu, sgeu) (sltu, sleu): Use mips_emit_scc. (*sge_[sd]i, *sgeu_[sd]i): New patterns. (*sle_[sd]i, *sle_[sd]i_mips16): Use sle_operand. (*sleu_[sd]i, *sleu_[sd]i_mips16): Use sleu_operand. From-SVN: r84808 --- gcc/ChangeLog | 19 ++ gcc/config/mips/mips-protos.h | 2 +- gcc/config/mips/mips.c | 423 ++++++++++++---------------------- gcc/config/mips/mips.h | 2 + gcc/config/mips/mips.md | 148 +++++------- 5 files changed, 226 insertions(+), 368 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b747aaaff19..a57ee1c7d86 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2004-07-16 Richard Sandiford + + * config/mips/mips-protos.h (gen_int_relational): Delete. + (mips_emit_scc): Declare. + * config/mips/mips.c (internal_test): Delete. + (sle_operand, sleu_operand): New functions. + (map_test_to_internal_test, gen_int_relational): Delete. + (mips_emit_binary, mips_relational_operand_ok_p) + (mips_emit_int_relational, mips_zero_if_equal) + (mips_emit_scc): New functions. + (gen_conditional_branch): Rework to use mips_emit_int_relational. + * config/mips/mips.h (PREDICATE_CODES): Add sle_operand and + sleu_operand. + * config/mips/mips.md (seq, sne, sgt, sge, slt, sle, sgtu, sgeu) + (sltu, sleu): Use mips_emit_scc. + (*sge_[sd]i, *sgeu_[sd]i): New patterns. + (*sle_[sd]i, *sle_[sd]i_mips16): Use sle_operand. + (*sleu_[sd]i, *sleu_[sd]i_mips16): Use sleu_operand. + 2004-07-16 Richard Sandiford * config/mips/mips.md (*sgt_di_mips16): Fix destination constraint. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 820d75f9cc0..73a7e75ad92 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -123,7 +123,7 @@ extern void mips_split_64bit_move (rtx, rtx); extern const char *mips_output_move (rtx, rtx); extern rtx mips_gp_save_slot (void); #ifdef RTX_CODE -extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); +extern bool mips_emit_scc (enum rtx_code, rtx); extern void gen_conditional_branch (rtx *, enum rtx_code); #endif extern void gen_conditional_move (rtx *); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index aed4d94d19c..648abbf00d2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -57,24 +57,6 @@ Boston, MA 02111-1307, USA. */ #include "sched-int.h" #include "tree-gimple.h" -/* Enumeration for all of the relational tests, so that we can build - arrays indexed by the test type, and not worry about the order - of EQ, NE, etc. */ - -enum internal_test { - ITEST_EQ, - ITEST_NE, - ITEST_GT, - ITEST_GE, - ITEST_LT, - ITEST_LE, - ITEST_GTU, - ITEST_GEU, - ITEST_LTU, - ITEST_LEU, - ITEST_MAX -}; - /* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ (GET_CODE (X) == UNSPEC \ @@ -193,7 +175,6 @@ static void mips_legitimize_const_move (enum machine_mode, rtx, rtx); static int m16_check_op (rtx, int, int, int); static bool mips_rtx_costs (rtx, int, int, int *); static int mips_address_cost (rtx); -static enum internal_test map_test_to_internal_test (enum rtx_code); static void get_float_compare_codes (enum rtx_code, enum rtx_code *, enum rtx_code *); static void mips_load_call_address (rtx, rtx, int); @@ -1343,6 +1324,24 @@ arith_operand (rtx op, enum machine_mode mode) return const_arith_operand (op, mode) || register_operand (op, mode); } +/* Return true if OP can be used as the second argument to an LE operation. */ + +int +sle_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +{ + return GET_CODE (op) == CONST_INT && SMALL_OPERAND (INTVAL (op) + 1); +} + +/* Likewise LEU. */ + +int +sleu_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +{ + return (GET_CODE (op) == CONST_INT + && INTVAL (op) + 1 != 0 + && SMALL_OPERAND (INTVAL (op) + 1)); +} + /* Return truth value of whether OP is an integer which fits in 16 bits. */ int @@ -2691,248 +2690,117 @@ mips_gp_save_slot (void) return loc; } -/* Make normal rtx_code into something we can index from an array */ +/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */ -static enum internal_test -map_test_to_internal_test (enum rtx_code test_code) +static void +mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1) { - enum internal_test test = ITEST_MAX; - - switch (test_code) - { - case EQ: test = ITEST_EQ; break; - case NE: test = ITEST_NE; break; - case GT: test = ITEST_GT; break; - case GE: test = ITEST_GE; break; - case LT: test = ITEST_LT; break; - case LE: test = ITEST_LE; break; - case GTU: test = ITEST_GTU; break; - case GEU: test = ITEST_GEU; break; - case LTU: test = ITEST_LTU; break; - case LEU: test = ITEST_LEU; break; - default: break; - } - - return test; + emit_insn (gen_rtx_SET (VOIDmode, target, + gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1))); } - -/* Generate the code to compare two integer values. The return value is: - (reg:SI xx) The pseudo register the comparison is in - 0 No register, generate a simple branch. - - ??? This is called with result nonzero by the Scond patterns in - mips.md. These patterns are called with a target in the mode of - the Scond instruction pattern. Since this must be a constant, we - must use SImode. This means that if RESULT is nonzero, it will - always be an SImode register, even if TARGET_64BIT is true. We - cope with this by calling convert_move rather than emit_move_insn. - This will sometimes lead to an unnecessary extension of the result; - for example: - - long long - foo (long long i) - { - return i < 5; - } - - TEST_CODE is the rtx code for the comparison. - CMP0 and CMP1 are the two operands to compare. - RESULT is the register in which the result should be stored (null for - branches). - For branches, P_INVERT points to an integer that is nonzero on return - if the branch should be inverted. */ - -rtx -gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, - rtx cmp1, int *p_invert) -{ - struct cmp_info - { - enum rtx_code test_code; /* code to use in instruction (LT vs. LTU) */ - int const_low; /* low bound of constant we can accept */ - int const_high; /* high bound of constant we can accept */ - int const_add; /* constant to add (convert LE -> LT) */ - int reverse_regs; /* reverse registers in test */ - int invert_const; /* != 0 if invert value if cmp1 is constant */ - int invert_reg; /* != 0 if invert value if cmp1 is register */ - int unsignedp; /* != 0 for unsigned comparisons. */ - }; - - static const struct cmp_info info[ (int)ITEST_MAX ] = { - - { XOR, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */ - { XOR, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */ - { LT, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */ - { LT, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */ - { LT, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */ - { LT, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */ - { LTU, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */ - { LTU, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */ - { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */ - { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */ - }; - - enum internal_test test; - enum machine_mode mode; - const struct cmp_info *p_info; - int branch_p; - int eqne_p; - int invert; - rtx reg; - rtx reg2; - - test = map_test_to_internal_test (test_code); - if (test == ITEST_MAX) - abort (); - - p_info = &info[(int) test]; - eqne_p = (p_info->test_code == XOR); - - mode = GET_MODE (cmp0); - if (mode == VOIDmode) - mode = GET_MODE (cmp1); +/* Return true if CMP1 is a suitable second operand for relational + operator CODE. See also the *sCC patterns in mips.md. */ - /* Eliminate simple branches. */ - branch_p = (result == 0); - if (branch_p) +static bool +mips_relational_operand_ok_p (enum rtx_code code, rtx cmp1) +{ + switch (code) { - if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG) - { - /* Comparisons against zero are simple branches. */ - if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0 - && (! TARGET_MIPS16 || eqne_p)) - return 0; - - /* Test for beq/bne. */ - if (eqne_p && ! TARGET_MIPS16) - return 0; - } - - /* Allocate a pseudo to calculate the value in. */ - result = gen_reg_rtx (mode); - } + case GT: + case GTU: + return reg_or_0_operand (cmp1, VOIDmode); - /* Make sure we can handle any constants given to us. */ - if (GET_CODE (cmp0) == CONST_INT) - cmp0 = force_reg (mode, cmp0); + case GE: + case GEU: + return !TARGET_MIPS16 && cmp1 == const1_rtx; - if (GET_CODE (cmp1) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (cmp1); + case LT: + case LTU: + return arith_operand (cmp1, VOIDmode); - if (value < p_info->const_low - || value > p_info->const_high - /* ??? Why? And why wasn't the similar code below modified too? */ - || (TARGET_64BIT - && HOST_BITS_PER_WIDE_INT < 64 - && p_info->const_add != 0 - && ((p_info->unsignedp - ? ((unsigned HOST_WIDE_INT) (value + p_info->const_add) - > (unsigned HOST_WIDE_INT) INTVAL (cmp1)) - : (value + p_info->const_add) > INTVAL (cmp1)) - != (p_info->const_add > 0)))) - cmp1 = force_reg (mode, cmp1); - } + case LE: + return sle_operand (cmp1, VOIDmode); - /* See if we need to invert the result. */ - invert = (GET_CODE (cmp1) == CONST_INT - ? p_info->invert_const : p_info->invert_reg); + case LEU: + return sleu_operand (cmp1, VOIDmode); - if (p_invert != (int *)0) - { - *p_invert = invert; - invert = 0; + default: + abort (); } +} - /* Comparison to constants, may involve adding 1 to change a LT into LE. - Comparison between two registers, may involve switching operands. */ - if (GET_CODE (cmp1) == CONST_INT) - { - if (p_info->const_add != 0) - { - HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add; - - /* If modification of cmp1 caused overflow, - we would get the wrong answer if we follow the usual path; - thus, x > 0xffffffffU would turn into x > 0U. */ - if ((p_info->unsignedp - ? (unsigned HOST_WIDE_INT) new > - (unsigned HOST_WIDE_INT) INTVAL (cmp1) - : new > INTVAL (cmp1)) - != (p_info->const_add > 0)) - { - /* This test is always true, but if INVERT is true then - the result of the test needs to be inverted so 0 should - be returned instead. */ - emit_move_insn (result, invert ? const0_rtx : const_true_rtx); - return result; - } - else - cmp1 = GEN_INT (new); - } - } +/* Compare CMP0 and CMP1 using relational operator CODE and store the + result in TARGET. CMP0 and TARGET are register_operands that have + the same integer mode. If INVERT_PTR is nonnull, it's OK to set + TARGET to the inverse of the result and flip *INVERT_PTR instead. */ - else if (p_info->reverse_regs) - { - rtx temp = cmp0; - cmp0 = cmp1; - cmp1 = temp; - } - - if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) - reg = cmp0; +static void +mips_emit_int_relational (enum rtx_code code, bool *invert_ptr, + rtx target, rtx cmp0, rtx cmp1) +{ + /* First see if there is a MIPS instruction that can do this operation + with CMP1 in its current form. If not, try doing the same for the + inverse operation. If that also fails, force CMP1 into a register + and try again. */ + if (mips_relational_operand_ok_p (code, cmp1)) + mips_emit_binary (code, target, cmp0, cmp1); else { - reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result; - convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, - mode, cmp0, cmp1), 0); - } - - if (test == ITEST_NE) - { - if (! TARGET_MIPS16) + enum rtx_code inv_code = reverse_condition (code); + if (!mips_relational_operand_ok_p (inv_code, cmp1)) + { + cmp1 = force_reg (GET_MODE (cmp0), cmp1); + mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1); + } + else if (invert_ptr == 0) { - convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0); - if (p_invert != NULL) - *p_invert = 0; - invert = 0; + rtx inv_target = gen_reg_rtx (GET_MODE (target)); + mips_emit_binary (inv_code, inv_target, cmp0, cmp1); + mips_emit_binary (XOR, target, inv_target, const1_rtx); } else { - reg2 = invert ? gen_reg_rtx (mode) : result; - convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0); - reg = reg2; + *invert_ptr = !*invert_ptr; + mips_emit_binary (inv_code, target, cmp0, cmp1); } } +} - else if (test == ITEST_EQ) - { - reg2 = invert ? gen_reg_rtx (mode) : result; - convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0); - reg = reg2; - } +/* Return a register that is zero iff CMP0 and CMP1 are equal. + The register will have the same mode as CMP0. */ - if (invert) - { - rtx one; +static rtx +mips_zero_if_equal (rtx cmp0, rtx cmp1) +{ + if (cmp1 == const0_rtx) + return cmp0; - if (! TARGET_MIPS16) - one = const1_rtx; - else - { - /* The value is in $24. Copy it to another register, so - that reload doesn't think it needs to store the $24 and - the input to the XOR in the same location. */ - reg2 = gen_reg_rtx (mode); - emit_move_insn (reg2, reg); - reg = reg2; - one = force_reg (mode, const1_rtx); - } - convert_move (result, gen_rtx_XOR (mode, reg, one), 0); - } + return expand_binop (GET_MODE (cmp0), xor_optab, + cmp0, cmp1, 0, 0, OPTAB_DIRECT); +} - return result; +/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE. + Store the result in TARGET and return true if successful. + + On 64-bit targets, TARGET may be wider than cmp_operands[0]. */ + +bool +mips_emit_scc (enum rtx_code code, rtx target) +{ + if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) + return false; + + target = gen_lowpart (GET_MODE (cmp_operands[0]), target); + if (code == EQ || code == NE) + { + rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + mips_emit_binary (code, target, zie, const0_rtx); + } + else + mips_emit_int_relational (code, 0, target, + cmp_operands[0], cmp_operands[1]); + return true; } /* Work out how to check a floating-point condition. We need a @@ -2970,74 +2838,67 @@ get_float_compare_codes (enum rtx_code in_code, enum rtx_code *cmp_code, void gen_conditional_branch (rtx *operands, enum rtx_code test_code) { - rtx cmp0 = cmp_operands[0]; - rtx cmp1 = cmp_operands[1]; + rtx cmp0, cmp1, target; enum machine_mode mode; enum rtx_code cmp_code; - rtx reg; - int invert; - rtx label1, label2; - switch (GET_MODE (cmp0)) + switch (GET_MODE (cmp_operands[0])) { case SImode: case DImode: - mode = GET_MODE (cmp0); - invert = 0; - reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - - if (reg) + mode = GET_MODE (cmp_operands[0]); + if (!TARGET_MIPS16 && cmp_operands[1] == const0_rtx) + { + cmp0 = cmp_operands[0]; + cmp1 = cmp_operands[1]; + } + else if (test_code == EQ || test_code == NE) + { + if (TARGET_MIPS16) + { + cmp0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + cmp1 = const0_rtx; + } + else + { + cmp0 = cmp_operands[0]; + cmp1 = force_reg (mode, cmp_operands[1]); + } + } + else { - cmp0 = reg; + bool invert = false; + cmp0 = gen_reg_rtx (mode); cmp1 = const0_rtx; - test_code = NE; + mips_emit_int_relational (test_code, &invert, cmp0, + cmp_operands[0], cmp_operands[1]); + test_code = (invert ? EQ : NE); } - else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) - /* We don't want to build a comparison against a nonzero - constant. */ - cmp1 = force_reg (mode, cmp1); - break; case SFmode: case DFmode: - if (! ISA_HAS_8CC) - reg = gen_rtx_REG (CCmode, FPSW_REGNUM); + mode = CCmode; + if (!ISA_HAS_8CC) + cmp0 = gen_rtx_REG (mode, FPSW_REGNUM); else - reg = gen_reg_rtx (CCmode); + cmp0 = gen_reg_rtx (mode); + cmp1 = const0_rtx; get_float_compare_codes (test_code, &cmp_code, &test_code); - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_fmt_ee (cmp_code, CCmode, cmp0, cmp1))); - - mode = CCmode; - cmp0 = reg; - cmp1 = const0_rtx; - invert = 0; + mips_emit_binary (cmp_code, cmp0, cmp_operands[0], cmp_operands[1]); break; default: - fatal_insn ("bad test", - gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); + abort (); } /* Generate the branch. */ - - label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); - label2 = pc_rtx; - - if (invert) - { - label2 = label1; - label1 = pc_rtx; - } - - emit_jump_insn - (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (test_code, mode, - cmp0, cmp1), - label1, label2))); + target = gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_fmt_ee (test_code, mode, cmp0, cmp1), + gen_rtx_LABEL_REF (VOIDmode, operands[0]), + pc_rtx); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, target)); } /* Emit the common code for conditional moves. OPERANDS is the array diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 562374ae529..f0f06ada15c 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2727,6 +2727,8 @@ typedef struct mips_args { UNSPEC_VOLATILE }}, \ {"arith_operand", { REG, CONST_INT, CONST, SUBREG }}, \ {"reg_or_0_operand", { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \ + {"sle_operand", { CONST_INT }}, \ + {"sleu_operand", { CONST_INT }}, \ {"small_int", { CONST_INT }}, \ {"const_float_1_operand", { CONST_DOUBLE }}, \ {"reg_or_const_float_1_operand", { CONST_DOUBLE, REG}}, \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index cad6dbfdb45..08f04f8ded3 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -6012,14 +6012,7 @@ dsrl\t%3,%3,1\n\ (eq:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (EQ, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) - + { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; }) (define_insn "*seq_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6057,20 +6050,15 @@ dsrl\t%3,%3,1\n\ [(set_attr "type" "slt") (set_attr "mode" "DI")]) -;; On the mips16 the default code is better than using sltu. +;; "sne" uses sltu instructions in which the first operand is $0. +;; This isn't possible in mips16 code. (define_expand "sne" [(set (match_operand:SI 0 "register_operand") (ne:SI (match_dup 1) (match_dup 2)))] "!TARGET_MIPS16" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (NE, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; }) (define_insn "*sne_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6095,13 +6083,7 @@ dsrl\t%3,%3,1\n\ (gt:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (GT, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; }) (define_insn "*sgt_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6144,26 +6126,32 @@ dsrl\t%3,%3,1\n\ (ge:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; + { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; }) - gen_int_relational (GE, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) +(define_insn "*sge_si" + [(set (match_operand:SI 0 "register_operand" "=d") + (ge:SI (match_operand:SI 1 "register_operand" "d") + (const_int 1)))] + "!TARGET_MIPS16" + "slt\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) + +(define_insn "*sge_di" + [(set (match_operand:DI 0 "register_operand" "=d") + (ge:DI (match_operand:DI 1 "register_operand" "d") + (const_int 1)))] + "TARGET_64BIT && !TARGET_MIPS16" + "slt\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "slt" [(set (match_operand:SI 0 "register_operand") (lt:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (LT, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; }) (define_insn "*slt_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6216,19 +6204,13 @@ dsrl\t%3,%3,1\n\ (le:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (LE, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; }) (define_insn "*sle_si" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:SI 2 "sle_operand" "")))] + "!TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "slt\t%0,%1,%2"; @@ -6239,8 +6221,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sle_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:SI 2 "sle_operand" "")))] + "TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "slt\t%1,%2"; @@ -6254,8 +6236,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sle_di" [(set (match_operand:DI 0 "register_operand" "=d") (le:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:DI 2 "sle_operand" "")))] + "TARGET_64BIT && !TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "slt\t%0,%1,%2"; @@ -6266,8 +6248,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sle_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t") (le:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:DI 2 "sle_operand" "")))] + "TARGET_64BIT && TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "slt\t%1,%2"; @@ -6283,13 +6265,7 @@ dsrl\t%3,%3,1\n\ (gtu:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (GTU, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; }) (define_insn "*sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6332,26 +6308,32 @@ dsrl\t%3,%3,1\n\ (geu:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; + { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; }) - gen_int_relational (GEU, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) +(define_insn "*sge_si" + [(set (match_operand:SI 0 "register_operand" "=d") + (geu:SI (match_operand:SI 1 "register_operand" "d") + (const_int 1)))] + "!TARGET_MIPS16" + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) + +(define_insn "*sge_di" + [(set (match_operand:DI 0 "register_operand" "=d") + (geu:DI (match_operand:DI 1 "register_operand" "d") + (const_int 1)))] + "TARGET_64BIT && !TARGET_MIPS16" + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "sltu" [(set (match_operand:SI 0 "register_operand") (ltu:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (LTU, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; }) (define_insn "*sltu_si" [(set (match_operand:SI 0 "register_operand" "=d") @@ -6404,19 +6386,13 @@ dsrl\t%3,%3,1\n\ (leu:SI (match_dup 1) (match_dup 2)))] "" -{ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - FAIL; - - gen_int_relational (LEU, operands[0], cmp_operands[0], cmp_operands[1], NULL); - DONE; -}) + { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; }) (define_insn "*sleu_si" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:SI 2 "sleu_operand" "")))] + "!TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "sltu\t%0,%1,%2"; @@ -6427,8 +6403,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sleu_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:SI 2 "sleu_operand" "")))] + "TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "sltu\t%1,%2"; @@ -6442,8 +6418,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sleu_di" [(set (match_operand:DI 0 "register_operand" "=d") (leu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:DI 2 "sleu_operand" "")))] + "TARGET_64BIT && !TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "sltu\t%0,%1,%2"; @@ -6454,8 +6430,8 @@ dsrl\t%3,%3,1\n\ (define_insn "*sleu_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t") (leu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" + (match_operand:DI 2 "sleu_operand" "")))] + "TARGET_64BIT && TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); return "sltu\t%1,%2"; -- 2.30.2