]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Use RTL builtins for FP ml[as] intrinsics
authorJonathan Wright <jonathan.wright@arm.com>
Tue, 16 Feb 2021 15:42:36 +0000 (15:42 +0000)
committerJonathan Wright <jonathan.wright@arm.com>
Fri, 30 Apr 2021 17:40:54 +0000 (18:40 +0100)
Rewrite floating-point vml[as][q] Neon intrinsics to use RTL builtins
rather than relying on the GCC vector extensions. Using RTL builtins
allows control over the emission of fmla/fmls instructions (which we
don't want here.)

With this commit, the code generated by these intrinsics changes from
a fused multiply-add/subtract instruction to an fmul followed by an
fadd/fsub instruction. If the programmer really wants fmla/fmls
instructions, they can use the vfm[as] intrinsics.

gcc/ChangeLog:

2021-02-16  Jonathan Wright  <jonathan.wright@arm.com>

* config/aarch64/aarch64-simd-builtins.def: Add float_ml[as]
builtin generator macros.
* config/aarch64/aarch64-simd.md (aarch64_float_mla<mode>):
Define.
(aarch64_float_mls<mode>): Define.
* config/aarch64/arm_neon.h (vmla_f32): Use RTL builtin
instead of relying on GCC vector extensions.
(vmla_f64): Likewise.
(vmlaq_f32): Likewise.
(vmlaq_f64): Likewise.
(vmls_f32): Likewise.
(vmls_f64): Likewise.
(vmlsq_f32): Likewise.
(vmlsq_f64): Likewise.
* config/aarch64/iterators.md: Define VDQF_DF mode iterator.

gcc/config/aarch64/aarch64-simd-builtins.def
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/arm_neon.h
gcc/config/aarch64/iterators.md

index 3b5e88443a8fbb0705956de55fab866534232f0c..2a2fc2076b11a83c1de0b9a7847488df73d312be 100644 (file)
   BUILTIN_VHSDF (TERNOP, fnma, 4, FP)
   VAR1 (TERNOP, fnma, 4, FP, hf)
 
+  BUILTIN_VDQF_DF (TERNOP, float_mla, 0, FP)
+  BUILTIN_VDQF_DF (TERNOP, float_mls, 0, FP)
   BUILTIN_VDQSF (TERNOP, float_mla_n, 0, FP)
   BUILTIN_VDQSF (TERNOP, float_mls_n, 0, FP)
 
index 6edfd2d637ef5a76d027e90053359e6da607ab84..0f96cd0bd512eb8437b6f16f45618f29e1d1526c 100644 (file)
   [(set_attr "type" "neon_fp_abs_<stype><q>")]
 )
 
+(define_expand "aarch64_float_mla<mode>"
+  [(set (match_operand:VDQF_DF 0 "register_operand")
+       (plus:VDQF_DF
+         (mult:VDQF_DF
+           (match_operand:VDQF_DF 2 "register_operand")
+           (match_operand:VDQF_DF 3 "register_operand"))
+         (match_operand:VDQF_DF 1 "register_operand")))]
+  "TARGET_SIMD"
+  {
+    rtx scratch = gen_reg_rtx (<MODE>mode);
+    emit_insn (gen_mul<mode>3 (scratch, operands[2], operands[3]));
+    emit_insn (gen_add<mode>3 (operands[0], operands[1], scratch));
+    DONE;
+  }
+)
+
+(define_expand "aarch64_float_mls<mode>"
+  [(set (match_operand:VDQF_DF 0 "register_operand")
+       (minus:VDQF_DF
+         (match_operand:VDQF_DF 1 "register_operand")
+         (mult:VDQF_DF
+           (match_operand:VDQF_DF 2 "register_operand")
+           (match_operand:VDQF_DF 3 "register_operand"))))]
+  "TARGET_SIMD"
+  {
+    rtx scratch = gen_reg_rtx (<MODE>mode);
+    emit_insn (gen_mul<mode>3 (scratch, operands[2], operands[3]));
+    emit_insn (gen_sub<mode>3 (operands[0], operands[1], scratch));
+    DONE;
+  }
+)
+
 (define_expand "aarch64_float_mla_n<mode>"
   [(set (match_operand:VDQSF 0 "register_operand")
        (plus:VDQSF
index f1e1e0ee79144c553fe207a51ba211c6dfc522ac..0227cadb7e869ee23dddd7abb71f169093f3cd05 100644 (file)
@@ -20347,28 +20347,28 @@ __extension__ extern __inline float32x2_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmla_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c)
 {
-  return __a + __b * __c;
+  return __builtin_aarch64_float_mlav2sf (__a, __b, __c);
 }
 
 __extension__ extern __inline float64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmla_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c)
 {
-  return __a + __b * __c;
+  return (float64x1_t) {__builtin_aarch64_float_mladf (__a[0], __b[0], __c[0])};
 }
 
 __extension__ extern __inline float32x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmlaq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
 {
-  return __a + __b * __c;
+  return __builtin_aarch64_float_mlav4sf (__a, __b, __c);
 }
 
 __extension__ extern __inline float64x2_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmlaq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c)
 {
-  return __a + __b * __c;
+  return __builtin_aarch64_float_mlav2df (__a, __b, __c);
 }
 
 /* vmla_lane  */
@@ -20545,28 +20545,28 @@ __extension__ extern __inline float32x2_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmls_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c)
 {
-  return __a - __b * __c;
+  return __builtin_aarch64_float_mlsv2sf (__a, __b, __c);
 }
 
 __extension__ extern __inline float64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmls_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c)
 {
-  return __a - __b * __c;
+  return (float64x1_t) {__builtin_aarch64_float_mlsdf (__a[0], __b[0], __c[0])};
 }
 
 __extension__ extern __inline float32x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmlsq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
 {
-  return __a - __b * __c;
+  return __builtin_aarch64_float_mlsv4sf (__a, __b, __c);
 }
 
 __extension__ extern __inline float64x2_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmlsq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c)
 {
-  return __a - __b * __c;
+  return __builtin_aarch64_float_mlsv2df (__a, __b, __c);
 }
 
 /* vmls_lane  */
index 634c44e225c2f1925ac5c12e9399ec535726bf0c..c57aa6bf2f44c910f410d843204ee5601216530f 100644 (file)
                             V2SF V4SF V2DF])
 
 ;; Advanced SIMD Float modes, and DF.
+(define_mode_iterator VDQF_DF [V2SF V4SF V2DF DF])
 (define_mode_iterator VHSDF_DF [(V4HF "TARGET_SIMD_F16INST")
                                (V8HF "TARGET_SIMD_F16INST")
                                V2SF V4SF V2DF DF])