summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-23 14:23:40 +0000
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-23 14:23:40 +0000
commitab9ffc3b4c042a6a31f47b7a7ffa6f426f3dde68 (patch)
tree9f9f17da59f58dce8b45052dae9dfe07e200a1c8 /gcc/config/i386
parentb3208e64a3a662c82718965540839074554c1301 (diff)
downloadgcc-ab9ffc3b4c042a6a31f47b7a7ffa6f426f3dde68.tar.gz
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. testsuite/ChangeLog: PR target/17390 * gcc.target/i386/pr17390.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127742 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/i386.c27
-rw-r--r--gcc/config/i386/i386.md125
2 files changed, 137 insertions, 15 deletions
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.