diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 27 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 125 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr17390.c | 10 |
5 files changed, 167 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19b4f02a128..1b881ffd5b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2007-08-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/17390 + * config/i386/i386.c (ix86_expand_fp_compare): Expand fp comparison to + fake fcomi i387 instruction for !TARGET_CMOVE. + (ix86_expand_branch): Expand natural sequence with one jump for + all targets, not only TARGET_CMOVE. + * config/i386/i386.md (*cmpfp_0_cc): New define_insn_and_split + pattern to implement fake fcomi sequence. Split instruction after + reload to correct compare sequences. + (*cmpfp_xf_cc): Ditto. + (*cmpfp_<mode>_cc): Ditto. + (*cmpfp_u_cc): Ditto. + (*cmpfp_<mode>_cc): Ditto. + 2007-08-23 Richard Guenther <rguenther@suse.de> * tree-pretty-print.c (dump_generic_node): Annotate diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 851d0a0032f..c474f017d97 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11471,26 +11471,24 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch, ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code); /* Do fcomi/sahf based test when profitable. */ - if ((TARGET_CMOVE || TARGET_SAHF) + if (ix86_fp_comparison_arithmetics_cost (code) > cost && (bypass_code == UNKNOWN || bypass_test) - && (second_code == UNKNOWN || second_test) - && ix86_fp_comparison_arithmetics_cost (code) > cost) + && (second_code == UNKNOWN || second_test)) { + tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); + tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), + tmp); if (TARGET_CMOVE) - { - tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); - tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), - tmp); - emit_insn (tmp); - } + emit_insn (tmp); else { - tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); - tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW); + gcc_assert (TARGET_SAHF); + if (!scratch) scratch = gen_reg_rtx (HImode); - emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2)); - emit_insn (gen_x86_sahf_1 (scratch)); + tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch); + + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, tmp2))); } /* The FP codes work out to act like unsigned. */ @@ -11717,8 +11715,7 @@ ix86_expand_branch (enum rtx_code code, rtx label) /* Check whether we will use the natural sequence with one jump. If so, we can expand jump early. Otherwise delay expansion by creating compound insn to not confuse optimizers. */ - if (bypass_code == UNKNOWN && second_code == UNKNOWN - && TARGET_CMOVE) + if (bypass_code == UNKNOWN && second_code == UNKNOWN) { ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1, gen_rtx_LABEL_REF (VOIDmode, label), diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 609e6d6dda7..a518aaeaca9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -925,6 +925,34 @@ ] (const_string "XF")))]) +(define_insn_and_split "*cmpfp_0_cc" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP + (match_operand 1 "register_operand" "f") + (match_operand 2 "const0_operand" "X"))) + (clobber (match_operand:HI 0 "register_operand" "=a"))] + "X87_FLOAT_MODE_P (GET_MODE (operands[1])) + && TARGET_SAHF && !TARGET_CMOVE + && GET_MODE (operands[1]) == GET_MODE (operands[2])" + "#" + "&& 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") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF")))]) + (define_insn "*cmpfp_xf" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI @@ -938,6 +966,27 @@ (set_attr "unit" "i387") (set_attr "mode" "XF")]) +(define_insn_and_split "*cmpfp_xf_cc" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP + (match_operand:XF 1 "register_operand" "f") + (match_operand:XF 2 "register_operand" "f"))) + (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 "*cmpfp_<mode>" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI @@ -951,6 +1000,27 @@ (set_attr "unit" "i387") (set_attr "mode" "<MODE>")]) +(define_insn_and_split "*cmpfp_<mode>_cc" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP + (match_operand:X87MODEF12 1 "register_operand" "f") + (match_operand:X87MODEF12 2 "nonimmediate_operand" "fm"))) + (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 "*cmpfp_u" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI @@ -971,6 +1041,34 @@ ] (const_string "XF")))]) +(define_insn_and_split "*cmpfp_u_cc" + [(set (reg:CCFPU FLAGS_REG) + (compare:CCFPU + (match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f"))) + (clobber (match_operand:HI 0 "register_operand" "=a"))] + "X87_FLOAT_MODE_P (GET_MODE (operands[1])) + && TARGET_SAHF && !TARGET_CMOVE + && GET_MODE (operands[1]) == GET_MODE (operands[2])" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:HI + [(compare:CCFPU (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") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF")))]) + (define_insn "*cmpfp_<mode>" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI @@ -988,6 +1086,33 @@ (set_attr "fp_int_src" "true") (set_attr "mode" "<MODE>")]) +(define_insn_and_split "*cmpfp_<mode>_cc" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP + (match_operand 1 "register_operand" "f") + (match_operator 3 "float_operator" + [(match_operand:X87MODEI12 2 "memory_operand" "m")]))) + (clobber (match_operand:HI 0 "register_operand" "=a"))] + "X87_FLOAT_MODE_P (GET_MODE (operands[1])) + && TARGET_SAHF && !TARGET_CMOVE + && TARGET_USE_<MODE>MODE_FIOP + && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:HI + [(compare:CCFP + (match_dup 1) + (match_op_dup 3 [(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 "fp_int_src" "true") + (set_attr "mode" "<MODE>")]) + ;; FP compares, step 2 ;; Move the fpsw to ax. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8e350b20aee..340c95e456c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-08-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/17390 + * gcc.target/i386/pr17390.c: New test. + 2007-08-23 Richard Guenther <rguenther@suse.de> * gcc.dg/tree-ssa/fprinf-1.c: Adjust patterns. diff --git a/gcc/testsuite/gcc.target/i386/pr17390.c b/gcc/testsuite/gcc.target/i386/pr17390.c new file mode 100644 index 00000000000..3cf22e6d0bd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr17390.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -ffast-math" } */ + +double sgn (double __x) +{ + return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0); +} + +/* { dg-final { scan-assembler-times "fnstsw" 1 } } */ |