/* Generate insn patterns to do a floating point compare of OPERANDS. */
static rtx
-ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
+ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
{
bool unordered_compare = ix86_unordered_fp_compare (code);
- machine_mode intcmp_mode;
- rtx tmp, tmp2;
+ machine_mode cmp_mode;
+ rtx tmp, scratch;
code = ix86_prepare_fp_compare_args (code, &op0, &op1);
+ tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
+ if (unordered_compare)
+ tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+
/* Do fcomi/sahf based test when profitable. */
switch (ix86_fp_comparison_strategy (code))
{
case IX86_FPCMP_COMI:
- intcmp_mode = CCFPmode;
- tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
- if (unordered_compare)
- tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+ cmp_mode = CCFPmode;
emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
break;
case IX86_FPCMP_SAHF:
- intcmp_mode = CCFPmode;
- tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
- if (unordered_compare)
- tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
- tmp = gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp);
- if (!scratch)
- scratch = gen_reg_rtx (HImode);
- tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, tmp2)));
+ cmp_mode = CCFPmode;
+ tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
+ scratch = gen_reg_rtx (HImode);
+ emit_insn (gen_rtx_SET (scratch, tmp));
+ emit_insn (gen_x86_sahf_1 (scratch));
break;
case IX86_FPCMP_ARITH:
- /* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */
- tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
- if (unordered_compare)
- tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+ cmp_mode = CCNOmode;
tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
- if (!scratch)
- scratch = gen_reg_rtx (HImode);
+ scratch = gen_reg_rtx (HImode);
emit_insn (gen_rtx_SET (scratch, tmp));
/* In the unordered case, we have to check C2 for NaN's, which
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:
emit_insn (gen_andqi_ext_1 (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;
+ cmp_mode = CCmode;
code = GEU;
}
break;
{
emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
- intcmp_mode = CCmode;
+ cmp_mode = CCmode;
code = EQ;
}
else
emit_insn (gen_andqi_ext_1 (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;
+ cmp_mode = CCmode;
code = LTU;
}
else
{
emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
- intcmp_mode = CCmode;
+ cmp_mode = CCmode;
code = EQ;
}
else
/* Return the test that should be put into the flags user, i.e.
the bcc, scc, or cmov instruction. */
return gen_rtx_fmt_ee (code, VOIDmode,
- gen_rtx_REG (intcmp_mode, FLAGS_REG),
+ gen_rtx_REG (cmp_mode, FLAGS_REG),
const0_rtx);
}
else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
{
gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
- ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX);
+ ret = ix86_expand_fp_compare (code, op0, op1);
}
else
ret = ix86_expand_int_compare (code, op0, op1);
we decide to expand comparison using arithmetic that is not
too common scenario. */
start_sequence ();
- compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX);
+ compare_op = ix86_expand_fp_compare (code, op0, op1);
compare_seq = get_insns ();
end_sequence ();
(set_attr "unit" "i387")
(set_attr "mode" "XF")])
-(define_insn_and_split "*cmpxf_cc_i387"
- [(set (reg:CCFP FLAGS_REG)
- (compare:CCFP
- (match_operand:XF 1 "register_operand" "f")
- (match_operand:XF 2 "reg_or_0_operand" "fC")))
- (clobber (match_operand:HI 0 "register_operand" "=a"))]
- "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (unspec:HI
- [(compare:CCFP (match_dup 1)(match_dup 2))]
- UNSPEC_FNSTSW))
- (set (reg:CC FLAGS_REG)
- (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
- ""
- [(set_attr "type" "multi")
- (set_attr "unit" "i387")
- (set_attr "mode" "XF")])
-
(define_insn "*cmp<mode>_i387"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
(set_attr "unit" "i387")
(set_attr "mode" "<MODE>")])
-(define_insn_and_split "*cmp<mode>_cc_i387"
- [(set (reg:CCFP FLAGS_REG)
- (compare:CCFP
- (match_operand:MODEF 1 "register_operand" "f")
- (match_operand:MODEF 2 "nonimm_or_0_operand" "fmC")))
- (clobber (match_operand:HI 0 "register_operand" "=a"))]
- "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (unspec:HI
- [(compare:CCFP (match_dup 1)(match_dup 2))]
- UNSPEC_FNSTSW))
- (set (reg:CC FLAGS_REG)
- (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
- ""
- [(set_attr "type" "multi")
- (set_attr "unit" "i387")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*cmpu<mode>_i387"
- [(set (match_operand:HI 0 "register_operand" "=a")
- (unspec:HI
- [(unspec:CCFP
- [(compare:CCFP
- (match_operand:X87MODEF 1 "register_operand" "f")
- (match_operand:X87MODEF 2 "register_operand" "f"))]
- UNSPEC_NOTRAP)]
- UNSPEC_FNSTSW))]
- "TARGET_80387"
- "* return output_fp_compare (insn, operands, false, true);"
- [(set_attr "type" "multi")
- (set_attr "unit" "i387")
- (set_attr "mode" "<MODE>")])
-
-(define_insn_and_split "*cmpu<mode>_cc_i387"
- [(set (reg:CCFP FLAGS_REG)
- (unspec:CCFP
- [(compare:CCFP
- (match_operand:X87MODEF 1 "register_operand" "f")
- (match_operand:X87MODEF 2 "register_operand" "f"))]
- UNSPEC_NOTRAP))
- (clobber (match_operand:HI 0 "register_operand" "=a"))]
- "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (unspec:HI
- [(unspec:CCFP
- [(compare:CCFP (match_dup 1)(match_dup 2))]
- UNSPEC_NOTRAP)]
- UNSPEC_FNSTSW))
- (set (reg:CC FLAGS_REG)
- (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
- ""
- [(set_attr "type" "multi")
- (set_attr "unit" "i387")
- (set_attr "mode" "<MODE>")])
-
(define_insn "*cmp<X87MODEF:mode>_<SWI24:mode>_i387"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
(set_attr "fp_int_src" "true")
(set_attr "mode" "<SWI24:MODE>")])
-(define_insn_and_split "*cmp<X87MODEF:mode>_<SWI24:mode>_cc_i387"
- [(set (reg:CCFP FLAGS_REG)
- (compare:CCFP
- (match_operand:X87MODEF 1 "register_operand" "f")
- (float:X87MODEF
- (match_operand:SWI24 2 "nonimmediate_operand" "m"))))
- (clobber (match_operand:HI 0 "register_operand" "=a"))]
- "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE
- && (TARGET_USE_<SWI24:MODE>MODE_FIOP
- || optimize_function_for_size_p (cfun))"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
+(define_insn "*cmpu<mode>_i387"
+ [(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
- [(compare:CCFP
- (match_dup 1)
- (float:X87MODEF (match_dup 2)))]
- UNSPEC_FNSTSW))
- (set (reg:CC FLAGS_REG)
- (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
- ""
+ [(unspec:CCFP
+ [(compare:CCFP
+ (match_operand:X87MODEF 1 "register_operand" "f")
+ (match_operand:X87MODEF 2 "register_operand" "f"))]
+ UNSPEC_NOTRAP)]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387"
+ "* return output_fp_compare (insn, operands, false, true);"
[(set_attr "type" "multi")
(set_attr "unit" "i387")
- (set_attr "fp_int_src" "true")
- (set_attr "mode" "<SWI24:MODE>")])
+ (set_attr "mode" "<MODE>")])
;; FP compares, step 2:
;; Get ax into flags, general case.