===================================================================
@@ -95,6 +95,13 @@ (define_constraint "G"
(and (match_code "const_double")
(match_test "op == CONST0_RTX (mode) || op == CONST1_RTX (mode)")))
+(define_constraint "Z"
+ "1.0 or (0.0 and !flag_signed_zeros)"
+ (and (match_code "const_double")
+ (ior (match_test "op == CONST1_RTX (mode)")
+ (and (match_test "op == CONST0_RTX (mode)")
+ (match_test "!flag_signed_zeros")))))
+
(define_constraint "H"
"0.0"
(and (match_code "const_double")
===================================================================
@@ -542,6 +542,19 @@ (define_predicate "xfreg_or_fp01_operand
(and (match_operand 0 "fr_reg_or_fp01_operand")
(not (match_code "subreg"))))
+;; Like fr_reg_or_fp01_operand, but don't allow 0 if flag_signed_zero is set.
+;; Using f0 as the second arg to fadd or fsub, or as the third arg to fma or
+;; fms can cause a zero result to have the wrong sign.
+(define_predicate "fr_reg_or_signed_fp01_operand"
+ (ior (match_operand 0 "fr_register_operand")
+ (and (match_code "const_double")
+ (match_test "satisfies_constraint_Z (op)"))))
+
+;; Like fr_reg_or_signed_fp01_operand, but don't allow any SUBREGs.
+(define_predicate "xfreg_or_signed_fp01_operand"
+ (and (match_operand 0 "fr_reg_or_signed_fp01_operand")
+ (not (match_code "subreg"))))
+
;; True if OP is a constant zero, or a register.
(define_predicate "fr_reg_or_0_operand"
(ior (match_operand 0 "fr_register_operand")
===================================================================
@@ -2664,7 +2664,7 @@ (define_insn_and_split "negti2"
(define_insn "addsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:SF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
""
"fadd.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2672,7 +2672,7 @@ (define_insn "addsf3"
(define_insn "subsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(minus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:SF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
""
"fsub.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2744,7 +2744,7 @@ (define_insn "*maddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2753,7 +2753,7 @@ (define_insn "*msubsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2784,7 +2784,7 @@ (define_insn "*nmaddsf4"
(define_insn "adddf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
""
"fadd.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2793,7 +2793,7 @@ (define_insn "*adddf3_trunc"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(plus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ"))))]
""
"fadd.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2801,7 +2801,7 @@ (define_insn "*adddf3_trunc"
(define_insn "subdf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
""
"fsub.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2810,7 +2810,7 @@ (define_insn "*subdf3_trunc"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ"))))]
""
"fsub.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2891,7 +2891,7 @@ (define_insn "*madddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2901,7 +2901,7 @@ (define_insn "*madddf4_trunc"
(float_truncate:SF
(plus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2910,7 +2910,7 @@ (define_insn "*msubdf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(minus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fms.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2920,7 +2920,7 @@ (define_insn "*msubdf4_trunc"
(float_truncate:SF
(minus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -2970,7 +2970,7 @@ (define_insn "*nmadddf4_truncsf"
(define_insn "addxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ")))]
""
"fadd %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2979,7 +2979,7 @@ (define_insn "*addxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
""
"fadd.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2988,7 +2988,7 @@ (define_insn "*addxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
(plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
""
"fadd.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -2996,7 +2996,7 @@ (define_insn "*addxf3_truncdf"
(define_insn "subxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ")))]
""
"fsub %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -3005,7 +3005,7 @@ (define_insn "*subxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
""
"fsub.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -3014,7 +3014,7 @@ (define_insn "*subxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
(minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
""
"fsub.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
@@ -3104,7 +3104,7 @@ (define_insn "*maddxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3114,7 +3114,7 @@ (define_insn "*maddxf4_truncsf"
(float_truncate:SF
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3124,7 +3124,7 @@ (define_insn "*maddxf4_truncdf"
(float_truncate:DF
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3133,7 +3133,7 @@ (define_insn "*msubxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ")))]
"TARGET_FUSED_MADD"
"fms %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3143,7 +3143,7 @@ (define_insn "*msubxf4_truncsf"
(float_truncate:SF
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3153,7 +3153,7 @@ (define_insn "*msubxf4_truncdf"
(float_truncate:DF
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (match_operand:XF 3 "xfreg_or_signed_fp01_operand" "fZ"))))]
"TARGET_FUSED_MADD"
"fms.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])