diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 27 | ||||
-rw-r--r-- | gcc/combine.c | 176 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 316 |
4 files changed, 239 insertions, 281 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b1d8c07..a04f135 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +Fri Jan 12 00:04:00 MET 2001 Jan Hubicka <jh@suse.cz> + + * i386.c (ix86_comparison_operator, fcmov_comparison_operator, + put_condition_code): Convert fp comparison codes to integer + before handling. + (ix86_expand_fp_compare): Postnote the fp comparison code converison + to final. + + * i386.c (unsigned_comparison, no_comparison_operator): Kill. + * i386-protos.h (no_comparison_operator): Kill. + + * i386.c (ix86_expand_fp_compare): Fix ordered/unordered confussion. + + * combine.c (REVERSIBLE_CC_MODE): Remove. + (reversible_comparison_p): Remove. + (combine_reversed_comparison_code): New. + (reversed_comparison): New. + (combine_simplify_rtx): Use + combine_reversed_comparison_code/reversed_comparison instead + of reversible_comparison_p. + (simplify_if_then_else): Likewise. + (simplify_set): Likewise. + (simplify_logical): Likewise. + (if_then_else_cond): Likewise. + (known_cond): Likewise. + (simplify_comparison): Likewise. + 2001-01-11 Alan Lehotsky <lehotsky@tiac.net> * builtins.c (std_expand_builtin_va_start): Handle varargs when diff --git a/gcc/combine.c b/gcc/combine.c index b8a2e04..53857ed 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -131,12 +131,6 @@ static int combine_successes; static int total_attempts, total_merges, total_extras, total_successes; -/* Define a default value for REVERSIBLE_CC_MODE. - We can never assume that a condition code mode is safe to reverse unless - the md tells us so. */ -#ifndef REVERSIBLE_CC_MODE -#define REVERSIBLE_CC_MODE(MODE) 0 -#endif /* Vector mapping INSN_UIDs to cuids. The cuids are like uids but increase monotonically always. @@ -414,7 +408,6 @@ static rtx gen_binary PARAMS ((enum rtx_code, enum machine_mode, static rtx gen_unary PARAMS ((enum rtx_code, enum machine_mode, enum machine_mode, rtx)); static enum rtx_code simplify_comparison PARAMS ((enum rtx_code, rtx *, rtx *)); -static int reversible_comparison_p PARAMS ((rtx)); static void update_table_tick PARAMS ((rtx)); static void record_value_for_reg PARAMS ((rtx, rtx, rtx)); static void check_promoted_subreg PARAMS ((rtx, rtx)); @@ -432,6 +425,8 @@ static void distribute_links PARAMS ((rtx)); static void mark_used_regs_combine PARAMS ((rtx)); static int insn_cuid PARAMS ((rtx)); static void record_promoted_value PARAMS ((rtx, rtx)); +static rtx reversed_comparison PARAMS ((rtx, enum machine_mode, rtx, rtx)); +static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx)); /* Substitute NEWVAL, an rtx expression, into INTO, a place in some insn. The substitution can be undone by undo_all. If INTO is already @@ -3501,6 +3496,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) enum rtx_code code = GET_CODE (x); enum machine_mode mode = GET_MODE (x); rtx temp; + rtx reversed; int i; /* If this is a commutative operation, put a constant last and a complex @@ -3922,10 +3918,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) reversing the comparison code if valid. */ if (STORE_FLAG_VALUE == -1 && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' - && reversible_comparison_p (XEXP (x, 0))) - return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))), - mode, XEXP (XEXP (x, 0), 0), - XEXP (XEXP (x, 0), 1)); + && (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0), + XEXP (XEXP (x, 0), 1)))) + return reversed; /* (ashiftrt foo C) where C is the number of bits in FOO minus 1 is (lt foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can @@ -4218,14 +4213,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) is 1. This produces better code than the alternative immediately below. */ if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' - && reversible_comparison_p (XEXP (x, 0)) && ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx) - || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx))) + || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)) + && (reversed = reversed_comparison (XEXP (x, 0), mode, + XEXP (XEXP (x, 0), 0), + XEXP (XEXP (x, 0), 1)))) return - gen_unary (NEG, mode, mode, - gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))), - mode, XEXP (XEXP (x, 0), 0), - XEXP (XEXP (x, 0), 1))); + gen_unary (NEG, mode, mode, reversed); /* If only the low-order bit of X is possibly nonzero, (plus x -1) can become (ashiftrt (ashift (xor x 1) C) C) where C is @@ -4270,10 +4264,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) if (STORE_FLAG_VALUE == 1 && XEXP (x, 0) == const1_rtx && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<' - && reversible_comparison_p (XEXP (x, 1))) - return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode, - XEXP (XEXP (x, 1), 0), - XEXP (XEXP (x, 1), 1)); + && (reversed = reversed_comparison (XEXP (x, 1), mode, + XEXP (XEXP (x, 1), 0), + XEXP (XEXP (x, 1), 1)))) + return reversed; /* (minus <foo> (and <foo> (const_int -pow2))) becomes (and <foo> (const_int pow2-1)) */ @@ -4626,27 +4620,31 @@ simplify_if_then_else (x) int comparison_p = GET_RTX_CLASS (true_code) == '<'; rtx temp; int i; + enum rtx_code false_code; + rtx reversed; /* Simplify storing of the truth value. */ if (comparison_p && true == const_true_rtx && false == const0_rtx) return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1)); /* Also when the truth value has to be reversed. */ - if (comparison_p && reversible_comparison_p (cond) - && true == const0_rtx && false == const_true_rtx) - return gen_binary (reverse_condition (true_code), - mode, XEXP (cond, 0), XEXP (cond, 1)); + if (comparison_p + && true == const0_rtx && false == const_true_rtx + && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0), + XEXP (cond, 1)))) + return reversed; /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used in it is being compared against certain values. Get the true and false comparisons and see if that says anything about the value of each arm. */ - if (comparison_p && reversible_comparison_p (cond) + if (comparison_p + && ((false_code = combine_reversed_comparison_code (cond)) + != UNKNOWN) && GET_CODE (XEXP (cond, 0)) == REG) { HOST_WIDE_INT nzb; rtx from = XEXP (cond, 0); - enum rtx_code false_code = reverse_condition (true_code); rtx true_val = XEXP (cond, 1); rtx false_val = true_val; int swapped = 0; @@ -4695,7 +4693,8 @@ simplify_if_then_else (x) arm, the false arm is the same as the first operand of the comparison, or the false arm is more complicated than the true arm. */ - if (comparison_p && reversible_comparison_p (cond) + if (comparison_p + && combine_reversed_comparison_code (cond) != UNKNOWN && (true == pc_rtx || (CONSTANT_P (true) && GET_CODE (false) != CONST_INT && false != pc_rtx) @@ -4708,10 +4707,10 @@ simplify_if_then_else (x) || reg_mentioned_p (true, false) || rtx_equal_p (false, XEXP (cond, 0)))) { - true_code = reverse_condition (true_code); + true_code = reversed_comparison_code (cond, NULL); SUBST (XEXP (x, 0), - gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0), - XEXP (cond, 1))); + reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0), + XEXP (cond, 1))); SUBST (XEXP (x, 1), false); SUBST (XEXP (x, 2), true); @@ -5211,6 +5210,7 @@ simplify_set (x) rtx cond = XEXP (src, 0); rtx true_val = const1_rtx; rtx false_arm, true_arm; + rtx reversed; if (GET_CODE (cond) == MULT) { @@ -5236,16 +5236,16 @@ simplify_set (x) /* Canonicalize if true_arm is the simpler one. */ if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o' && GET_RTX_CLASS (GET_CODE (false_arm)) != 'o' - && reversible_comparison_p (cond)) + && (reversed = reversed_comparison_code (cond, GET_MODE (cond), + XEXP (cond, 0), + XEXP (cond, 1)))) { rtx temp = true_arm; true_arm = false_arm; false_arm = temp; - cond = gen_rtx_combine (reverse_condition (GET_CODE (cond)), - GET_MODE (cond), XEXP (cond, 0), - XEXP (cond, 1)); + cond = reversed; } src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src), @@ -5279,6 +5279,7 @@ simplify_logical (x, last) enum machine_mode mode = GET_MODE (x); rtx op0 = XEXP (x, 0); rtx op1 = XEXP (x, 1); + rtx reversed; switch (GET_CODE (x)) { @@ -5530,9 +5531,9 @@ simplify_logical (x, last) if (STORE_FLAG_VALUE == 1 && op1 == const1_rtx && GET_RTX_CLASS (GET_CODE (op0)) == '<' - && reversible_comparison_p (op0)) - return gen_rtx_combine (reverse_condition (GET_CODE (op0)), - mode, XEXP (op0, 0), XEXP (op0, 1)); + && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0), + XEXP (op0, 1)))) + return reversed; /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 is (lt foo (const_int 0)), so we can perform the above @@ -5552,9 +5553,9 @@ simplify_logical (x, last) == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && op1 == const_true_rtx && GET_RTX_CLASS (GET_CODE (op0)) == '<' - && reversible_comparison_p (op0)) - return gen_rtx_combine (reverse_condition (GET_CODE (op0)), - mode, XEXP (op0, 0), XEXP (op0, 1)); + && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0), + XEXP (op0, 1)))) + return reversed; break; @@ -7344,12 +7345,11 @@ if_then_else_cond (x, ptrue, pfalse) if (GET_RTX_CLASS (GET_CODE (cond0)) == '<' && GET_RTX_CLASS (GET_CODE (cond1)) == '<' - && reversible_comparison_p (cond1) - && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1)) + && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) || ((swap_condition (GET_CODE (cond0)) - == reverse_condition (GET_CODE (cond1))) + == combine_reversed_comparison_code (cond1)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && ! side_effects_p (x)) @@ -7374,12 +7374,11 @@ if_then_else_cond (x, ptrue, pfalse) if (GET_RTX_CLASS (GET_CODE (cond0)) == '<' && GET_RTX_CLASS (GET_CODE (cond1)) == '<' - && reversible_comparison_p (cond1) - && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1)) + && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) || ((swap_condition (GET_CODE (cond0)) - == reverse_condition (GET_CODE (cond1))) + == combine_reversed_comparison_code (cond1)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && ! side_effects_p (x)) @@ -7527,7 +7526,7 @@ known_cond (x, cond, reg, val) if (comparison_dominates_p (cond, code)) return const_true_rtx; - code = reverse_condition (code); + code = combine_reversed_comparison_code (x); if (code != UNKNOWN && comparison_dominates_p (cond, code)) return const0_rtx; @@ -10705,20 +10704,21 @@ simplify_comparison (code, pop0, pop1) /* Check for the cases where we simply want the result of the earlier test or the opposite of that result. */ - if (code == NE - || (code == EQ && reversible_comparison_p (op0)) + if (code == NE || code == EQ || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && (STORE_FLAG_VALUE & (((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) - && (code == LT - || (code == GE && reversible_comparison_p (op0))))) + && (code == LT || (code == GE)))) { code = (code == LT || code == NE - ? GET_CODE (op0) : reverse_condition (GET_CODE (op0))); - op0 = tem, op1 = tem1; - continue; + ? GET_CODE (op0) : combine_reversed_comparison_code (op0)); + if (code != UNKNOWN) + { + op0 = tem, op1 = tem1; + continue; + } } break; @@ -11121,42 +11121,38 @@ simplify_comparison (code, pop0, pop1) return code; } -/* Return 1 if we know that X, a comparison operation, is not operating - on a floating-point value or is EQ or NE, meaning that we can safely - reverse it. */ - -static int -reversible_comparison_p (x) - rtx x; +/* Like jump.c' reversed_comparison_code, but use combine infrastructure for + searching backward. */ +enum rtx_code +combine_reversed_comparison_code (exp) + rtx exp; { - if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT - || flag_fast_math - || GET_CODE (x) == NE || GET_CODE (x) == EQ - || GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED) - return 1; - - switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0)))) - { - case MODE_INT: - case MODE_PARTIAL_INT: - case MODE_COMPLEX_INT: - return 1; - - case MODE_CC: - /* If the mode of the condition codes tells us that this is safe, - we need look no further. */ - if (REVERSIBLE_CC_MODE (GET_MODE (XEXP (x, 0)))) - return 1; - - /* Otherwise try and find where the condition codes were last set and - use that. */ - x = get_last_value (XEXP (x, 0)); - return (x && GET_CODE (x) == COMPARE - && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))); - - default: - return 0; - } + enum rtx_code code1 = reversed_comparison_code (exp, NULL); + rtx x; + + if (code1 != UNKNOWN + || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC) + return code1; + /* Otherwise try and find where the condition codes were last set and + use that. */ + x = get_last_value (XEXP (x, 0)); + if (GET_CODE (x) != COMPARE) + return UNKNOWN; + return reversed_comparison_code_parts (GET_CODE (exp), + XEXP (x, 0), XEXP (x, 1), NULL); +} +/* Return comparison with reversed code of EXP and operands OP0 and OP1. + Return NULL_RTX in case we fail to do the reversal. */ +static rtx +reversed_comparison (exp, mode, op0, op1) + rtx exp, op0, op1; + enum machine_mode mode; +{ + enum rtx_code reversed_code = combine_reversed_comparison_code (exp); + if (reversed_code == UNKNOWN) + return NULL_RTX; + else + return gen_binary (reversed_code, mode, op0, op1); } /* Utility function for following routine. Called when X is part of a value diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index e000dca..42481fb 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -56,7 +56,6 @@ extern int general_no_elim_operand PARAMS ((rtx, enum machine_mode)); extern int nonmemory_no_elim_operand PARAMS ((rtx, enum machine_mode)); extern int q_regs_operand PARAMS ((rtx, enum machine_mode)); extern int non_q_regs_operand PARAMS ((rtx, enum machine_mode)); -extern int no_comparison_operator PARAMS ((rtx, enum machine_mode)); extern int sse_comparison_operator PARAMS ((rtx, enum machine_mode)); extern int fcmov_comparison_operator PARAMS ((rtx, enum machine_mode)); extern int cmp_fp_expander_operand PARAMS ((rtx, enum machine_mode)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 72dbb9a..50ac27b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -386,7 +386,6 @@ int ix86_align_jumps; static void output_pic_addr_const PARAMS ((FILE *, rtx, int)); static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode, int, int, FILE *)); -static enum rtx_code unsigned_comparison PARAMS ((enum rtx_code code)); static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx)); static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code, rtx *, rtx *)); @@ -1267,30 +1266,6 @@ non_q_regs_operand (op, mode) return NON_QI_REG_P (op); } -/* Return 1 if OP is a comparison operator that can use the condition code - generated by a logical operation, which characteristicly does not set - overflow or carry. To be used with CCNOmode. */ - -int -no_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; - - switch (GET_CODE (op)) - { - case EQ: case NE: - case LT: case GE: - case LEU: case LTU: case GEU: case GTU: - return 1; - - default: - return 0; - } -} - /* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS insns. */ int @@ -1308,25 +1283,33 @@ ix86_comparison_operator (op, mode) enum machine_mode mode; { enum machine_mode inmode; + enum rtx_code code = GET_CODE (op); if (mode != VOIDmode && GET_MODE (op) != mode) return 0; - switch (GET_CODE (op)) + if (GET_RTX_CLASS (code) != '<') + return 0; + inmode = GET_MODE (XEXP (op, 0)); + + if (inmode == CCFPmode || inmode == CCFPUmode) + { + enum rtx_code second_code, bypass_code; + ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); + return (bypass_code == NIL && second_code == NIL); + } + switch (code) { case EQ: case NE: return 1; case LT: case GE: - inmode = GET_MODE (XEXP (op, 0)); if (inmode == CCmode || inmode == CCGCmode || inmode == CCGOCmode || inmode == CCNOmode) return 1; return 0; case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU: - inmode = GET_MODE (XEXP (op, 0)); if (inmode == CCmode) return 1; return 0; case GT: case LE: - inmode = GET_MODE (XEXP (op, 0)); if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode) return 1; return 0; @@ -1343,16 +1326,30 @@ fcmov_comparison_operator (op, mode) enum machine_mode mode; { enum machine_mode inmode = GET_MODE (XEXP (op, 0)); + enum rtx_code code = GET_CODE (op); if (mode != VOIDmode && GET_MODE (op) != mode) return 0; - switch (GET_CODE (op)) + if (GET_RTX_CLASS (code) != '<') + return 0; + inmode = GET_MODE (XEXP (op, 0)); + if (inmode == CCFPmode || inmode == CCFPUmode) { - case EQ: case NE: - return 1; - case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU: - if (inmode == CCFPmode || inmode == CCFPUmode) + enum rtx_code second_code, bypass_code; + ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); + if (bypass_code != NIL || second_code != NIL) + return 0; + code = ix86_fp_compare_code_to_integer (code); + } + /* i387 supports just limited amount of conditional codes. */ + switch (code) + { + case LTU: case GTU: case LEU: case GEU: + if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode) return 1; return 0; + case ORDERED: case UNORDERED: + case EQ: case NE: + return 1; default: return 0; } @@ -3102,6 +3099,15 @@ put_condition_code (code, mode, reverse, fp, file) { const char *suffix; + if (mode == CCFPmode || mode == CCFPUmode) + { + enum rtx_code second_code, bypass_code; + ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); + if (bypass_code != NIL || second_code != NIL) + abort(); + code = ix86_fp_compare_code_to_integer (code); + mode = CCmode; + } if (reverse) code = reverse_condition (code); @@ -4611,41 +4617,6 @@ ix86_match_ccmode (insn, req_mode) return (GET_MODE (SET_SRC (set)) == set_mode); } -/* Produce an unsigned comparison for a given signed comparison. */ - -static enum rtx_code -unsigned_comparison (code) - enum rtx_code code; -{ - switch (code) - { - case GT: - code = GTU; - break; - case LT: - code = LTU; - break; - case GE: - code = GEU; - break; - case LE: - code = LEU; - break; - case EQ: - case NE: - case LEU: - case LTU: - case GEU: - case GTU: - case UNORDERED: - case ORDERED: - break; - default: - abort (); - } - return code; -} - /* Generate insn patterns to do an integer compare of OPERANDS. */ static rtx @@ -4960,8 +4931,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch) } /* The FP codes work out to act like unsigned. */ - code = ix86_fp_compare_code_to_integer (first_code); - intcmp_mode = CCmode; + intcmp_mode = fpcmp_mode; } else { @@ -4970,153 +4940,119 @@ ix86_expand_fp_compare (code, op0, op1, scratch) tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9); emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2)); - if (fpcmp_mode == CCFPmode - || code == ORDERED - || code == UNORDERED) - { - /* We have two options here -- use sahf, or testing bits of ah - directly. On PPRO, they are equivalent, sahf being one byte - smaller. On Pentium, sahf is non-pairable while test is UV - pairable. */ - - /* - * The numbers below correspond to the bits of the FPSW in AH. - * C3, C2, and C0 are in bits 0x40, 0x4, and 0x01 respectively. - * - * cmp C3 C2 C0 - * > 0 0 0 - * < 0 0 1 - * = 1 0 0 - * un 1 1 1 - */ - - int mask; + /* In the unordered case, we have to check C2 for NaN's, which + doesn't happen to work out to anything nice combination-wise. + So do some bit twiddling on the value we've got in AH to come + up with an appropriate set of condition codes. */ - switch (code) - { - case GT: - mask = 0x41; - code = EQ; - break; - case LT: - mask = 0x01; - code = NE; - break; - case GE: - /* We'd have to use `xorb 1,ah; andb 0x41,ah', so it's - faster in all cases to just fall back on sahf. */ - goto do_sahf; - case LE: - mask = 0x41; - code = NE; - break; - case EQ: - mask = 0x40; - code = NE; - break; - case NE: - mask = 0x40; - code = EQ; - break; - case UNORDERED: - mask = 0x04; - code = NE; - break; - case ORDERED: - mask = 0x04; - code = EQ; - break; - - default: - abort (); - } - - emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (mask))); - intcmp_mode = CCNOmode; - } - else + intcmp_mode = CCNOmode; + switch (code) { - /* In the unordered case, we have to check C2 for NaN's, which - doesn't happen to work out to anything nice combination-wise. - So do some bit twiddling on the value we've got in AH to come - up with an appropriate set of condition codes. */ - - intcmp_mode = CCNOmode; - switch (code) + case GT: + case UNGT: + if (code == GT || !TARGET_IEEE_FP) { - case GT: emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45))); code = EQ; - break; - case LT: + } + else + { + emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); + emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx)); + emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44))); + intcmp_mode = CCmode; + code = GEU; + } + break; + case LT: + case UNLT: + if (code == LT && TARGET_IEEE_FP) + { emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01))); intcmp_mode = CCmode; code = EQ; - break; - case GE: + } + else + { + emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01))); + code = NE; + } + break; + case GE: + case UNGE: + if (code == GE || !TARGET_IEEE_FP) + { emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05))); code = EQ; - break; - case LE: + } + else + { + emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); + emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, + GEN_INT (0x01))); + code = NE; + } + break; + case LE: + case UNLE: + if (code == LE && TARGET_IEEE_FP) + { emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx)); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40))); intcmp_mode = CCmode; code = LTU; - break; - case EQ: + } + else + { + emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45))); + code = NE; + } + break; + case EQ: + case UNEQ: + if (code == EQ && TARGET_IEEE_FP) + { emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40))); intcmp_mode = CCmode; code = EQ; - break; - case NE: - emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); - emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x40))); - code = NE; - break; - - case UNORDERED: - emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04))); - code = NE; - break; - case ORDERED: - emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04))); - code = EQ; - break; - case UNEQ: + } + else + { emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40))); code = NE; break; - case UNGE: + } + break; + case NE: + case LTGT: + if (code == NE && TARGET_IEEE_FP) + { emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); - emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x01))); + emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, + GEN_INT (0x40))); code = NE; - break; - case UNGT: - emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); - emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx)); - emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44))); - intcmp_mode = CCmode; - code = GEU; - break; - case UNLE: - emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45))); - code = NE; - break; - case UNLT: - emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01))); - code = NE; - break; - case LTGT: + } + else + { emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40))); code = EQ; - break; - - default: - abort (); } + break; + + case UNORDERED: + emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04))); + code = NE; + break; + case ORDERED: + emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04))); + code = EQ; + break; + + default: + abort (); } } |