===================================================================
@@ -233,6 +233,38 @@ (define_expand "neg<mode>2"
}
}")
+(define_expand "fma<mode>4"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fma:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")
+ (match_operand:VEC_F 3 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "fms<mode>4"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fma:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")
+ (neg:VEC_F (match_operand:VEC_F 3 "vfloat_operand" ""))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "fnma<mode>4"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fma:VEC_F (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" ""))
+ (match_operand:VEC_F 2 "vfloat_operand" "")
+ (match_operand:VEC_F 3 "vfloat_operand" "")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "")
+
+(define_expand "fnms<mode>4"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fma:VEC_F (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" ""))
+ (match_operand:VEC_F 2 "vfloat_operand" "")
+ (neg:VEC_F (match_operand:VEC_F 3 "vfloat_operand" ""))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "")
+
(define_expand "abs<mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
===================================================================
@@ -177,8 +177,8 @@ Target Report Var(TARGET_AVOID_XFORM) In
Avoid generation of indexed load/store instructions when possible
mfused-madd
-Target Report Var(TARGET_FUSED_MADD) Init(1)
-Generate fused multiply/add instructions
+Target Alias(ffp-contract=, fast, off)
+Generate fused multiply/add instructions. Same as -ffp-contract=fast
mtls-markers
Target Report Var(tls_markers) Init(1)
===================================================================
@@ -666,6 +666,23 @@ (define_insn "vsx_fnmadd<mode>4_2"
[(set_attr "type" "<VStype_mul>")
(set_attr "fp_type" "<VSfptype_mul>")])
+(define_insn "*vsx_fnmadd<mode>4_3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (fma:VSX_B
+ (neg:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa"))
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (neg:VSX_B
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "@
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
(define_insn "vsx_fnmsub<mode>4"
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(neg:VSX_B
@@ -717,6 +734,22 @@ (define_insn "vsx_fnmsub<mode>4_2"
[(set_attr "type" "<VStype_mul>")
(set_attr "fp_type" "<VSfptype_mul>")])
+(define_insn "*vsx_fnmsub<mode>4_3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (fma:VSX_B
+ (neg:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa"))
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "@
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
;; Vector conditional expressions (no scalar version for these instructions)
(define_insn "vsx_eq<mode>"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
===================================================================
@@ -597,6 +597,9 @@ extern int rs6000_vector_align[];
&& TARGET_DOUBLE_FLOAT \
&& (TARGET_PPC_GFXOPT || VECTOR_UNIT_VSX_P (DFmode)))
+/* Old -mno-fused-add is now -ffp-contract=off. */
+#define TARGET_FUSED_MADD (flag_fp_contract_mode != FP_CONTRACT_OFF)
+
/* Whether the various reciprocal divide/square root estimate instructions
exist, and whether we should automatically generate code for the instruction
by default. */
===================================================================
@@ -5870,7 +5870,7 @@ (define_insn "fmasf4_fpr"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn "*fmssf4_fpr"
+(define_insn "fmssf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")
@@ -5885,7 +5885,28 @@ (define_insn "*fmssf4_fpr"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn "*fnmasf4_fpr"
+;; Note, FNMA is defined to be (-a * b) + c, and FNMS is defined to be
+;; (-a * b) - c. The PowerPC defines its FNMADD operation as -((a*b)+c)
+;; and FNMSUB as -((a*b)-c), so for FNMA we need to emit a FNMSUB and for
+;; FNMS we need to emit a FNMADD. And signed zeros are also a possiblity
+;; so make this fast-math only
+(define_insn "fnmasf4"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (fma:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f")
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && !HONOR_SIGNED_ZEROS (SFmode)"
+ "*
+{
+ return ((TARGET_POWERPC)
+ ? \"fnmsubs %0,%1,%2,%3\"
+ : \"{fnms|fnmsub} %0,%1,%2,%3\");
+}"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+(define_insn "*fnmasf4_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")
@@ -5900,7 +5921,23 @@ (define_insn "*fnmasf4_fpr"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn "*fnmssf4_fpr"
+(define_insn "fnmssf4"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (fma:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f")
+ (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && !HONOR_SIGNED_ZEROS (SFmode)"
+ "*
+{
+ return ((TARGET_POWERPC)
+ ? \"fnmadds %0,%1,%2,%3\"
+ : \"{fnma|fnmadd} %0,%1,%2,%3\");
+}"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+(define_insn "*fnmssf4_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")
@@ -6396,43 +6433,96 @@ (define_expand "fmadf4"
"")
(define_insn "fmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (fma:DF (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (match_operand:DF 3 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& VECTOR_UNIT_NONE_P (DFmode)"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
+(define_expand "fmsdf4"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (fma:DF (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")
+ (neg:DF (match_operand:DF 3 "gpc_reg_operand" ""))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
(define_insn "*fmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (fma:DF (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (neg:DF (match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& VECTOR_UNIT_NONE_P (DFmode)"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn "*fnmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+;; Note, FNMA is defined to be (-a * b) + c, and FNMS is defined to be
+;; (-a * b) - c. The PowerPC defines its FNMADD operation as -((a*b)+c)
+;; and FNMSUB as -((a*b)-c), so for FNMA we need to emit a FNMSUB and for
+;; FNMS we need to emit a FNMADD. And signed zeros are also a possiblity
+;; so make this fast-math only
+(define_expand "fnmadf4"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (fma:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" ""))
+ (match_operand:DF 2 "gpc_reg_operand" "")
+ (match_operand:DF 3 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !HONOR_SIGNED_ZEROS (DFmode)"
+ "")
+
+(define_insn "*fnmadf4_fpr_1"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (fma:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d"))
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnms|fnmsub} %0,%1,%2,%3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+(define_insn "*fnmadf4_fpr_2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& VECTOR_UNIT_NONE_P (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn "*fnmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f")))))]
+(define_expand "fnmsdf4"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (fma:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" ""))
+ (match_operand:DF 2 "gpc_reg_operand" "")
+ (neg:DF (match_operand:DF 3 "gpc_reg_operand" ""))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !HONOR_SIGNED_ZEROS (DFmode)"
+ "")
+
+(define_insn "*fnmsdf4_fpr_1"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (fma:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d"))
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (neg:DF (match_operand:DF 3 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+(define_insn "*fnmsdf4_fpr_2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 2 "gpc_reg_operand" "d")
+ (neg:DF (match_operand:DF 3 "gpc_reg_operand" "d")))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& VECTOR_UNIT_NONE_P (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"