i386.c (ix86_prepare_fp_compare_args): Do not force operand 0.0 into register in XFmode.

* config/i386/i386.c (ix86_prepare_fp_compare_args): Do not
        force operand 0.0 into register in XFmode. Also do not force
        operand 0.0 into register if !TARGET_CMOVE.

        * config/i386/i386.md (*cmpfp_0): Delete. Remove comment.
        (*cmpfp_0_sf, cmpfp_0_df, cmpfp_0_xf): New patterns to
        implement ftst x87 instruction.
        (*fp_jcc_7): New insn pattern. Change corresponding split
        pattern to handle "general_operand" instead of
        "nonimmediate_operand".

----------------------------------------------------------------------

From-SVN: r87173
This commit is contained in:
Uros Bizjak 2004-09-08 07:08:26 +02:00 committed by Uros Bizjak
parent 70d5fb1c36
commit 45c8c47fde
3 changed files with 99 additions and 38 deletions

View File

@ -1,3 +1,15 @@
2004-09-08 Uros Bizjak <uros@kss-loka.si>
* config/i386/i386.c (ix86_prepare_fp_compare_args): Do not
force operand 0.0 into register in XFmode. Also do not force
operand 0.0 into register if !TARGET_CMOVE.
* config/i386/i386.md (*cmpfp_0): Delete. Remove comment.
(*cmpfp_0_sf, cmpfp_0_df, cmpfp_0_xf): New patterns to
implement ftst x87 instruction.
(*fp_jcc_7): New insn pattern. Change corresponding split
pattern to handle "general_operand" instead of
"nonimmediate_operand".
2004-09-08 Ben Elliston <bje@au.ibm.com>
* doc/rtl.texi (Insns): Document NOTE_INSN_FUNCTION_BEG.

View File

@ -7941,12 +7941,15 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
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);
@ -7973,10 +7976,16 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
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);
}
}

View File

@ -797,41 +797,65 @@
;; 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"
(define_insn "*cmpfp_0_sf"
[(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: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])))
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" "SF")])
(define_insn "*cmpfp_0_df"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(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])))
{
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" "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.
@ -13322,6 +13346,25 @@
&& 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"
@ -13343,17 +13386,14 @@
[(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]);