int is_sse = SSE_REG_P (op0) | SSE_REG_P (op1);
/* All of the unordered compare instructions only work on registers.
- The same is true of the XFmode compare instructions. The same is
- true of the fcomi compare instructions. */
+ The same is true of the fcomi compare instructions. The same is
+ true of the XFmode compare instructions if not comparing with
+ zero (ftst insn is used in this case). */
if (!is_sse
&& (fpcmp_mode == CCFPUmode
- || op_mode == XFmode
+ || (op_mode == XFmode
+ && ! (standard_80387_constant_p (op0) == 1
+ || standard_80387_constant_p (op1) == 1))
|| ix86_use_fcomi_compare (code)))
{
op0 = force_reg (op_mode, op0);
if (CONSTANT_P (op1))
{
- if (standard_80387_constant_p (op1))
- op1 = force_reg (op_mode, op1);
- else
+ int tmp = standard_80387_constant_p (op1);
+ if (tmp == 0)
op1 = validize_mem (force_const_mem (op_mode, op1));
+ else if (tmp == 1)
+ {
+ if (TARGET_CMOVE)
+ op1 = force_reg (op_mode, op1);
+ }
+ else
+ op1 = force_reg (op_mode, op1);
}
}
;; CCFPmode compare with exceptions
;; CCFPUmode compare with no exceptions
-;; %%% It is an unfortunate fact that ftst has no non-popping variant,
-;; and that fp moves clobber the condition codes, and that there is
-;; currently no way to describe this fact to reg-stack. So there are
-;; no splitters yet for this.
-
-;; %%% YIKES! This scheme does not retain a strong connection between
-;; the real compare and the ultimate cc0 user, so CC_REVERSE does not
-;; work! Only allow tos/mem with tos in op 0.
-;;
-;; Hmm, of course, this is what the actual _hardware_ does. Perhaps
-;; things aren't as bad as they sound...
+(define_insn "*cmpfp_0_sf"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (unspec:HI
+ [(compare:CCFP
+ (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "const0_operand" "X"))]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387"
+{
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ {
+ output_asm_insn ("ftst\;fnstsw\t%0", operands);
+ return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+ }
+ else
+ return "ftst\;fnstsw\t%0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SF")])
-(define_insn "*cmpfp_0"
+(define_insn "*cmpfp_0_df"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
- [(compare:CCFP (match_operand 1 "register_operand" "f")
- (match_operand 2 "const0_operand" "X"))]
- UNSPEC_FNSTSW))]
- "TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[1]))
- && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+ [(compare:CCFP
+ (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "const0_operand" "X"))]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387"
{
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "ftst\;fnstsw\t%0\;fstp\t%y0";
+ {
+ output_asm_insn ("ftst\;fnstsw\t%0", operands);
+ return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+ }
else
return "ftst\;fnstsw\t%0";
}
[(set_attr "type" "multi")
- (set (attr "mode")
- (cond [(match_operand:SF 1 "" "")
- (const_string "SF")
- (match_operand:DF 1 "" "")
- (const_string "DF")
- ]
- (const_string "XF")))])
+ (set_attr "mode" "DF")])
+
+(define_insn "*cmpfp_0_xf"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (unspec:HI
+ [(compare:CCFP
+ (match_operand:XF 1 "register_operand" "f")
+ (match_operand:XF 2 "const0_operand" "X"))]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387"
+{
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ {
+ output_asm_insn ("ftst\;fnstsw\t%0", operands);
+ return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+ }
+ else
+ return "ftst\;fnstsw\t%0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "XF")])
;; We may not use "#" to split and emit these, since the REG_DEAD notes
;; used to manage the reg stack popping would not be preserved.
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
+(define_insn "*fp_jcc_7"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "const_double_operand" "C")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 4 "=a"))]
+ "TARGET_80387
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && operands[2] == CONST0_RTX (GET_MODE (operands[1]))
+ && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+ && SELECT_CC_MODE (GET_CODE (operands[0]),
+ operands[1], operands[2]) == CCFPmode
+ && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
+ "#")
+
(define_split
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "")
- (match_operand 2 "nonimmediate_operand" "")])
+ (match_operand 2 "general_operand" "")])
(match_operand 3 "" "")
(match_operand 4 "" "")))
(clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 5 "=a"))]
"reload_completed"
- [(set (pc)
- (if_then_else (match_dup 6)
- (match_dup 3)
- (match_dup 4)))]
+ [(const_int 0)]
{
ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
operands[3], operands[4], operands[5]);