On 28/01/2026 09:13, Kyrylo Tkachov wrote:
Hi Karl,

On 27 Jan 2026, at 18:09, Karl Meakin <[email protected]> wrote:

Add support for the `SVE_BFSCALE` architecture extension.

gcc/ChangeLog:

* doc/invoke.texi: Document `+sve-bfscale` flag.
* config/aarch64/aarch64.h (TARGET_SVE_BFSCALE): New macro.
* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins):
Define `__AARCH64_FEATURE_SVE_BFSCALE`.
* config/aarch64/aarch64-sve-builtins-base.cc: Skip constant
folding for floating-point or unpredicated multiplications.
* config/aarch64/aarch64-sve-builtins-sve2.def: New `SVE_FUNCTION`s.
* config/aarch64/aarch64-sve.md: Modify insns for
`SVE_COND_FP_BINARY_INT` to handle BF16 modes.
* config/aarch64/aarch64-sve2.md
(@aarch64_sve_<optab><mode>, @aarch64_sve_<optab><mode>_single): New insn for 
`BFSCALE`.
Modify insns for `UNSPEC_FSCALE` to handle BF16 modes.
* config/aarch64/iterators.md (SVE_FULL_F_SCALAR): Add `VNx8BF` to iterator.
(SVE_FULL_F_BFSCALE): New iterator.
(SVE_Fx24_BFSCALE): New iterator.
(SVE_BFx24): New iterator.
(UNSPEC_FMUL): New unspec.
(V_INT_EQUIV): Add entries for BF16 modes.
(b): Add entries for scalar float modes.
(is_bf16): Add entries for BF16 modes and reformat.
(SVSCALE_SINGLE_INTARG): Likewise.
(SVSCALE_INTARG): Likewise.
(SVE_FP_MULL): New iterator.

gcc/testsuite/ChangeLog:

* lib/target-supports.exp: Add `sve-bfscale` to `sve_exts`.
* gcc.target/aarch64/pragma_cpp_predefs_4.c: Add test for 
`__ARM_SVE_FEATURE_BFSCALE`.
* gcc.target/aarch64/sme2/acle-asm/mul_bf16_x2.c: New test.
* gcc.target/aarch64/sme2/acle-asm/mul_bf16_x4.c: New test.
* gcc.target/aarch64/sme2/acle-asm/scale_bf16_x2.c: New test.
* gcc.target/aarch64/sme2/acle-asm/scale_bf16_x4.c: New test.
* gcc.target/aarch64/sve/acle/asm/scale_bf16.c: New test.
* gcc.target/aarch64/sve/acle/general-c/bfscale.c: New test.
---
gcc/config/aarch64/aarch64-c.cc               |   2 +
.../aarch64/aarch64-sve-builtins-base.cc      |   9 +-
.../aarch64/aarch64-sve-builtins-sve2.def     |  43 +++
gcc/config/aarch64/aarch64-sve.md             |  87 ++---
gcc/config/aarch64/aarch64-sve2.md            |  70 +++-
gcc/config/aarch64/aarch64.h                  |   1 +
gcc/config/aarch64/iterators.md               |  63 +++-
gcc/doc/invoke.texi                           |   3 +-
.../gcc.target/aarch64/pragma_cpp_predefs_4.c |   5 +
.../aarch64/sme2/acle-asm/mul_bf16_x2.c       | 193 ++++++++++
.../aarch64/sme2/acle-asm/mul_bf16_x4.c       | 227 ++++++++++++
.../aarch64/sme2/acle-asm/scale_bf16_x2.c     | 194 ++++++++++
.../aarch64/sme2/acle-asm/scale_bf16_x4.c     | 231 ++++++++++++
.../aarch64/sve/acle/asm/scale_bf16.c         | 337 ++++++++++++++++++
.../aarch64/sve/acle/general-c/bfscale.c      | 114 ++++++
gcc/testsuite/lib/target-supports.exp         |   2 +-
16 files changed, 1506 insertions(+), 75 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x4.c
create mode 100644 
gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x2.c
create mode 100644 
gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x4.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/asm/scale_bf16.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/bfscale.c

diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index b52ea7649f9..f8be998da16 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -275,6 +275,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
"__ARM_FEATURE_BF16", pfile);
   aarch64_def_or_undef (TARGET_SVE_BF16,
"__ARM_FEATURE_SVE_BF16", pfile);
+  aarch64_def_or_undef (TARGET_SVE_BFSCALE,
+ "__ARM_FEATURE_SVE_BFSCALE", pfile);

   aarch64_def_or_undef (TARGET_LUT, "__ARM_FEATURE_LUT", pfile);
   aarch64_def_or_undef (TARGET_SME_LUTv2, "__ARM_FEATURE_SME_LUTv2", pfile);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc 
