From 45c8c47fdeac150e070dad6dae959544bc81a64a Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 8 Sep 2004 07:08:26 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 +++++ gcc/config/i386/i386.c | 21 +++++--- gcc/config/i386/i386.md | 104 +++++++++++++++++++++++++++------------- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17cdf17e52b..a6f00a14c57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-09-08 Uros Bizjak + + * 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 * doc/rtl.texi (Insns): Document NOTE_INSN_FUNCTION_BEG. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4a869527505..3199b575691 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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); } } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 3104e0aec2d..f08c85a4d44 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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]);