This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[4.0 PATCH, i386]: Fix PR target/20421
- From: Uros Bizjak <uros at kss-loka dot si>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 16 Mar 2005 08:54:36 +0100
- Subject: [4.0 PATCH, i386]: Fix PR target/20421
Hello!
This is the same problem as in PR target/12308. When 387 rounding mode
control word calculation clobbers flags, patterns should be marked as
FLAGS_REG clobbering. fistp* patterns were fixed in target/12308, but
ceil/floor/... patterns should be fixed as well.
This is a 4.0 version of patch. Patch was bootstrapped on
i686-pc-linux-gnu, regtested for c,c++. OK to install on 4.0 branch?
(The mainline patch will be implemented usign mode_macro macros).
2005-03-16 Uros Bizjak <uros@kss-loka.si>
PR target/20421
PR target/12308
* config/i386/i386.md (frndintxf2_floor_1, frndintxf2_ceil_1,
frndintxf2_trunc_1, frndintxf2_mask_pm_1): New insn patterns.
(floorsf2, floordf2, floorxf2): Use frndintxf2_floor_1 when
387 rounding mode control word initialization clobbers flags.
(ceilsf2, ceildf2, ceilxf2): Use frndintxf2_ceil_1 when
387 rounding mode control word initialization clobbers flags.
(truncsf2, truncdf2, truncxf2): Use frndintxf2_trunc_1 when
387 rounding mode control word initialization clobbers flags.
(nearbyintsf2, nearbyintdf2, nearbyintxf2): Use frndintxf2_mask_pm_1.
Uros.
Index: i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.618
diff -u -p -r1.618 i386.md
--- i386.md 12 Feb 2005 11:34:22 -0000 1.618
+++ i386.md 16 Mar 2005 06:58:14 -0000
@@ -16297,6 +16297,34 @@
DONE;
})
+;; Following rounding expanders clobber FLAGS_REG, when logic instructions
+;; are emitted in emit_i387_cw_initialization () function. The "if"
+;; condition in this function and the "if" condition in the body of round
+;; expanders should be kept in sync to select correct FLAGS_REG clobbering
+;; pattern.
+
+(define_insn_and_split "frndintxf2_floor_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (unspec:XF [(match_dup 1)]
+ UNSPEC_FRNDINT_FLOOR))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ ""
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "XF")])
+
(define_insn "frndintxf2_floor"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
@@ -16325,7 +16353,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extenddfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_floor_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
@@ -16346,7 +16378,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extendsfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_floor_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
@@ -16363,10 +16399,36 @@
ix86_optimize_mode_switching = 1;
- emit_insn (gen_frndintxf2_floor (operands[0], operands[1], op2, op3));
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_floor (operands[0], operands[1], op2, op3));
+ else
+ emit_insn (gen_frndintxf2_floor_1 (operands[0], operands[1], op2, op3));
+
DONE;
})
+(define_insn_and_split "frndintxf2_ceil_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (unspec:XF [(match_dup 1)]
+ UNSPEC_FRNDINT_CEIL))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ ""
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "XF")])
+
(define_insn "frndintxf2_ceil"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
@@ -16395,7 +16457,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extenddfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_ceil_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
@@ -16416,7 +16482,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extendsfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_ceil_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
@@ -16433,10 +16503,36 @@
ix86_optimize_mode_switching = 1;
- emit_insn (gen_frndintxf2_ceil (operands[0], operands[1], op2, op3));
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_ceil (operands[0], operands[1], op2, op3));
+ else
+ emit_insn (gen_frndintxf2_ceil_1 (operands[0], operands[1], op2, op3));
+
DONE;
})
+(define_insn_and_split "frndintxf2_trunc_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_TRUNC))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (unspec:XF [(match_dup 1)]
+ UNSPEC_FRNDINT_TRUNC))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ ""
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "XF")])
+
(define_insn "frndintxf2_trunc"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
@@ -16465,7 +16561,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extenddfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_trunc_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
@@ -16486,7 +16586,11 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extendsfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+ else
+ emit_insn (gen_frndintxf2_trunc_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
@@ -16503,10 +16607,38 @@
ix86_optimize_mode_switching = 1;
- emit_insn (gen_frndintxf2_trunc (operands[0], operands[1], op2, op3));
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size && !TARGET_64BIT)
+ emit_insn (gen_frndintxf2_trunc (operands[0], operands[1], op2, op3));
+ else
+ emit_insn (gen_frndintxf2_trunc_1 (operands[0], operands[1], op2, op3));
+
DONE;
})
+;; PM bit setting is implemented using ior and always clobbers FP_REGS.
+
+(define_insn_and_split "frndintxf2_mask_pm_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_MASK_PM))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (unspec:XF [(match_dup 1)]
+ UNSPEC_FRNDINT_MASK_PM))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ ""
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "mask_pm")
+ (set_attr "mode" "XF")])
+
(define_insn "frndintxf2_mask_pm"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
@@ -16515,7 +16647,7 @@
(use (match_operand:HI 3 "memory_operand" "m"))]
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
- "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
[(set_attr "type" "frndint")
(set_attr "i387_cw" "mask_pm")
(set_attr "mode" "XF")])
@@ -16535,7 +16667,7 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extenddfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
+ emit_insn (gen_frndintxf2_mask_pm_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
@@ -16556,7 +16688,7 @@
ix86_optimize_mode_switching = 1;
emit_insn (gen_extendsfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
+ emit_insn (gen_frndintxf2_mask_pm_1 (op0, op1, op2, op3));
emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
@@ -16573,8 +16705,8 @@
ix86_optimize_mode_switching = 1;
- emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1],
- op2, op3));
+ emit_insn (gen_frndintxf2_mask_pm_1 (operands[0], operands[1], op2, op3));
+
DONE;
})