b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index e3d0f9b909a..b296f5c259f 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -2315,11 +2315,18 @@ class svmul_impl : public rtx_code_function
{
public:
   CONSTEXPR svmul_impl ()
-    : rtx_code_function (MULT, MULT, UNSPEC_COND_FMUL) {}
+    : rtx_code_function (MULT, MULT, UNSPEC_COND_FMUL, UNSPEC_FMUL) {}

   gimple *
   fold (gimple_folder &f) const override
   {
+    /* The code below assumes that the function has 3 arguments (pg, rn, rm).
+     * Unpredicated functions have only 2 arguments (rn, rm) so will cause the
+     * code below to crash.  Also skip if it does not operatoe on integers,
Typo: “operate”. Also, the house style is to not have the asterisks at the 
beginning of comment lines.
Fixed, thanks.

+     * since all the optimizations below are for integer multiplication.  */
+    if (!f.type_suffix (0).integer_p || f.pred == aarch64_sve::PRED_none)
+      return nullptr;
+
     if (auto *res = f.fold_const_binary (MULT_EXPR))
       return res;

diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def 
b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
index 19249a58875..62a80a7b320 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
@@ -447,3 +447,46 @@ DEF_SVE_FUNCTION_GS_FPM (svmmla, mmla, s_float_mf8, none, 
none, set)
#define REQUIRED_EXTENSIONS nonstreaming_sve (AARCH64_FL_SVE_F16F32MM)
DEF_SVE_FUNCTION (svmmla, mmla, cvt_f32_f16, none)
#undef REQUIRED_EXTENSIONS
+
+/*
+- BFSCALE (predicated)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SVE2 != 0
+  svbfloat16_t svscale[_bf16]_m (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_bf16]_x (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_bf16]_z (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_n_bf16]_m (svbool_t pg, svbfloat16_t zdn, int16_t zm);
+  svbfloat16_t svscale[_n_bf16]_x (svbool_t pg, svbfloat16_t zdn, int16_t zm);
+  svbfloat16_t svscale[_n_bf16]_z (svbool_t pg, svbfloat16_t zdn, int16_t zm); 
 */
+#define REQUIRED_EXTENSIONS \
+  sve_and_sme (AARCH64_FL_SVE2 | AARCH64_FL_SVE_BFSCALE, \
+       AARCH64_FL_SME2 | AARCH64_FL_SVE_BFSCALE)
+DEF_SVE_FUNCTION (svscale, binary_int_opt_n, h_bfloat, mxz)
+#undef REQUIRED_EXTENSIONS
+
+/*
+- BFSCALE (multiple vectors)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svscale[_bf16_x2] (svbfloat16x2_t zdn, svint16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svscale[_bf16_x4] (svbfloat16x4_t zdn, svint16x4_t zm) 
__arm_streaming;
+
+- BFSCALE (multiple and single vector)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svscale[_single_bf16_x2] (svbfloat16x2_t zn, svint16_t zm) 
__arm_streaming;
+  svbfloat16x4_t svscale[_single_bf16_x4] (svbfloat16x4_t zn, svint16_t zm) 
__arm_streaming;  */
+#define REQUIRED_EXTENSIONS streaming_only (AARCH64_FL_SVE_BFSCALE | 
AARCH64_FL_SME2)
+DEF_SVE_FUNCTION_GS (svscale, binary_int_opt_single_n, h_bfloat, x24, none)
+#undef REQUIRED_EXTENSIONS
+
+/*
+- BFMUL (multiple vectors)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svmul[_bf16_x2] (svbfloat16x2_t zdn, svbfloat16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svmul[_bf16_x4] (svbfloat16x4_t zdn, svbfloat16x4_t zm) 
__arm_streaming;
+
+- BFMUL (multiple and single vector)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svmul[_single_bf16_x2] (svbfloat16x2_t zn, svbfloat16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svmul[_single_bf16_x4] (svbfloat16x4_t zn, svbfloat16x4_t zm) 
__arm_streaming;  */
+#define REQUIRED_EXTENSIONS streaming_only (AARCH64_FL_SVE_BFSCALE | 
AARCH64_FL_SME2)
+DEF_SVE_FUNCTION_GS (svmul, binary_opt_single_n, h_bfloat, x24, none)
+#undef REQUIRED_EXTENSIONS
diff --git a/gcc/config/aarch64/aarch64-sve.md 
b/gcc/config/aarch64/aarch64-sve.md
index 846ed5c65d2..97fd9516959 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -5529,6 +5529,7 @@ (define_insn_and_rewrite "*cond_<sve_int_op><mode>_any"
;; -------------------------------------------------------------------------
;; Includes:
;; - FSCALE
+;; - BFSCALE (SVE_BFSCALE)
;; - FTSMUL
;; - FTSSEL
;; -------------------------------------------------------------------------
@@ -5566,15 +5567,15 @@ (define_insn "@aarch64_sve_<optab><mode>"
(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_FULL_F_SCALAR 0 "register_operand")
(unspec:SVE_FULL_F_SCALAR
-  [(match_operand:<VPRED> 1 "register_operand")
-   (match_operand:SI 4 "aarch64_sve_gp_strictness")
+  [(match_operand:<VPRED>    1 "register_operand")
+   (match_operand:SI    4 "aarch64_sve_gp_strictness")
   (match_operand:SVE_FULL_F_SCALAR 2 "register_operand")
-   (match_operand:<V_INT_EQUIV> 3 "register_operand")]
+   (match_operand:<V_INT_EQUIV>     3 "register_operand")]
  SVE_COND_FP_BINARY_INT))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
-     [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%Z0.<Vetype>, %1/m, 
%Z0.<Vetype>, %Z3.<Vetype>
-     [ ?&w      , Upl , w , w ; yes            ] movprfx\t%Z0, 
%Z2\;<sve_fp_op>\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, %Z3.<Vetype>
+  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
+     [ w , Upl , 0 , w ; * ] <b><sve_fp_op>\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, 
%Z3.<Vetype>
+     [ ?&w , Upl , w , w ; yes ] movprfx\t%Z0, %Z2\;<b><sve_fp_op>\t%Z0.<Vetype>, %1/m, 
%Z0.<Vetype>, %Z3.<Vetype>
   }
   [(set_attr "sve_type" "sve_fp_mul")]
)
@@ -5582,16 +5583,16 @@ (define_insn "@aarch64_pred_<optab><mode>"
;; Predicated floating-point binary operations with merging, taking an
;; integer as their second operand.
(define_expand "@cond_<optab><mode>"
-  [(set (match_operand:SVE_FULL_F 0 "register_operand")
- (unspec:SVE_FULL_F
+  [(set (match_operand:SVE_FULL_F_BFSCALE 0 "register_operand")
+ (unspec:SVE_FULL_F_BFSCALE
  [(match_operand:<VPRED> 1 "register_operand")
-   (unspec:SVE_FULL_F
+   (unspec:SVE_FULL_F_BFSCALE
     [(match_dup 1)
      (const_int SVE_STRICT_GP)
-      (match_operand:SVE_FULL_F 2 "register_operand")
-      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
+      (match_operand:SVE_FULL_F_BFSCALE 2 "register_operand")
+      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
     SVE_COND_FP_BINARY_INT)
-   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
+   (match_operand:SVE_FULL_F_BFSCALE 4 "aarch64_simd_reg_or_zero")]
  UNSPEC_SEL))]
   "TARGET_SVE"
)
@@ -5599,21 +5600,21 @@ (define_expand "@cond_<optab><mode>"
;; Predicated floating-point binary operations that take an integer as their
;; second operand, with inactive lanes coming from the first operand.
(define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
-  [(set (match_operand:SVE_FULL_F 0 "register_operand")
- (unspec:SVE_FULL_F
+  [(set (match_operand:SVE_FULL_F_BFSCALE 0 "register_operand")
+ (unspec:SVE_FULL_F_BFSCALE
  [(match_operand:<VPRED> 1 "register_operand")
-   (unspec:SVE_FULL_F
+   (unspec:SVE_FULL_F_BFSCALE
     [(match_operand 4)
      (const_int SVE_RELAXED_GP)
-      (match_operand:SVE_FULL_F 2 "register_operand")
+      (match_operand:SVE_FULL_F_BFSCALE 2 "register_operand")
      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
     SVE_COND_FP_BINARY_INT)
   (match_dup 2)]
  UNSPEC_SEL))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
-     [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, 
%0.<Vetype>, %3.<Vetype>
-     [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, 
%2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
+     [ w , Upl , 0 , w ; * ] <b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, 
%3.<Vetype>
+     [ ?&w , Upl , w , w ; yes ] movprfx\t%0, %2\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, 
%0.<Vetype>, %3.<Vetype>
   }
   "&& !rtx_equal_p (operands[1], operands[4])"
   {
@@ -5623,21 +5624,21 @@ (define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
)

(define_insn "*cond_<optab><mode>_2_strict"
-  [(set (match_operand:SVE_FULL_F 0 "register_operand")
- (unspec:SVE_FULL_F
+  [(set (match_operand:SVE_FULL_F_BFSCALE 0 "register_operand")
+ (unspec:SVE_FULL_F_BFSCALE
  [(match_operand:<VPRED> 1 "register_operand")
-   (unspec:SVE_FULL_F
+   (unspec:SVE_FULL_F_BFSCALE
     [(match_dup 1)
      (const_int SVE_STRICT_GP)
-      (match_operand:SVE_FULL_F 2 "register_operand")
+      (match_operand:SVE_FULL_F_BFSCALE 2 "register_operand")
      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
     SVE_COND_FP_BINARY_INT)
   (match_dup 2)]
  UNSPEC_SEL))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
-     [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, 
%0.<Vetype>, %3.<Vetype>
-     [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, 
%2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+  {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
+     [ w , Upl , 0 , w ; * ] <b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, 
%3.<Vetype>
+     [ ?&w , Upl , w , w ; yes ] movprfx\t%0, %2\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, 
%0.<Vetype>, %3.<Vetype>
   }
   [(set_attr "sve_type" "sve_fp_mul")]
)
@@ -5646,22 +5647,22 @@ (define_insn "*cond_<optab><mode>_2_strict"
;; their second operand, with the values of inactive lanes being distinct
;; from the other inputs.
(define_insn_and_rewrite "*cond_<optab><mode>_any_relaxed"
-  [(set (match_operand:SVE_FULL_F 0 "register_operand")
- (unspec:SVE_FULL_F
+  [(set (match_operand:SVE_FULL_F_BFSCALE 0 "register_operand")
+ (unspec:SVE_FULL_F_BFSCALE
  [(match_operand:<VPRED> 1 "register_operand")
-   (unspec:SVE_FULL_F
+   (unspec:SVE_FULL_F_BFSCALE
     [(match_operand 5)
      (const_int SVE_RELAXED_GP)
-      (match_operand:SVE_FULL_F 2 "register_operand")
+      (match_operand:SVE_FULL_F_BFSCALE 2 "register_operand")
      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
     SVE_COND_FP_BINARY_INT)
-   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
+   (match_operand:SVE_FULL_F_BFSCALE 4 "aarch64_simd_reg_or_zero")]
  UNSPEC_SEL))]
   "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
   {@ [ cons: =0 , 1   , 2 , 3 , 4   ]
-     [ &w       , Upl , 0 , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
-     [ &w       , Upl , w , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
-     [ &w       , Upl , w , w , 0   ] movprfx\t%0.<Vetype>, %1/m, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , 0 , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , w , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , w , w , 0   ] movprfx\t%0.<Vetype>, %1/m, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w , w   ] #
   }
   "&& 1"
@@ -5684,22 +5685,22 @@ (define_insn_and_rewrite 
"*cond_<optab><mode>_any_relaxed"
)

(define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
-  [(set (match_operand:SVE_FULL_F 0 "register_operand")
- (unspec:SVE_FULL_F
+  [(set (match_operand:SVE_FULL_F_BFSCALE 0 "register_operand")
+ (unspec:SVE_FULL_F_BFSCALE
  [(match_operand:<VPRED> 1 "register_operand")
-   (unspec:SVE_FULL_F
+   (unspec:SVE_FULL_F_BFSCALE
     [(match_dup 1)
      (const_int SVE_STRICT_GP)
-      (match_operand:SVE_FULL_F 2 "register_operand")
-      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
+      (match_operand:SVE_FULL_F_BFSCALE 2 "register_operand")
+      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
     SVE_COND_FP_BINARY_INT)
-   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
+   (match_operand:SVE_FULL_F_BFSCALE    4 "aarch64_simd_reg_or_zero")]
  UNSPEC_SEL))]
   "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
   {@ [ cons: =0 , 1   , 2 , 3 , 4   ]
-     [ &w       , Upl , 0 , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
-     [ &w       , Upl , w , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
-     [ &w       , Upl , w , w , 0   ] movprfx\t%0.<Vetype>, %1/m, 
%2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , 0 , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , w , w , Dz  ] movprfx\t%0.<Vetype>, %1/z, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+     [ &w       , Upl , w , w , 0   ] movprfx\t%0.<Vetype>, %1/m, 
%2.<Vetype>\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w , w   ] #
   }
   "&& reload_completed
diff --git a/gcc/config/aarch64/aarch64-sve2.md 
b/gcc/config/aarch64/aarch64-sve2.md
index 1278b9081cd..89e9bf9690c 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -61,6 +61,7 @@
;; ---- [FP] Non-widening bfloat16 arithmetic
;; ---- [FP] Clamp to minimum/maximum
;; ---- [FP] Scaling by powers of two
+;; ---- [FP] Multiplication
;;
;; == Uniform ternary arithmnetic
;; ---- [INT] General ternary arithmetic that maps to unspecs
@@ -1492,26 +1493,74 @@ (define_insn "@aarch64_sve_fclamp_single<mode>"
;; -------------------------------------------------------------------------
;; Includes the multiple and single vector and multiple vectors forms of
;; - FSCALE
+;; - BFSCALE
It would be good to have the (SVE_BFSCALE) in the comment here to keep 
consistent with the practice of highlighting non-default ISA extensions needed 
for various instructions.
Fixed, thanks.

;; -------------------------------------------------------------------------

+;; FSCALE / BFSCALE (multiple vectors)
+;; sv{b}floatNx2_t svscale[_{b}fN_x2] (sv{b}floatNx2_t zdn, svintNx2_t zm) 
__arm_streaming;
+;; sv{b}floatNx4_t svscale[_{b}fN_x4] (sv{b}floatNx4_t zdn, svintNx4_t zm) 
__arm_streaming;
+;; {B}FSCALE { <Zdn1>.T-<Zdn2>.T }, { <Zdn1>.T-<Zdn2>.T }, { <Zm1>.H-<Zm2>.T }
+;; {B}FSCALE { <Zdn1>.T-<Zdn4>.T }, { <Zdn1>.T-<Zdn4>.T }, { <Zm1>.H-<Zm4>.T }
(define_insn "@aarch64_sve_fscale<mode>"
-  [(set (match_operand:SVE_Fx24_NOBF 0 "register_operand" "=Uw<vector_count>")
- (unspec:SVE_Fx24_NOBF
-  [(match_operand:SVE_Fx24_NOBF 1 "register_operand" "0")
+  [(set (match_operand:SVE_Fx24_BFSCALE 0 "register_operand" 
"=Uw<vector_count>")
+ (unspec:SVE_Fx24_BFSCALE
+  [(match_operand:SVE_Fx24_BFSCALE 1 "register_operand" "0")
   (match_operand:<SVSCALE_INTARG> 2 "register_operand" "Uw<vector_count>")]
  UNSPEC_FSCALE))]
-  "TARGET_STREAMING_SME2 && TARGET_FP8"
-  "fscale\t%0, %1, %2"
+  "TARGET_STREAMING_SME2 && (<is_bf16> ? TARGET_SVE_BFSCALE : TARGET_FP8)"
Is this instruction supposed to work outside of SME2/SSVE? I think this 
condition doesn’t allow the instruction for non-SME targets. Or am I 
misremembering the TARGET_* definitions here?
Otherwise looks ok to me.
Thanks,
Kyrill

The documentation for the instructions (https://armv8.arm.com/latest_builds/v9A/isa64/fscale_mz_zzv.xml) state they are only available when SME2 is enabled, and the documentation for the intrinsics (https://arm-software.github.io/acle/main/acle.html#fscale) says that streaming mode must be enabled.

+  "<b>fscale\t%0, %1, %2"
)

+;; FSCALE / BFSCALE (multiple and single vector)
+;; sv{b}floatNx2_t svscale[_single_{b}fN_x2] (sv{b}floatNx2_t zdn, svintN_t 
zm) __arm_streaming;
+;; sv{b}floatNx4_t svscale[_single_{b}fN_x4] (sv{b}floatNx4_t zdn, svintN_t 
zm) __arm_streaming;
+;; {B}FSCALE { <Zdn1>.T-<Zdn2>.T }, { <Zdn1>.T-<Zdn2>.T }, <Zm1>.T
+;; {B}FSCALE { <Zdn1>.T-<Zdn4>.T }, { <Zdn1>.T-<Zdn4>.T }, <Zm1>.T
(define_insn "@aarch64_sve_single_fscale<mode>"
-  [(set (match_operand:SVE_Fx24_NOBF 0 "register_operand" "=Uw<vector_count>")
- (unspec:SVE_Fx24_NOBF
-  [(match_operand:SVE_Fx24_NOBF 1 "register_operand" "0")
+  [(set (match_operand:SVE_Fx24_BFSCALE 0 "register_operand" 
"=Uw<vector_count>")
+ (unspec:SVE_Fx24_BFSCALE
+  [(match_operand:SVE_Fx24_BFSCALE  1 "register_operand" "0")
   (match_operand:<SVSCALE_SINGLE_INTARG> 2 "register_operand" "x")]
  UNSPEC_FSCALE))]
-  "TARGET_STREAMING_SME2 && TARGET_FP8"
-  "fscale\t%0, %1, %2.<Vetype>"
+  "TARGET_STREAMING_SME2 && (<is_bf16> ? TARGET_SVE_BFSCALE : TARGET_FP8)"
+  "<b>fscale\t%0, %1, %2.<Vetype>"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Multiplication
+;; -------------------------------------------------------------------------
+;; Includes the multiple and single vector and multiple vectors forms of
+;; - BFMUL
+;; -------------------------------------------------------------------------
+
+;; BFMUL (multiple vectors)
+;; svbfloat16x2_t svmul[_bf16_x2](svbfloat16x2_t zd, svbfloat16x2_t zm) 
__arm_streaming;
+;; svbfloat16x4_t svmul[_bf16_x4](svbfloat16x4_t zd, svbfloat16x4_t zm) 
__arm_streaming;
+;; BFMUL { <Zd1>.H-<Zd2>.H }, { <Zn1>.H-<Zn2>.H }, { <Zm1>.H-<Zm2>.H }
+;; BFMUL { <Zd1>.H-<Zd4>.H }, { <Zn1>.H-<Zn4>.H }, { <Zm1>.H-<Zm4>.H }
+(define_insn "@aarch64_sve_<optab><mode>"
+  [(set (match_operand:SVE_BFx24 0 "register_operand" "=Uw<vector_count>")
+ (unspec:SVE_BFx24
+  [(match_operand:SVE_BFx24 1 "register_operand" "Uw<vector_count>")
+   (match_operand:SVE_BFx24 2 "register_operand" "Uw<vector_count>")]
+  SVE_FP_MUL))]
+  "TARGET_STREAMING_SME2 && TARGET_SVE_BFSCALE"
+  "bfmul\t%0, %1, %2"
+)
+
+;; BFMUL (multiple and single vector)
+;; svbfloat16x2_t svmul[_single_bf16_x2](svbfloat16x2_t zd, svbfloat16_t zm) 
__arm_streaming;
+;; svbfloat16x4_t svmul[_single_bf16_x4](svbfloat16x4_t zd, svbfloat16_t zm) 
__arm_streaming;
+;; BFMUL { <Zd1>.H-<Zd2>.H }, { <Zn1>.H-<Zn2>.H }, <Zm>.H
+;; BFMUL { <Zd1>.H-<Zd4>.H }, { <Zn1>.H-<Zn4>.H }, <Zm>.H
+(define_insn "@aarch64_sve_<optab><mode>_single"
+  [(set (match_operand:SVE_BFx24 0 "register_operand" "=Uw<vector_count>")
+ (unspec:SVE_BFx24
+  [(match_operand:SVE_BFx24 1 "register_operand" "Uw<vector_count>")
+   (match_operand:<VSINGLE> 2 "register_operand" "x")]
+  SVE_FP_MUL))]
+  "TARGET_STREAMING_SME2 && TARGET_SVE_BFSCALE"
+  "bfmul\t%0, %1, %2.h"
)

;; =========================================================================
@@ -4704,4 +4753,3 @@ (define_insn 
"@aarch64_sve2_<sve_fp_op><VNx4SF_ONLY:mode><VNx8HF_ONLY:mode>"
   }
   [(set_attr "sve_type" "sve_fp_mul")]
)
-
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 1dd942f377f..21f9682ef97 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -385,6 +385,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
#define TARGET_BF16_FP AARCH64_HAVE_ISA (BF16)
#define TARGET_BF16_SIMD (TARGET_BF16_FP && TARGET_SIMD)
#define TARGET_SVE_BF16 (TARGET_BF16_FP && TARGET_SVE)
+#define TARGET_SVE_BFSCALE (AARCH64_HAVE_ISA (SVE_BFSCALE))

/* PAUTH instructions are enabled through +pauth.  */
#define TARGET_PAUTH AARCH64_HAVE_ISA (PAUTH)
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index b425b0ed2ca..39b1e84edcc 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -501,10 +501,13 @@ (define_mode_iterator SVE_PARTIAL_F [VNx2HF VNx4HF 
VNx2SF])
(define_mode_iterator SVE_F [SVE_PARTIAL_F SVE_FULL_F])

;; Fully-packed SVE floating-point vector modes and their scalar equivalents.
-(define_mode_iterator SVE_FULL_F_SCALAR [SVE_FULL_F GPF_HF])
+(define_mode_iterator SVE_FULL_F_SCALAR [SVE_FULL_F GPF_HF (VNx8BF 
"TARGET_SVE_BFSCALE")])

(define_mode_iterator SVE_FULL_F_B16B16 [(VNx8BF "TARGET_SSVE_B16B16") 
SVE_FULL_F])

+(define_mode_iterator SVE_FULL_F_BFSCALE [SVE_FULL_F
+ (VNx8BF "TARGET_SVE_BFSCALE")])
+
(define_mode_iterator SVE_PARTIAL_F_B16B16 [(VNx2BF "TARGET_SSVE_B16B16")
    (VNx4BF "TARGET_SSVE_B16B16")
    SVE_PARTIAL_F])
@@ -746,10 +749,18 @@ (define_mode_iterator SVE_Ix24 [VNx32QI VNx16HI VNx8SI 
VNx4DI
(define_mode_iterator SVE_Fx24_NOBF [VNx16HF VNx8SF VNx4DF
     VNx32HF VNx16SF VNx8DF])

+(define_mode_iterator SVE_Fx24_BFSCALE [
+ SVE_Fx24_NOBF
+ (VNx16BF "TARGET_SVE_BFSCALE") ;; bf16x2
+ (VNx32BF "TARGET_SVE_BFSCALE") ;; bf16x4
+])
+
(define_mode_iterator SVE_Fx24 [(VNx16BF "TARGET_SSVE_B16B16")
(VNx32BF "TARGET_SSVE_B16B16")
SVE_Fx24_NOBF])

+(define_mode_iterator SVE_BFx24 [VNx16BF VNx32BF])
+
(define_mode_iterator SVE_SFx24 [VNx8SF VNx16SF])

;; The modes used to represent different ZA access sizes.
@@ -824,6 +835,7 @@ (define_c_enum "unspec"
     UNSPEC_FMAX ; Used in aarch64-simd.md.
     UNSPEC_FMAXNMV ; Used in aarch64-simd.md.
     UNSPEC_FMAXV ; Used in aarch64-simd.md.
+    UNSPEC_FMUL ; Used in aarch64-sve2.md.
     UNSPEC_FMIN ; Used in aarch64-simd.md.
     UNSPEC_FMINNMV ; Used in aarch64-simd.md.
     UNSPEC_FMINV ; Used in aarch64-simd.md.
@@ -2211,6 +2223,8 @@ (define_mode_attr V_INT_EQUIV [(V8QI "V8QI") (V16QI 
"V16QI")
       (VNx16QI "VNx16QI")
       (VNx8HI  "VNx8HI") (VNx8HF "VNx8HI")
       (VNx8BF  "VNx8HI")
+       (VNx16BF  "VNx16HI")
+       (VNx32BF  "VNx32HI")
       (VNx4SI  "VNx4SI") (VNx4SF "VNx4SI")
       (VNx2DI  "VNx2DI") (VNx2DF "VNx2DI")
       (VNx8SF  "VNx8SI") (VNx16SF "VNx16SI")
@@ -2792,17 +2806,20 @@ (define_mode_attr vec_or_offset [(V8QI "vec") (V16QI "vec") (V4HI 
"vec")
(V8HI "vec") (V2SI "vec") (V4SI "vec")
(V2DI "vec") (DI "offset")])

-(define_mode_attr b [(V4BF "b") (V4HF "") (V8BF "b") (V8HF "")
+(define_mode_attr b [(BF "b") (HF "") (SF "") (DF "")
+     (V4BF "b") (V4HF "") (V8BF "b") (V8HF "")
     (VNx2BF "b") (VNx2HF "") (VNx2SF "")
     (VNx4BF "b") (VNx4HF "") (VNx4SF "")
     (VNx8BF "b") (VNx8HF "") (VNx2DF "")
     (VNx16BF "b") (VNx16HF "") (VNx8SF "") (VNx4DF "")
     (VNx32BF "b") (VNx32HF "") (VNx16SF "") (VNx8DF "")])

-(define_mode_attr is_bf16 [(VNx2BF "true") (VNx4BF "true") (VNx8BF "true")
-   (VNx2HF "false") (VNx4HF "false") (VNx8HF "false")
-   (VNx2SF "false") (VNx4SF "false")
-   (VNx2DF "false")])
+(define_mode_attr is_bf16 [
+ (VNx2BF "true")  (VNx4BF "true")  (VNx8BF "true")  (VNx16BF "true")  (VNx32BF 
"true")
+ (VNx2HF "false") (VNx4HF "false") (VNx8HF "false") (VNx16HF "false") (VNx32HF 
"false")
+ (VNx2SF "false") (VNx4SF "false") (VNx8SF "false") (VNx16SF "false")
+ (VNx2DF "false") (VNx4DF "false") (VNx8DF "false")
+])

(define_mode_attr aligned_operand [(VNx16QI "register_operand")
   (VNx8HI "register_operand")
@@ -2829,22 +2846,29 @@ (define_mode_attr LD1_EXTENDQ_MEM [(VNx4SI "VNx1SI") (VNx4SF 
"VNx1SI")

;; Maps the output type of svscale to the corresponding int vector type in the
;; second argument.
-(define_mode_attr SVSCALE_SINGLE_INTARG [(VNx16HF "VNx8HI") ;; f16_x2 -> s16
- (VNx32HF "VNx8HI") ;; f16_x4 -> s16
- (VNx8SF "VNx4SI") ;; f32_x2 -> s32
- (VNx16SF "VNx4SI") ;; f32_x4 -> s32
- (VNx4DF "VNx2DI") ;; f64_x2 -> s64
- (VNx8DF "VNx2DI") ;; f64_x4 -> s64
+(define_mode_attr SVSCALE_SINGLE_INTARG [
+ (VNx16HF "VNx8HI") ;; f16_x2  -> s16
+ (VNx32HF "VNx8HI") ;; f16_x4  -> s16
+ (VNx16BF "VNx8HI") ;; bf16_x2 -> s16
+ (VNx32BF "VNx8HI") ;; bf16_x4 -> s16
+ (VNx8SF  "VNx4SI") ;; f32_x2  -> s32
+ (VNx16SF "VNx4SI") ;; f32_x4  -> s32
+ (VNx4DF  "VNx2DI") ;; f64_x2  -> s64
+ (VNx8DF  "VNx2DI") ;; f64_x4  -> s64
])

-(define_mode_attr SVSCALE_INTARG [(VNx16HF "VNx16HI") ;; f16_x2 -> s16x2
-  (VNx32HF "VNx32HI") ;; f16_x4 -> s16x4
-  (VNx8SF "VNx8SI") ;; f32_x2 -> s32_x2
-  (VNx16SF "VNx16SI") ;; f32_x4 -> s32_x4
-  (VNx4DF "VNx4DI") ;; f64_x2 -> s64_x2
-  (VNx8DF "VNx8DI") ;; f64_x4 -> s64_x4
+(define_mode_attr SVSCALE_INTARG [
+ (VNx16HF "VNx16HI") ;; f16_x2  -> s16x2
+ (VNx32HF "VNx32HI") ;; f16_x4  -> s16x4
+ (VNx16BF "VNx16HI") ;; bf16_x2 -> s16x2
+ (VNx32BF "VNx32HI") ;; bf16_x4 -> s16x4
+ (VNx8SF  "VNx8SI")  ;; f32_x2  -> s32_x2
+ (VNx16SF "VNx16SI") ;; f32_x4  -> s32_x4
+ (VNx4DF  "VNx4DI")  ;; f64_x2  -> s64_x2
+ (VNx8DF  "VNx8DI")  ;; f64_x4  -> s64_x4
])

+
;; -------------------------------------------------------------------
;; Code Iterators
;; -------------------------------------------------------------------
@@ -3644,6 +3668,8 @@ (define_int_iterator SVE_COND_FP_ADD [UNSPEC_COND_FADD])
(define_int_iterator SVE_COND_FP_SUB [UNSPEC_COND_FSUB])
(define_int_iterator SVE_COND_FP_MUL [UNSPEC_COND_FMUL])

+(define_int_iterator SVE_FP_MUL [UNSPEC_FMUL])
+
(define_int_iterator SVE_COND_FP_BINARY_I1 [UNSPEC_COND_FMAX
    UNSPEC_COND_FMAXNM
    UNSPEC_COND_FMIN
@@ -4205,6 +4231,7 @@ (define_int_attr optab [(UNSPEC_ANDF "and")
(UNSPEC_FMINNMQV "fminnmqv")
(UNSPEC_FMINNMV "smin")
(UNSPEC_FMINV "smin_nan")
+ (UNSPEC_FMUL "fmul")
        (UNSPEC_SMUL_HIGHPART "smulh")
        (UNSPEC_UMUL_HIGHPART "umulh")
(UNSPEC_FMLA "fma")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 87c0470c3db..bb43bf27658 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -23621,7 +23621,8 @@ Enable the Checked Pointer Arithmetic instructions.
@item sve-b16b16
Enable the SVE non-widening brain floating-point (@code{bf16}) extension.
This only has an effect when @code{sve2} or @code{sme2} are also enabled.
-
+@item sve-bfscale
+Enable the SVE_BFSCALE extension.
@end table

Feature @option{crypto} implies @option{aes}, @option{sha2}, and @option{simd},
diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c 
b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
index 284c2a23252..70f59b47aee 100644
--- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
@@ -111,6 +111,11 @@
#error Foo
#endif

+#pragma GCC target "+nothing+sve-bfscale"
+#ifndef __ARM_FEATURE_SVE_BFSCALE
+#error "__ARM_FEATURE_SVE_BFSCALE should be defined but isn't"
+#endif
+
#pragma GCC target "+nothing+sve2+sme-f8f16"
#ifndef __ARM_FEATURE_SME_F8F16
#error Foo
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x2.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x2.c
new file mode 100644
index 00000000000..d9e6ad1bb4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x2.c
@@ -0,0 +1,193 @@
+/* { dg-do assemble { target aarch64_asm_sve-bfscale_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sve-bfscale_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sve-bfscale"
+
+/*
+** mul_z0_z0_z4:
+** bfmul {z0\.h - z1\.h}, {z0\.h - z1\.h}, {z4\.h - z5\.h}
+** ret
+*/
+TEST_XN (mul_z0_z0_z4, svbfloat16x2_t, z0,
+ svmul_bf16_x2 (z0, z4),
+ svmul (z0, z4))
+
+/*
+** mul_z0_z4_z0:
+** bfmul {z0\.h - z1\.h}, {z4\.h - z5\.h}, {z0\.h - z1\.h}
+** ret
+*/
+TEST_XN (mul_z0_z4_z0, svbfloat16x2_t, z0,
+ svmul_bf16_x2 (z4, z0),
+ svmul (z4, z0))
+
+/*
+** mul_z0_z4_z28:
+** bfmul {z0\.h - z1\.h}, {z4\.h - z5\.h}, {z28\.h - z29\.h}
+** ret
+*/
+TEST_XN (mul_z0_z4_z28, svbfloat16x2_t, z0,
+ svmul_bf16_x2 (z4, z28),
+ svmul (z4, z28))
+
+/*
+** mul_z18_z18_z4:
+** bfmul {z18\.h - z19\.h}, {z18\.h - z19\.h}, {z4\.h - z5\.h}
+** ret
+*/
+TEST_XN (mul_z18_z18_z4, svbfloat16x2_t, z18,
+ svmul_bf16_x2 (z18, z4),
+ svmul (z18, z4))
+
+/*
+** mul_z23_z23_z18:
+** mov [^\n]+
+** mov [^\n]+
+** bfmul [^\n]+, {z18\.h - z19\.h}
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN (mul_z23_z23_z18, svbfloat16x2_t, z23,
+ svmul_bf16_x2 (z23, z18),
+ svmul (z23, z18))
+
+/*
+** mul_z28_z28_z0:
+** bfmul {z28\.h - z29\.h}, {z28\.h - z29\.h}, {z0\.h - z1\.h}
+** ret
+*/
+TEST_XN (mul_z28_z28_z0, svbfloat16x2_t, z28,
+ svmul_bf16_x2 (z28, z0),
+ svmul (z28, z0))
+
+/*
+** mul_z0_z0_z18:
+** bfmul {z0\.h - z1\.h}, {z0\.h - z1\.h}, {z18\.h - z19\.h}
+** ret
+*/
+TEST_XN (mul_z0_z0_z18, svbfloat16x2_t, z0,
+ svmul_bf16_x2 (z0, z18),
+ svmul (z0, z18))
+
+/*
+** mul_z4_z4_z23:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** bfmul {z4\.h - z5\.h}, {z4\.h - z5\.h}, [^\n]+
+** |
+** bfmul {z4\.h - z5\.h}, {z4\.h - z5\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_XN (mul_z4_z4_z23, svbfloat16x2_t, z4,
+ svmul_bf16_x2 (z4, z23),
+ svmul (z4, z23))
+
+/*
+** mul_single_z24_z24_z0:
+** bfmul {z24\.h - z25\.h}, {z24\.h - z25\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z24_z0, svbfloat16x2_t, svbfloat16_t, z24,
+ svmul_single_bf16_x2 (z24, z0),
+ svmul (z24, z0))
+
+/*
+** mul_single_z24_z28_z0:
+** bfmul {z24\.h - z25\.h}, {z28\.h - z29\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z28_z0, svbfloat16x2_t, svbfloat16_t, z24,
+ svmul_single_bf16_x2 (z28, z0),
+ svmul (z28, z0))
+
+/*
+** mul_single_z24_z1_z0:
+** (
+** mov z30\.d, z1\.d
+** mov z31\.d, z2\.d
+** |
+** mov z31\.d, z2\.d
+** mov z30\.d, z1\.d
+** )
+** bfmul {z24\.h - z25\.h}, {z30\.h - z31\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z1_z0, svbfloat16x2_t, svbfloat16_t, z24,
+ svmul_single_bf16_x2 (z1, z0),
+ svmul (z1, z0))
+
+/*
+** mul_single_z1_z24_z0:
+** bfmul {z30\.h - z31\.h}, {z24\.h - z25\.h}, z0\.h
+** (
+** mov z2\.d, z31\.d
+** mov z1\.d, z30\.d
+** |
+** mov z1\.d, z30\.d
+** mov z2\.d, z31\.d
+** )
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z1_z24_z0, svbfloat16x2_t, svbfloat16_t, z1,
+ svmul_single_bf16_x2 (z24, z0),
+ svmul (z24, z0))
+
+/*
+** mul_single_z1_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** bfmul ({z[0-9]+\.h - z[0-9]+\.h}), \1, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z1_z1_z0, svbfloat16x2_t, svbfloat16_t, z1,
+ svmul_single_bf16_x2 (z1, z0),
+ svmul (z1, z0))
+
+/*
+** mul_single_z18_z18_z0:
+** bfmul {z18\.h - z19\.h}, {z18\.h - z19\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z18_z18_z0, svbfloat16x2_t, svbfloat16_t, z18,
+ svmul_single_bf16_x2 (z18, z0),
+ svmul (z18, z0))
+
+/*
+** mul_single_awkward:
+** ...
+** bfmul {z0\.h - z1\.h}, {z30\.h - z31\.h}, z[0-9]+\.h
+** ret
+*/
+TEST_XN_SINGLE_AWKWARD (mul_single_awkward, svbfloat16x2_t, svbfloat16_t,
+ z0_res = svmul_single_bf16_x2 (z1, z0),
+ z0_res = svmul (z1, z0))
+
+/*
+** mul_single_z0_z0_z15:
+** ...
+** bfmul {z0\.h - z1\.h}, {z0\.h - z1\.h}, z15\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_Z15 (mul_single_z0_z0_z15, svbfloat16x2_t, svbfloat16_t,
+    z0 = svmul_single_bf16_x2 (z0, z15),
+    z0 = svmul (z0, z15))
+
+/*
+** mul_single_z24_z24_z16:
+** mov (z[0-7])\.d, z16\.d
+** bfmul {z24\.h - z25\.h}, {z24\.h - z25\.h}, \1\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z24_z16, svbfloat16x2_t, svbfloat16_t, z24,
+ svmul_single_bf16_x2 (z24, z16),
+ svmul (z24, z16))
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x4.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x4.c
new file mode 100644
index 00000000000..8da388e5e12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/mul_bf16_x4.c
@@ -0,0 +1,227 @@
+/* { dg-do assemble { target aarch64_asm_sve-bfscale_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sve-bfscale_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sve-bfscale"
+
+/*
+** mul_z0_z0_z4:
+** bfmul {z0\.h - z3\.h}, {z0\.h - z3\.h}, {z4\.h - z7\.h}
+** ret
+*/
+TEST_XN (mul_z0_z0_z4, svbfloat16x4_t, z0,
+ svmul_bf16_x4 (z0, z4),
+ svmul (z0, z4))
+
+/*
+** mul_z0_z4_z0:
+** bfmul {z0\.h - z3\.h}, {z4\.h - z7\.h}, {z0\.h - z3\.h}
+** ret
+*/
+TEST_XN (mul_z0_z4_z0, svbfloat16x4_t, z0,
+ svmul_bf16_x4 (z4, z0),
+ svmul (z4, z0))
+
+/*
+** mul_z0_z4_z28:
+** bfmul {z0\.h - z3\.h}, {z4\.h - z7\.h}, {z28\.h - z31\.h}
+** ret
+*/
+TEST_XN (mul_z0_z4_z28, svbfloat16x4_t, z0,
+ svmul_bf16_x4 (z4, z28),
+ svmul (z4, z28))
+
+/*
+** mul_z18_z18_z4:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul [^\n]+, {z4\.h - z7\.h}
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN (mul_z18_z18_z4, svbfloat16x4_t, z18,
+ svmul_bf16_x4 (z18, z4),
+ svmul (z18, z4))
+
+/*
+** mul_z23_z23_z28:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul [^\n]+, {z28\.h - z31\.h}
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN (mul_z23_z23_z28, svbfloat16x4_t, z23,
+ svmul_bf16_x4 (z23, z28),
+ svmul (z23, z28))
+
+/*
+** mul_z28_z28_z0:
+** bfmul {z28\.h - z31\.h}, {z28\.h - z31\.h}, {z0\.h - z3\.h}
+** ret
+*/
+TEST_XN (mul_z28_z28_z0, svbfloat16x4_t, z28,
+ svmul_bf16_x4 (z28, z0),
+ svmul (z28, z0))
+
+/*
+** mul_z0_z0_z18:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul {z0\.h - z3\.h}, {z0\.h - z3\.h}, [^\n]+
+** |
+** bfmul {z0\.h - z3\.h}, {z0\.h - z3\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_XN (mul_z0_z0_z18, svbfloat16x4_t, z0,
+ svmul_bf16_x4 (z0, z18),
+ svmul (z0, z18))
+
+/*
+** mul_z4_z4_z23:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul {z4\.h - z7\.h}, {z4\.h - z7\.h}, [^\n]+
+** |
+** bfmul {z4\.h - z7\.h}, {z4\.h - z7\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_XN (mul_z4_z4_z23, svbfloat16x4_t, z4,
+ svmul_bf16_x4 (z4, z23),
+ svmul (z4, z23))
+
+/*
+** mul_single_z24_z24_z0:
+** bfmul {z24\.h - z27\.h}, {z24\.h - z27\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z24_z0, svbfloat16x4_t, svbfloat16_t, z24,
+ svmul_single_bf16_x4 (z24, z0),
+ svmul (z24, z0))
+
+/*
+** mul_single_z24_z28_z0:
+** bfmul {z24\.h - z27\.h}, {z28\.h - z31\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z28_z0, svbfloat16x4_t, svbfloat16_t, z24,
+ svmul_single_bf16_x4 (z28, z0),
+ svmul (z28, z0))
+
+/*
+** mul_single_z24_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul {z24\.h - z27\.h}, {z28\.h - z31\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z1_z0, svbfloat16x4_t, svbfloat16_t, z24,
+ svmul_single_bf16_x4 (z1, z0),
+ svmul (z1, z0))
+
+/*
+** mul_single_z1_z24_z0:
+** bfmul {z28\.h - z31\.h}, {z24\.h - z27\.h}, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z1_z24_z0, svbfloat16x4_t, svbfloat16_t, z1,
+ svmul_single_bf16_x4 (z24, z0),
+ svmul (z24, z0))
+
+/*
+** mul_single_z1_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul ({z[0-9]+\.h - z[0-9]+\.h}), \1, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z1_z1_z0, svbfloat16x4_t, svbfloat16_t, z1,
+ svmul_single_bf16_x4 (z1, z0),
+ svmul (z1, z0))
+
+/*
+** mul_single_z18_z18_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfmul [^\n]+, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z18_z18_z0, svbfloat16x4_t, svbfloat16_t, z18,
+ svmul_single_bf16_x4 (z18, z0),
+ svmul (z18, z0))
+
+/*
+** mul_single_awkward:
+** ...
+** bfmul {z0\.h - z3\.h}, {z[0-9]+\.h - z[0-9]+\.h}, z[0-9]+\.h
+** ret
+*/
+TEST_XN_SINGLE_AWKWARD (mul_single_awkward, svbfloat16x4_t, svbfloat16_t,
+ z0_res = svmul_single_bf16_x4 (z1, z0),
+ z0_res = svmul (z1, z0))
+
+/*
+** mul_single_z0_z0_z15:
+** ...
+** bfmul {z0\.h - z3\.h}, {z0\.h - z3\.h}, z15\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_Z15 (mul_single_z0_z0_z15, svbfloat16x4_t, svbfloat16_t,
+    z0 = svmul_single_bf16_x4 (z0, z15),
+    z0 = svmul (z0, z15))
+
+/*
+** mul_single_z24_z24_z16:
+** mov (z[0-7])\.d, z16\.d
+** bfmul {z24\.h - z27\.h}, {z24\.h - z27\.h}, \1\.h
+** ret
+*/
+TEST_XN_SINGLE (mul_single_z24_z24_z16, svbfloat16x4_t, svbfloat16_t, z24,
+ svmul_single_bf16_x4 (z24, z16),
+ svmul (z24, z16))
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x2.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x2.c
new file mode 100644
index 00000000000..33a14e34653
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x2.c
@@ -0,0 +1,194 @@
+/* { dg-do assemble { target aarch64_asm_sve-bfscale_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sve-bfscale_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sve-bfscale"
+
+/*
+** bfscale_z0_z0_z4:
+** bfscale {z0\.h - z1\.h}, {z0\.h - z1\.h}, {z4\.h - z5\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z0_z0_z4, svbfloat16x2_t, svint16x2_t, z0,
+ svscale_bf16_x2 (z0, z4),
+ svscale (z0, z4))
+
+/*
+** bfscale_z4_z4_z0:
+** bfscale {z4\.h - z5\.h}, {z4\.h - z5\.h}, {z0\.h - z1\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z4_z4_z0, svint16x2_t, svbfloat16x2_t, z4,
+ svscale_bf16_x2 (z4, z0),
+ svscale (z4, z0))
+
+/*
+** bfscale_z18_z18_z4:
+** bfscale {z18\.h - z19\.h}, {z18\.h - z19\.h}, {z4\.h - z5\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z18_z18_z4, svbfloat16x2_t, svint16x2_t, z18,
+ svscale_bf16_x2 (z18, z4),
+ svscale (z18, z4))
+
+/*
+** bfscale_z23_z23_z18:
+** mov [^\n]+
+** mov [^\n]+
+** bfscale [^\n]+, {z18\.h - z19\.h}
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_DUAL_XN (bfscale_z23_z23_z18, svint16x2_t, svbfloat16x2_t, z23,
+ svscale_bf16_x2 (z23, z18),
+ svscale (z23, z18))
+
+
+/*
+** bfscale_z28_z28_z4:
+** bfscale {z28\.h - z29\.h}, {z28\.h - z29\.h}, {z4\.h - z5\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z28_z28_z4, svbfloat16x2_t, svint16x2_t, z28,
+ svscale_bf16_x2 (z28, z4),
+ svscale (z28, z4))
+
+/*
+** bfscale_z4_z4_z18:
+** bfscale {z4\.h - z5\.h}, {z4\.h - z5\.h}, {z18\.h - z19\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z4_z4_z18, svint16x2_t, svbfloat16x2_t, z4,
+ svscale_bf16_x2 (z4, z18),
+ svscale (z4, z18))
+
+/*
+** bfscale_z28_28_z23:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z28\.h - z29\.h}, {z28\.h - z29\.h}, [^\n]+
+** |
+** bfscale {z28\.h - z29\.h}, {z28\.h - z29\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_DUAL_XN (bfscale_z28_28_z23, svbfloat16x2_t, svint16x2_t, z28,
+ svscale_bf16_x2 (z28, z23),
+ svscale (z28, z23))
+
+/*
+** bfscale_single_z24_z24_z0:
+** bfscale {z24\.h - z25\.h}, {z24\.h - z25\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z24_z0, svbfloat16x2_t, svint16_t, z24,
+ svscale_single_bf16_x2 (z24, z0),
+ svscale (z24, z0))
+
+/*
+** bfscale_single_z24_z28_z0:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z24\.h - z25\.h}, {z24\.h - z25\.h}, z0\.h
+** |
+** bfscale {z28\.h - z29\.h}, {z28\.h - z29\.h}, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z28_z0, svbfloat16x2_t, svint16_t, z24,
+ svscale_single_bf16_x2 (z28, z0),
+ svscale (z28, z0))
+
+/*
+** bfscale_single_z24_z1_z0:
+** (
+** mov z24\.d, z1\.d
+** mov z25\.d, z2\.d
+** |
+** mov z25\.d, z2\.d
+** mov z24\.d, z1\.d
+** )
+** bfscale {z24\.h - z25\.h}, {z24\.h - z25\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z1_z0, svbfloat16x2_t, svint16_t, z24,
+ svscale_single_bf16_x2 (z1, z0),
+ svscale (z1, z0))
+
+/*
+** bfscale_single_z1_z24_z0:
+** bfscale {z24\.h - z25\.h}, {z24\.h - z25\.h}, z0\.h
+** (
+** mov z1\.d, z24\.d
+** mov z2\.d, z25\.d
+** |
+** mov z2\.d, z25\.d
+** mov z1\.d, z24\.d
+** )
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z1_z24_z0, svbfloat16x2_t, svint16_t, z1,
+ svscale_single_bf16_x2 (z24, z0),
+ svscale (z24, z0))
+
+/*
+** bfscale_single_z1_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** bfscale ({z[0-9]+\.h - z[0-9]+\.h}), \1, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z1_z1_z0, svbfloat16x2_t, svint16_t, z1,
+ svscale_single_bf16_x2 (z1, z0),
+ svscale (z1, z0))
+
+/*
+** bfscale_single_z18_z18_z0:
+** bfscale {z18\.h - z19\.h}, {z18\.h - z19\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z18_z18_z0, svbfloat16x2_t, svint16_t, z18,
+ svscale_single_bf16_x2 (z18, z0),
+ svscale (z18, z0))
+
+/*
+** bfscale_single_awkward:
+** ...
+** bfscale ({z[0-9]+\.h - z[0-9]+\.h}), \1, z[0-9]+\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_AWKWARD (bfscale_single_awkward, svbfloat16x2_t, svint16_t,
+ z0_res = svscale_single_bf16_x2 (z1, z0),
+ z0_res = svscale (z1, z0))
+
+/*
+** bfscale_single_z0_z0_z15:
+** ...
+** bfscale {z0\.h - z1\.h}, {z0\.h - z1\.h}, z15\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_Z15 (bfscale_single_z0_z0_z15, svbfloat16x2_t, svint16_t,
+    z0 = svscale_single_bf16_x2 (z0, z15),
+    z0 = svscale (z0, z15))
+
+/*
+** bfscale_single_z24_z24_z16:
+** mov (z[0-7])\.d, z16\.d
+** bfscale {z24\.h - z25\.h}, {z24\.h - z25\.h}, \1\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z24_z16, svbfloat16x2_t, svint16_t, z24,
+ svscale_single_bf16_x2 (z24, z16),
+ svscale (z24, z16))
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x4.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x4.c
new file mode 100644
index 00000000000..d9e90746a98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/scale_bf16_x4.c
@@ -0,0 +1,231 @@
+/* { dg-do assemble { target aarch64_asm_sve-bfscale_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sve-bfscale_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sve-bfscale"
+
+/*
+** bfscale_z0_z0_z4:
+** bfscale {z0\.h - z3\.h}, {z0\.h - z3\.h}, {z4\.h - z7\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z0_z0_z4, svbfloat16x4_t, svint16x4_t, z0,
+      svscale_bf16_x4 (z0, z4),
+      svscale (z0, z4))
+
+/*
+** bfscale_z4_z4_z0:
+** bfscale {z4\.h - z7\.h}, {z4\.h - z7\.h}, {z0\.h - z3\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z4_z4_z0, svint16x4_t, svbfloat16x4_t, z4,
+      svscale_bf16_x4 (z4, z0),
+      svscale (z4, z0))
+
+/*
+** bfscale_z18_z18_z4:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale [^\n]+, {z4\.h - z7\.h}
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_DUAL_XN (bfscale_z18_z18_z4, svbfloat16x4_t, svint16x4_t, z18,
+      svscale_bf16_x4 (z18, z4),
+      svscale (z18, z4))
+
+/*
+** bfscale_z23_z23_z28:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale [^\n]+, {z28\.h - z31\.h}
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_DUAL_XN (bfscale_z23_z23_z28, svint16x4_t, svbfloat16x4_t, z23,
+      svscale_bf16_x4 (z23, z28),
+      svscale (z23, z28))
+
+/*
+** bfscale_z28_z28_z4:
+** bfscale {z28\.h - z31\.h}, {z28\.h - z31\.h}, {z4\.h - z7\.h}
+** ret
+*/
+TEST_DUAL_XN (bfscale_z28_z28_z4, svbfloat16x4_t, svint16x4_t, z28,
+      svscale_bf16_x4 (z28, z4),
+      svscale (z28, z4))
+
+/*
+** bfscale_z4_z4_z18:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z4\.h - z7\.h}, {z4\.h - z7\.h}, [^\n]+
+** |
+** bfscale {z4\.h - z7\.h}, {z4\.h - z7\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_DUAL_XN (bfscale_z4_z4_z18, svint16x4_t, svbfloat16x4_t, z4,
+      svscale_bf16_x4 (z4, z18),
+      svscale (z4, z18))
+
+/*
+** bfscale_z0_z0_z23:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z0\.h - z3\.h}, {z0\.h - z3\.h}, [^\n]+
+** |
+** bfscale {z0\.h - z3\.h}, {z0\.h - z3\.h}, [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_DUAL_XN (bfscale_z0_z0_z23, svbfloat16x4_t, svint16x4_t, z0,
+      svscale_bf16_x4 (z0, z23),
+      svscale (z0, z23))
+
+/*
+** bfscale_single_z24_z24_z0:
+** bfscale {z24\.h - z27\.h}, {z24\.h - z27\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z24_z0, svbfloat16x4_t, svint16_t, z24,
+ svscale_single_bf16_x4 (z24, z0),
+ svscale (z24, z0))
+
+/*
+** bfscale_single_z24_z28_z0:
+** (
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z24\.h - z27\.h}, {z24\.h - z27\.h}, z0\.h
+** |
+** bfscale {z28\.h - z31\.h}, {z28\.h - z31\.h}, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** )
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z28_z0, svbfloat16x4_t, svint16_t, z24,
+ svscale_single_bf16_x4 (z28, z0),
+ svscale (z28, z0))
+
+/*
+** bfscale_single_z24_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale {z24\.h - z27\.h}, {z24\.h - z27\.h}, z0\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z1_z0, svbfloat16x4_t, svint16_t, z24,
+ svscale_single_bf16_x4 (z1, z0),
+ svscale (z1, z0))
+
+/*
+** bfscale_single_z1_z24_z0:
+** bfscale {z24\.h - z27\.h}, {z24\.h - z27\.h}, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z1_z24_z0, svbfloat16x4_t, svint16_t, z1,
+ svscale_single_bf16_x4 (z24, z0),
+ svscale (z24, z0))
+
+/*
+** bfscale_single_z1_z1_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale ({z[0-9]+\.h - z[0-9]+\.h}), \1, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z1_z1_z0, svbfloat16x4_t, svint16_t, z1,
+ svscale_single_bf16_x4 (z1, z0),
+ svscale (z1, z0))
+
+/*
+** bfscale_single_z18_z18_z0:
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** bfscale [^\n]+, z0\.h
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** mov [^\n]+
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z18_z18_z0, svbfloat16x4_t, svint16_t, z18,
+ svscale_single_bf16_x4 (z18, z0),
+ svscale (z18, z0))
+
+/*
+** bfscale_single_awkward:
+** ...
+** bfscale ({z[0-9]+\.h - z[0-9]+\.h}), \1, z[0-9]+\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_AWKWARD (bfscale_single_awkward, svbfloat16x4_t, svint16_t,
+ z0_res = svscale_single_bf16_x4 (z1, z0),
+ z0_res = svscale (z1, z0))
+
+/*
+** bfscale_single_z0_z0_z15:
+** ...
+** bfscale {z0\.h - z3\.h}, {z0\.h - z3\.h}, z15\.h
+** ...
+** ret
+*/
+TEST_XN_SINGLE_Z15 (bfscale_single_z0_z0_z15, svbfloat16x4_t, svint16_t,
+    z0 = svscale_single_bf16_x4 (z0, z15),
+    z0 = svscale (z0, z15))
+
+/*
+** bfscale_single_z24_z24_z16:
+** mov (z[0-7])\.d, z16\.d
+** bfscale {z24\.h - z27\.h}, {z24\.h - z27\.h}, \1\.h
+** ret
+*/
+TEST_XN_SINGLE (bfscale_single_z24_z24_z16, svbfloat16x4_t, svint16_t, z24,
+ svscale_single_bf16_x4 (z24, z16),
+ svscale (z24, z16))
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/scale_bf16.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/scale_bf16.c
new file mode 100644
index 00000000000..4e8ff3392ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/scale_bf16.c
@@ -0,0 +1,337 @@
+/* { dg-do assemble { target aarch64_asm_sve-bfscale_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sve-bfscale_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sve_acle.h"
+#pragma GCC target "+sve2,+sve-bfscale"
+#ifdef STREAMING_COMPATIBLE
+#pragma GCC target "+sme2"
+#endif
+
+/*
+** scale_bf16_m_tied1:
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_m_tied1, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_m (p0, z0, z4),
+     z0 = svscale_m (p0, z0, z4))
+
+/*
+** scale_bf16_m_tied2:
+** mov (z[0-9]+)\.d, z0\.d
+** movprfx z0, z4
+** bfscale z0\.h, p0/m, z0\.h, \1\.h
+** ret
+*/
+TEST_DUAL_Z_REV (scale_bf16_m_tied2, svbfloat16_t, svint16_t,
+ z0_res = svscale_bf16_m (p0, z4, z0),
+ z0_res = svscale_m (p0, z4, z0))
+
+/*
+** scale_bf16_m_untied:
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_m_untied, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_m (p0, z1, z4),
+     z0 = svscale_m (p0, z1, z4))
+
+/*
+** scale_w0_bf16_m_tied1:
+** mov (z[0-9]+\.h), w0
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_m_tied1, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_m (p0, z0, x0),
+ z0 = svscale_m (p0, z0, x0))
+
+/*
+** scale_w0_bf16_m_untied:
+** mov (z[0-9]+\.h), w0
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_m_untied, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_m (p0, z1, x0),
+ z0 = svscale_m (p0, z1, x0))
+
+/*
+** scale_3_bf16_m_tied1:
+** mov (z[0-9]+\.h), #3
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_m_tied1, svbfloat16_t,
+ z0 = svscale_n_bf16_m (p0, z0, 3),
+ z0 = svscale_m (p0, z0, 3))
+
+/*
+** scale_3_bf16_m_untied:
+** mov (z[0-9]+\.h), #3
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_m_untied, svbfloat16_t,
+ z0 = svscale_n_bf16_m (p0, z1, 3),
+ z0 = svscale_m (p0, z1, 3))
+
+/*
+** scale_m3_bf16_m:
+** mov (z[0-9]+\.h), #-3
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_m3_bf16_m, svbfloat16_t,
+ z0 = svscale_n_bf16_m (p0, z0, -3),
+ z0 = svscale_m (p0, z0, -3))
+
+/*
+** scale_bf16_z_tied1:
+** movprfx z0\.h, p0/z, z0\.h
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_z_tied1, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_z (p0, z0, z4),
+     z0 = svscale_z (p0, z0, z4))
+
+/*
+** scale_bf16_z_tied2:
+** mov (z[0-9]+)\.d, z0\.d
+** movprfx z0\.h, p0/z, z4\.h
+** bfscale z0\.h, p0/m, z0\.h, \1\.h
+** ret
+*/
+TEST_DUAL_Z_REV (scale_bf16_z_tied2, svbfloat16_t, svint16_t,
+ z0_res = svscale_bf16_z (p0, z4, z0),
+ z0_res = svscale_z (p0, z4, z0))
+
+/*
+** scale_bf16_z_untied:
+** movprfx z0\.h, p0/z, z1\.h
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_z_untied, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_z (p0, z1, z4),
+     z0 = svscale_z (p0, z1, z4))
+
+/*
+** scale_w0_bf16_z_tied1:
+** mov (z[0-9]+\.h), w0
+** movprfx z0\.h, p0/z, z0\.h
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_z_tied1, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_z (p0, z0, x0),
+ z0 = svscale_z (p0, z0, x0))
+
+/*
+** scale_w0_bf16_z_untied:
+** mov (z[0-9]+\.h), w0
+** movprfx z0\.h, p0/z, z1\.h
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_z_untied, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_z (p0, z1, x0),
+ z0 = svscale_z (p0, z1, x0))
+
+/*
+** scale_3_bf16_z_tied1:
+** mov (z[0-9]+\.h), #3
+** movprfx z0\.h, p0/z, z0\.h
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_z_tied1, svbfloat16_t,
+ z0 = svscale_n_bf16_z (p0, z0, 3),
+ z0 = svscale_z (p0, z0, 3))
+
+/*
+** scale_3_bf16_z_untied:
+** mov (z[0-9]+\.h), #3
+** movprfx z0\.h, p0/z, z1\.h
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_z_untied, svbfloat16_t,
+ z0 = svscale_n_bf16_z (p0, z1, 3),
+ z0 = svscale_z (p0, z1, 3))
+
+/*
+** scale_m3_bf16_z:
+** mov (z[0-9]+\.h), #-3
+** movprfx z0\.h, p0/z, z0\.h
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_m3_bf16_z, svbfloat16_t,
+ z0 = svscale_n_bf16_z (p0, z0, -3),
+ z0 = svscale_z (p0, z0, -3))
+
+/*
+** scale_bf16_x_tied1:
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_x_tied1, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_x (p0, z0, z4),
+     z0 = svscale_x (p0, z0, z4))
+
+/*
+** scale_bf16_x_tied2:
+** mov (z[0-9]+)\.d, z0\.d
+** movprfx z0, z4
+** bfscale z0\.h, p0/m, z0\.h, \1\.h
+** ret
+*/
+TEST_DUAL_Z_REV (scale_bf16_x_tied2, svbfloat16_t, svint16_t,
+ z0_res = svscale_bf16_x (p0, z4, z0),
+ z0_res = svscale_x (p0, z4, z0))
+
+/*
+** scale_bf16_x_untied:
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, z4\.h
+** ret
+*/
+TEST_DUAL_Z (scale_bf16_x_untied, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_x (p0, z1, z4),
+     z0 = svscale_x (p0, z1, z4))
+
+/*
+** scale_w0_bf16_x_tied1:
+** mov (z[0-9]+\.h), w0
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_x_tied1, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_x (p0, z0, x0),
+ z0 = svscale_x (p0, z0, x0))
+
+/*
+** scale_w0_bf16_x_untied:
+** mov (z[0-9]+\.h), w0
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_ZX (scale_w0_bf16_x_untied, svbfloat16_t, int16_t,
+ z0 = svscale_n_bf16_x (p0, z1, x0),
+ z0 = svscale_x (p0, z1, x0))
+
+/*
+** scale_3_bf16_x_tied1:
+** mov (z[0-9]+\.h), #3
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_x_tied1, svbfloat16_t,
+ z0 = svscale_n_bf16_x (p0, z0, 3),
+ z0 = svscale_x (p0, z0, 3))
+
+/*
+** scale_3_bf16_x_untied:
+** mov (z[0-9]+\.h), #3
+** movprfx z0, z1
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_3_bf16_x_untied, svbfloat16_t,
+ z0 = svscale_n_bf16_x (p0, z1, 3),
+ z0 = svscale_x (p0, z1, 3))
+
+/*
+** scale_m3_bf16_x:
+** mov (z[0-9]+\.h), #-3
+** bfscale z0\.h, p0/m, z0\.h, \1
+** ret
+*/
+TEST_UNIFORM_Z (scale_m3_bf16_x, svbfloat16_t,
+ z0 = svscale_n_bf16_x (p0, z0, -3),
+ z0 = svscale_x (p0, z0, -3))
+
+/*
+** ptrue_scale_bf16_x_tied1:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_DUAL_Z (ptrue_scale_bf16_x_tied1, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_x (svptrue_b16 (), z0, z4),
+     z0 = svscale_x (svptrue_b16 (), z0, z4))
+
+/*
+** ptrue_scale_bf16_x_tied2:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_DUAL_Z_REV (ptrue_scale_bf16_x_tied2, svbfloat16_t, svint16_t,
+ z0_res = svscale_bf16_x (svptrue_b16 (), z4, z0),
+ z0_res = svscale_x (svptrue_b16 (), z4, z0))
+
+/*
+** ptrue_scale_bf16_x_untied:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_DUAL_Z (ptrue_scale_bf16_x_untied, svbfloat16_t, svint16_t,
+     z0 = svscale_bf16_x (svptrue_b16 (), z1, z4),
+     z0 = svscale_x (svptrue_b16 (), z1, z4))
+
+/*
+** ptrue_scale_3_bf16_x_tied1:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_UNIFORM_Z (ptrue_scale_3_bf16_x_tied1, svbfloat16_t,
+ z0 = svscale_n_bf16_x (svptrue_b16 (), z0, 3),
+ z0 = svscale_x (svptrue_b16 (), z0, 3))
+
+/*
+** ptrue_scale_3_bf16_x_untied:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_UNIFORM_Z (ptrue_scale_3_bf16_x_untied, svbfloat16_t,
+ z0 = svscale_n_bf16_x (svptrue_b16 (), z1, 3),
+ z0 = svscale_x (svptrue_b16 (), z1, 3))
+
+/*
+** ptrue_scale_m3_bf16_x_tied1:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_UNIFORM_Z (ptrue_scale_m3_bf16_x_tied1, svbfloat16_t,
+ z0 = svscale_n_bf16_x (svptrue_b16 (), z0, -3),
+ z0 = svscale_x (svptrue_b16 (), z0, -3))
+
+/*
+** ptrue_scale_m3_bf16_x_untied:
+** ...
+** ptrue p[0-9]+\.b[^\n]*
+** ...
+** ret
+*/
+TEST_UNIFORM_Z (ptrue_scale_m3_bf16_x_untied, svbfloat16_t,
+ z0 = svscale_n_bf16_x (svptrue_b16 (), z1, -3),
+ z0 = svscale_x (svptrue_b16 (), z1, -3))
+
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/bfscale.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/bfscale.c
new file mode 100644
index 00000000000..051ff47b3bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/bfscale.c
@@ -0,0 +1,114 @@
+// { dg-options "-std=c23 -fsyntax-only" }
+// { dg-do compile }
+
+#pragma GCC target "+sve,+sve2,+sme,+sme2,+sve-bfscale"
+static_assert (__ARM_FEATURE_SVE2 == 1);
+static_assert (__ARM_FEATURE_SME2 == 1);
+static_assert (__ARM_FEATURE_SVE_BFSCALE == 1);
+#include <arm_sve.h>
+#include <arm_sme.h>
+
+/*
+- BFSCALE (predicated)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SVE2 != 0
+  svbfloat16_t svscale[_bf16]_m (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_bf16]_x (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_bf16]_z (svbool_t pg, svbfloat16_t zdn, svint16_t zm);
+  svbfloat16_t svscale[_n_bf16]_m (svbool_t pg, svbfloat16_t zdn, int16_t zm);
+  svbfloat16_t svscale[_n_bf16]_x (svbool_t pg, svbfloat16_t zdn, int16_t zm);
+  svbfloat16_t svscale[_n_bf16]_z (svbool_t pg, svbfloat16_t zdn, int16_t zm); 
 */
+
+void
+svscale_predicated_explicit_ok (svbool_t p, svbfloat16_t bf16x1,
+ svint16_t i16x1, int16_t i16)
+{
+  bf16x1 = svscale_bf16_m (p, bf16x1, i16x1);
+  bf16x1 = svscale_bf16_x (p, bf16x1, i16x1);
+  bf16x1 = svscale_bf16_z (p, bf16x1, i16x1);
+
+  bf16x1 = svscale_n_bf16_m (p, bf16x1, i16);
+  bf16x1 = svscale_n_bf16_x (p, bf16x1, i16);
+  bf16x1 = svscale_n_bf16_z (p, bf16x1, i16);
+}
+
+void
+svscale_predicated_inferred_ok (svbool_t p, svbfloat16_t bf16x1,
+ svbfloat16x4_t bf16x4, svint16_t i16x1,
+ int16_t i16)
+{
+  bf16x1 = svscale_m (p, bf16x1, i16x1);
+  bf16x1 = svscale_x (p, bf16x1, i16x1);
+  bf16x1 = svscale_z (p, bf16x1, i16x1);
+
+  bf16x1 = svscale_m (p, bf16x1, i16);
+  bf16x1 = svscale_x (p, bf16x1, i16);
+  bf16x1 = svscale_z (p, bf16x1, i16);
+}
+
+/*
+- BFSCALE (multiple vectors)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svscale[_bf16_x2] (svbfloat16x2_t zdn, svint16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svscale[_bf16_x4] (svbfloat16x4_t zdn, svint16x4_t zm) 
__arm_streaming;
+
+- BFSCALE (multiple and single vector)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svscale[_single_bf16_x2] (svbfloat16x2_t zn, svint16_t zm) 
__arm_streaming;
+  svbfloat16x4_t svscale[_single_bf16_x4] (svbfloat16x4_t zn, svint16_t zm) 
__arm_streaming;  */
+
+void
+svscale_explicit_ok (svbfloat16_t bf16x1, svbfloat16x2_t bf16x2,
+     svbfloat16x4_t bf16x4, svint16_t i16x1, svint16x2_t i16x2,
+     svint16x4_t i16x4) __arm_streaming
+{
+  bf16x2 = svscale_bf16_x2 (bf16x2, i16x2);
+  bf16x4 = svscale_bf16_x4 (bf16x4, i16x4);
+
+  bf16x2 = svscale_single_bf16_x2 (bf16x2, i16x1);
+  bf16x4 = svscale_single_bf16_x4 (bf16x4, i16x1);
+}
+
+void
+svscale_inferred_ok (svbfloat16x2_t bf16x2, svbfloat16x4_t bf16x4,
+     svint16_t i16x1, svint16x2_t i16x2,
+     svint16x4_t i16x4) __arm_streaming
+{
+  bf16x2 = svscale_bf16_x2 (bf16x2, i16x2);
+  bf16x4 = svscale_bf16_x4 (bf16x4, i16x4);
+
+  bf16x2 = svscale_single_bf16_x2 (bf16x2, i16x1);
+  bf16x4 = svscale_single_bf16_x4 (bf16x4, i16x1);
+}
+
+/*
+- BFMUL (multiple vectors)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svmul[_bf16_x2] (svbfloat16x2_t zdn, svbfloat16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svmul[_bf16_x4] (svbfloat16x4_t zdn, svbfloat16x4_t zm) 
__arm_streaming;
+
+- BFMUL (multiple and single vector)
+  // Only if __ARM_FEATURE_SVE_BFSCALE != 0 && __ARM_FEATURE_SME2 != 0
+  svbfloat16x2_t svmul[_single_bf16_x2] (svbfloat16x2_t zn, svbfloat16x2_t zm) 
__arm_streaming;
+  svbfloat16x4_t svmul[_single_bf16_x4] (svbfloat16x4_t zn, svbfloat16x4_t zm) 
__arm_streaming;  */
+
+void
+svmul_explicit_ok (svbfloat16_t bf16x1, svbfloat16x2_t bf16x2,
+   svbfloat16x4_t bf16x4) __arm_streaming
+{
+  svmul_bf16_x2 (bf16x2, bf16x2);
+  svmul_bf16_x4 (bf16x4, bf16x4);
+
+  svmul_single_bf16_x2 (bf16x2, bf16x1);
+  svmul_single_bf16_x4 (bf16x4, bf16x1);
+}
+
+void
+svmul_inferred_ok (svbfloat16_t bf16x1, svbfloat16x2_t bf16x2,
+   svbfloat16x4_t bf16x4) __arm_streaming
+{
+  svmul (bf16x2, bf16x2);
+  svmul (bf16x4, bf16x4);
+
+  svmul (bf16x2, bf16x1);
+  svmul (bf16x4, bf16x1);
+}
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 2b450669c3d..87c21664422 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -12682,7 +12682,7 @@ set exts {
set exts_sve2 {
     "sme-f8f16" "sme-f8f32"
     "sme-b16b16" "sme-f16f16" "sme-i16i64" "sme" "sme2" "sme2p1"
-    "ssve-fp8dot2" "ssve-fp8dot4" "ssve-fp8fma"
+    "ssve-fp8dot2" "ssve-fp8dot4" "ssve-fp8fma" "sve-bfscale"
}

foreach { aarch64_ext } $exts {
--
2.43.0


Reply via email to