Add FMA patterns for ia64.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Oct 2010 17:40:58 +0000 (17:40 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Oct 2010 17:40:58 +0000 (17:40 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165702 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/ia64/ia64.md
gcc/testsuite/gcc.target/ia64/builtin-fma-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/ia64/builtin-fma-2.c [new file with mode: 0644]

index 3b58b5c..fdd86ca 100644 (file)
@@ -1,3 +1,9 @@
+2010-10-19  Richard Henderson  <rth@redhat.com>
+
+       * config/ia64/ia64.md (fmasf4, *fmssf4, *nfmasf4): New.
+       (fmadf4, *fmsdf4, *nfmadf4): New.
+       (fmaxf4, *fmsxf4, *nfmaxf4): New.
+
 2010-10-19  Michael Eager  <eager@eagercon.com>
 
        * config/microblaze/microblaze.c (TARGET_EXCEPT_UNWIND_INFO): 
index db1d2d2..73e57b6 100644 (file)
   "TARGET_FUSED_MADD"
   "fnma.s %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
+
+;; Official C99 versions of the fmaf family of operations.
+(define_insn "fmasf4"
+  [(set (match_operand:SF 0 "fr_register_operand" "=f")
+       (fma: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_signed_fp01_operand" "fZ")))]
+  ""
+  "fma.s %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmssf4"
+  [(set (match_operand:SF 0 "fr_register_operand" "=f")
+       (fma:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")
+               (neg:SF
+                 (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+  ""
+  "fms.s %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+;; This insn is officially "-(a * b) + c" which is "(-a * b) + c".
+(define_insn "*nfmasf4"
+  [(set (match_operand:SF 0 "fr_register_operand" "=f")
+       (fma:SF (neg: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_signed_fp01_operand" "fZ")))]
+  ""
+  "fnma.s %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
 \f
 ;; ::::::::::::::::::::
 ;; ::
   "TARGET_FUSED_MADD"
   "fnma.s %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
+
+;; Official C99 versions of the fma family of operations.
+(define_insn "fmadf4"
+  [(set (match_operand:DF 0 "fr_register_operand" "=f")
+       (fma: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_signed_fp01_operand" "fZ")))]
+  ""
+  "fma.d %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmsdf4"
+  [(set (match_operand:DF 0 "fr_register_operand" "=f")
+       (fma:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+               (neg:DF
+                 (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+  ""
+  "fms.d %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+;; See comment for nfmasf4.
+(define_insn "*nfmadf4"
+  [(set (match_operand:DF 0 "fr_register_operand" "=f")
+       (fma:DF (neg: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_signed_fp01_operand" "fZ")))]
+  ""
+  "fnma.d %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
 \f
 ;; ::::::::::::::::::::
 ;; ::
   "TARGET_FUSED_MADD"
   "fnma.d %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
+
+;; Official C99 versions of the fmal family of operations.
+(define_insn "fmaxf4"
+  [(set (match_operand:XF 0 "fr_register_operand" "=f")
+       (fma:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+  ""
+  "fma %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmsxf4"
+  [(set (match_operand:XF 0 "fr_register_operand" "=f")
+       (fma:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+               (neg:XF
+                 (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+  ""
+  "fms %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
+
+;; See comment for nfmasf4.
+(define_insn "*nfmaxf4"
+  [(set (match_operand:XF 0 "fr_register_operand" "=f")
+       (fma:XF (neg:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG"))
+               (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+               (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+  ""
+  "fnma %0 = %F1, %F2, %F3"
+  [(set_attr "itanium_class" "fmac")])
 \f
 ;; ::::::::::::::::::::
 ;; ::
diff --git a/gcc/testsuite/gcc.target/ia64/builtin-fma-1.c b/gcc/testsuite/gcc.target/ia64/builtin-fma-1.c
new file mode 100644 (file)
index 0000000..a4b2e06
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* Don't confuse the fma insn with the fma in the filename.  */
+/* { dg-final { scan-assembler-times "fma\\." 4 } } */
+/* { dg-final { scan-assembler-times "fms" 2 } } */
+/* { dg-final { scan-assembler-times "fnma" 4 } } */
+
+#ifndef __FP_FAST_FMAF
+# error "__FP_FAST_FMAF should be defined"
+#endif
+#ifndef __FP_FAST_FMA
+# error "__FP_FAST_FMA should be defined"
+#endif
+
+float f0(float x, float y, float z) { return __builtin_fmaf(x,y,z); }
+float f1(float x, float y, float z) { return __builtin_fmaf(x,y,-z); }
+float f2(float x, float y, float z) { return __builtin_fmaf(-x,y,z); }
+float f3(float x, float y, float z) { return __builtin_fmaf(x,-y,z); }
+float f4(float x, float y, float z) { return __builtin_fmaf(-x,-y,z); }
+
+double d0(double x, double y, double z) { return __builtin_fma(x,y,z); }
+double d1(double x, double y, double z) { return __builtin_fma(x,y,-z); }
+double d2(double x, double y, double z) { return __builtin_fma(-x,y,z); }
+double d3(double x, double y, double z) { return __builtin_fma(x,-y,z); }
+double d4(double x, double y, double z) { return __builtin_fma(-x,-y,z); }
diff --git a/gcc/testsuite/gcc.target/ia64/builtin-fma-2.c b/gcc/testsuite/gcc.target/ia64/builtin-fma-2.c
new file mode 100644 (file)
index 0000000..16d95b7
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "128-bit long double" { *-*-hpux* } { "*" } { "" } } */
+/* { dg-options "-O" } */
+/* Don't confuse the fma insn with the fma in the filename.  */
+/* { dg-final { scan-assembler-times "fma\[    \]" 2 } } */
+/* { dg-final { scan-assembler-times "fms" 1 } } */
+/* { dg-final { scan-assembler-times "fnma" 2 } } */
+
+#ifndef __FP_FAST_FMAL
+# error "__FP_FAST_FMAL should be defined"
+#endif
+
+typedef long double LD;
+
+LD L0(LD x, LD y, LD z) { return __builtin_fmal(x,y,z); }
+LD L1(LD x, LD y, LD z) { return __builtin_fmal(x,y,-z); }
+LD L2(LD x, LD y, LD z) { return __builtin_fmal(-x,y,z); }
+LD L3(LD x, LD y, LD z) { return __builtin_fmal(x,-y,z); }
+LD L4(LD x, LD y, LD z) { return __builtin_fmal(-x,-y,z); }