+2020-01-16 Stam Markianos-Wright <stam.markianos-wright@arm.com>
+
+ * config.gcc: Add arm_bf16.h.
+ * config/arm/arm-builtins.c (arm_mangle_builtin_type): Fix comment.
+ (arm_simd_builtin_std_type): Add BFmode.
+ (arm_init_simd_builtin_types): Define element types for vector types.
+ (arm_init_bf16_types): New function.
+ (arm_init_builtins): Add arm_init_bf16_types function call.
+ * config/arm/arm-modes.def: Add BFmode and V4BF, V8BF vector modes.
+ * config/arm/arm-simd-builtin-types.def: Add V4BF, V8BF.
+ * config/arm/arm.c (aapcs_vfp_sub_candidate): Add BFmode.
+ (arm_hard_regno_mode_ok): Add BFmode and tidy up statements.
+ (arm_vector_mode_supported_p): Add V4BF, V8BF.
+ (arm_mangle_type): Add __bf16.
+ * config/arm/arm.h: Add V4BF, V8BF to VALID_NEON_DREG_MODE,
+ VALID_NEON_QREG_MODE respectively. Add export arm_bf16_type_node,
+ arm_bf16_ptr_type_node.
+ * config/arm/arm.md: Add BFmode to movhf expand, mov pattern and
+ define_split between ARM registers.
+ * config/arm/arm_bf16.h: New file.
+ * config/arm/arm_neon.h: Add arm_bf16.h and Bfloat vector types.
+ * config/arm/iterators.md: (ANY64_BF, VDXMOV, VHFBF, HFBF, fporbf): New.
+ (VQXMOV): Add V8BF.
+ * config/arm/neon.md: Add BF vector types to movhf NEON move patterns.
+ * config/arm/vfp.md: Add BFmode to movhf patterns.
+
2020-01-16 Mihail Ionescu <mihail.ionescu@arm.com>
2020-01-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
arm*-*-*)
cpu_type=arm
extra_objs="arm-builtins.o aarch-common.o"
- extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h"
+ extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h"
target_type_format_char='%'
c_target_objs="arm-c.o"
cxx_target_objs="arm-c.o"
#define v8qi_UP E_V8QImode
#define v4hi_UP E_V4HImode
#define v4hf_UP E_V4HFmode
+#define v4bf_UP E_V4BFmode
#define v2si_UP E_V2SImode
#define v2sf_UP E_V2SFmode
#define di_UP E_DImode
#define v16qi_UP E_V16QImode
#define v8hi_UP E_V8HImode
#define v8hf_UP E_V8HFmode
+#define v8bf_UP E_V8BFmode
#define v4si_UP E_V4SImode
#define v4sf_UP E_V4SFmode
#define v2di_UP E_V2DImode
#define ei_UP E_EImode
#define oi_UP E_OImode
#define hf_UP E_HFmode
+#define bf_UP E_BFmode
#define si_UP E_SImode
#define void_UP E_VOIDmode
-
+#define sf_UP E_SFmode
#define UP(X) X##_UP
typedef struct {
/* The user-visible __fp16 type. */
tree arm_fp16_type_node = NULL_TREE;
+
+/* Back-end node type for brain float (bfloat) types. */
+tree arm_bf16_type_node = NULL_TREE;
+tree arm_bf16_ptr_type_node = NULL_TREE;
+
static tree arm_simd_intOI_type_node = NULL_TREE;
static tree arm_simd_intEI_type_node = NULL_TREE;
static tree arm_simd_intCI_type_node = NULL_TREE;
arm_mangle_builtin_type (const_tree type)
{
const char *mangle;
- /* Walk through all the AArch64 builtins types tables to filter out the
+ /* Walk through all the Arm builtins types tables to filter out the
incoming type. */
if ((mangle = arm_mangle_builtin_vector_type (type))
|| (mangle = arm_mangle_builtin_scalar_type (type)))
return float_type_node;
case E_DFmode:
return double_type_node;
+ case E_BFmode:
+ return arm_bf16_type_node;
default:
gcc_unreachable ();
}
arm_simd_types[Float32x2_t].eltype = float_type_node;
arm_simd_types[Float32x4_t].eltype = float_type_node;
+ /* Init Bfloat vector types with underlying __bf16 scalar type. */
+ arm_simd_types[Bfloat16x4_t].eltype = arm_bf16_type_node;
+ arm_simd_types[Bfloat16x8_t].eltype = arm_bf16_type_node;
+
for (i = 0; i < nelts; i++)
{
tree eltype = arm_simd_types[i].eltype;
arm_builtin_decls[fcode] = fndecl;
}
+/* Initialize the backend REAL_TYPE type supporting bfloat types. */
+static void
+arm_init_bf16_types (void)
+{
+ arm_bf16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (arm_bf16_type_node) = 16;
+ SET_TYPE_MODE (arm_bf16_type_node, BFmode);
+ layout_type (arm_bf16_type_node);
+
+ lang_hooks.types.register_builtin_type (arm_bf16_type_node, "__bf16");
+ arm_bf16_ptr_type_node = build_pointer_type (arm_bf16_type_node);
+}
+
/* Set up ACLE builtins, even builtins for instructions that are not
in the current target ISA to allow the user to compile particular modules
with different target specific options that differ from the command line
arm_init_neon_builtins which uses it. */
arm_init_fp16_builtins ();
+ arm_init_bf16_types ();
+
if (TARGET_MAYBE_HARD_FLOAT)
{
arm_init_neon_builtins ();
VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
VECTOR_MODE (FLOAT, HF, 2); /* V2HF */
+FLOAT_MODE (BF, 2, 0);
+ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format);
+VECTOR_MODE (FLOAT, BF, 4); /* V4BF. */
+VECTOR_MODE (FLOAT, BF, 8); /* V8BF. */
+
/* Fraction and accumulator vector modes. */
VECTOR_MODES (FRACT, 4); /* V4QQ V2HQ */
VECTOR_MODES (UFRACT, 4); /* V4UQQ V2UHQ */
ENTRY (Float16x8_t, V8HF, none, 128, float16, 19)
ENTRY (Float32x4_t, V4SF, none, 128, float32, 19)
+ ENTRY (Bfloat16x4_t, V4BF, none, 64, bfloat16, 20)
+ ENTRY (Bfloat16x8_t, V8BF, none, 128, bfloat16, 20)
{
case REAL_TYPE:
mode = TYPE_MODE (type);
- if (mode != DFmode && mode != SFmode && mode != HFmode)
+ if (mode != DFmode && mode != SFmode && mode != HFmode && mode != BFmode)
return -1;
if (*modep == VOIDmode)
if (TARGET_HARD_FLOAT && IS_VFP_REGNUM (regno))
{
- if (mode == SFmode || mode == SImode)
- return VFP_REGNO_OK_FOR_SINGLE (regno);
-
if (mode == DFmode)
return VFP_REGNO_OK_FOR_DOUBLE (regno);
- if (mode == HFmode)
- return VFP_REGNO_OK_FOR_SINGLE (regno);
-
- /* VFP registers can hold HImode values. */
- if (mode == HImode)
+ if (mode == HFmode || mode == BFmode || mode == HImode
+ || mode == SFmode || mode == SImode)
return VFP_REGNO_OK_FOR_SINGLE (regno);
if (TARGET_NEON)
/* Neon also supports V2SImode, etc. listed in the clause below. */
if (TARGET_NEON && (mode == V2SFmode || mode == V4SImode || mode == V8HImode
|| mode == V4HFmode || mode == V16QImode || mode == V4SFmode
- || mode == V2DImode || mode == V8HFmode))
+ || mode == V2DImode || mode == V8HFmode || mode == V4BFmode
+ || mode == V8BFmode))
return true;
if ((TARGET_NEON || TARGET_IWMMXT)
&& lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type))
return "St9__va_list";
- /* Half-precision float. */
+ /* Half-precision floating point types. */
if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16)
- return "Dh";
+ {
+ if (TYPE_MODE (type) == BFmode)
+ return "u6__bf16";
+ else
+ return "Dh";
+ }
/* Try mangling as a Neon type, TYPE_NAME is non-NULL if this is a
builtin type. */
the backend. Defined in arm-builtins.c. */
extern tree arm_fp16_type_node;
+/* This type is the user-visible __bf16. We need it in a few places in
+ the backend. Defined in arm-builtins.c. */
+extern tree arm_bf16_type_node;
+extern tree arm_bf16_ptr_type_node;
+
\f
#undef CPP_SPEC
#define CPP_SPEC "%(subtarget_cpp_spec) \
/* Modes valid for Neon D registers. */
#define VALID_NEON_DREG_MODE(MODE) \
((MODE) == V2SImode || (MODE) == V4HImode || (MODE) == V8QImode \
- || (MODE) == V4HFmode || (MODE) == V2SFmode || (MODE) == DImode)
+ || (MODE) == V4HFmode || (MODE) == V2SFmode || (MODE) == DImode \
+ || (MODE) == V4BFmode)
/* Modes valid for Neon Q registers. */
#define VALID_NEON_QREG_MODE(MODE) \
((MODE) == V4SImode || (MODE) == V8HImode || (MODE) == V16QImode \
- || (MODE) == V8HFmode || (MODE) == V4SFmode || (MODE) == V2DImode)
+ || (MODE) == V8HFmode || (MODE) == V4SFmode || (MODE) == V2DImode \
+ || (MODE) == V8BFmode)
/* Structure modes valid for Neon registers. */
#define VALID_NEON_STRUCT_MODE(MODE) \
)
(define_split
- [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
- (match_operand:ANY64 1 "arm_general_register_operand" ""))]
+ [(set (match_operand:ANY64_BF 0 "arm_general_register_operand" "")
+ (match_operand:ANY64_BF 1 "arm_general_register_operand" ""))]
"TARGET_EITHER && reload_completed"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))]
(set_attr "length" "2,4,4,2,4,2,2,4,4")]
)
-;; HFmode moves
-(define_expand "movhf"
- [(set (match_operand:HF 0 "general_operand")
- (match_operand:HF 1 "general_operand"))]
+;; HFmode and BFmode moves.
+(define_expand "mov<mode>"
+ [(set (match_operand:HFBF 0 "general_operand")
+ (match_operand:HFBF 1 "general_operand"))]
"TARGET_EITHER"
"
- gcc_checking_assert (aligned_operand (operands[0], HFmode));
- gcc_checking_assert (aligned_operand (operands[1], HFmode));
+ gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
+ gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
if (TARGET_32BIT)
{
if (MEM_P (operands[0]))
- operands[1] = force_reg (HFmode, operands[1]);
+ operands[1] = force_reg (<MODE>mode, operands[1]);
}
else /* TARGET_THUMB1 */
{
if (can_create_pseudo_p ())
{
if (!REG_P (operands[0]))
- operands[1] = force_reg (HFmode, operands[1]);
+ operands[1] = force_reg (<MODE>mode, operands[1]);
}
}
"
)
-(define_insn "*arm32_movhf"
- [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
- (match_operand:HF 1 "general_operand" " m,r,r,F"))]
+(define_insn "*arm32_mov<mode>"
+ [(set (match_operand:HFBF 0 "nonimmediate_operand" "=r,m,r,r")
+ (match_operand:HFBF 1 "general_operand" " m,r,r,F"))]
"TARGET_32BIT && !TARGET_HARD_FLOAT
- && ( s_register_operand (operands[0], HFmode)
- || s_register_operand (operands[1], HFmode))"
+ && ( s_register_operand (operands[0], <MODE>mode)
+ || s_register_operand (operands[1], <MODE>mode))"
"*
switch (which_alternative)
{
case 0: /* ARM register from memory */
- return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
+ return \"ldrh%?\\t%0, %1\\t%@ __<fporbf>\";
case 1: /* memory from ARM register */
- return \"strh%?\\t%1, %0\\t%@ __fp16\";
+ return \"strh%?\\t%1, %0\\t%@ __<fporbf>\";
case 2: /* ARM register from ARM register */
- return \"mov%?\\t%0, %1\\t%@ __fp16\";
+ return \"mov%?\\t%0, %1\\t%@ __<fporbf>\";
case 3: /* ARM register from constant */
{
long bits;
rtx ops[4];
bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
- HFmode);
+ <MODE>mode);
ops[0] = operands[0];
ops[1] = GEN_INT (bits);
ops[2] = GEN_INT (bits & 0xff00);
--- /dev/null
+/* Arm BF16 intrinsics include file.
+
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#ifndef _GCC_ARM_BF16_H
+#define _GCC_ARM_BF16_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef __bf16 bfloat16_t;
+typedef float float32_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
#endif
#include <arm_fp16.h>
+#include <arm_bf16.h>
#include <stdint.h>
typedef __simd64_int8_t int8x8_t;
typedef float float32_t;
+typedef __simd128_bfloat16_t bfloat16x8_t;
+typedef __simd64_bfloat16_t bfloat16x4_t;
+
/* The Poly types are user visible and live in their own world,
keep them that way. */
typedef __builtin_neon_poly8 poly8_t;
;; registers.
(define_mode_iterator ANY64 [DI DF V8QI V4HI V4HF V2SI V2SF])
+;; Additional definition of ANY64 that also includes the special V4BF mode.
+;; BFmode is allowed only on define_split between ARM registers.
+(define_mode_iterator ANY64_BF [DI DF V8QI V4HI V4BF V4HF V2SI V2SF])
+
(define_mode_iterator ANY128 [V2DI V2DF V16QI V8HI V4SI V4SF])
;; A list of integer modes that are up to one word long
;; Double-width vector modes plus 64-bit elements.
(define_mode_iterator VDX [V8QI V4HI V4HF V2SI V2SF DI])
+;; Double-width vector modes plus 64-bit elements,
+;; with V4BFmode added, suitable for moves.
+(define_mode_iterator VDXMOV [V8QI V4HI V4HF V4BF V2SI V2SF DI])
+
;; Double-width vector modes, with V4HF - for vldN_lane and vstN_lane.
(define_mode_iterator VD_LANE [V8QI V4HI V4HF V2SI V2SF])
;; Quad-width vector modes without floating-point elements.
(define_mode_iterator VQI [V16QI V8HI V4SI])
-;; Quad-width vector modes, with TImode added, for moves.
-(define_mode_iterator VQXMOV [V16QI V8HI V8HF V4SI V4SF V2DI TI])
+;; Quad-width vector modes, with TImode and V8BFmode added, suitable for moves.
+(define_mode_iterator VQXMOV [V16QI V8HI V8HF V8BF V4SI V4SF V2DI TI])
;; Opaque structure types wider than TImode.
(define_mode_iterator VSTRUCT [EI OI CI XI])
;; Vector modes for 16-bit floating-point support.
(define_mode_iterator VH [V8HF V4HF])
+;; 16-bit floating-point vector modes suitable for moving (includes BFmode).
+(define_mode_iterator VHFBF [V8HF V4HF V4BF V8BF])
+
+;; 16-bit floating-point scalar modes suitable for moving (includes BFmode).
+(define_mode_iterator HFBF [HF BF])
+
;; Iterators used for fixed-point support.
(define_mode_iterator FIXED [QQ HQ SQ UQQ UHQ USQ HA SA UHA USA])
;; vtbl<n> suffix for NEON vector modes.
(define_mode_attr VTAB_n [(TI "2") (EI "3") (OI "4")])
+;; fp16 or bf16 marker for 16-bit float modes.
+(define_mode_attr fporbf [(HF "fp16") (BF "bf16")])
+
;; (Opposite) mode to convert to/from for NEON mode conversions.
(define_mode_attr V_CVTTO [(V2SI "V2SF") (V2SF "V2SI")
(V4SI "V4SF") (V4SF "V4SI")])
(V4HF "") (V8HF "_q")
(V2SF "") (V4SF "_q")
(V4HF "") (V8HF "_q")
+ (V4BF "") (V8BF "_q")
(DI "") (V2DI "_q")
(DF "") (V2DF "_q")
(HF "")])
[(set_attr "type" "neon_store1_1reg")])
(define_insn "*neon_mov<mode>"
- [(set (match_operand:VDX 0 "nonimmediate_operand"
+ [(set (match_operand:VDXMOV 0 "nonimmediate_operand"
"=w,Un,w, w, w, ?r,?w,?r, ?Us,*r")
- (match_operand:VDX 1 "general_operand"
+ (match_operand:VDXMOV 1 "general_operand"
" w,w, Dm,Dn,Uni, w, r, Usi,r,*r"))]
"TARGET_NEON
&& (register_operand (operands[0], <MODE>mode)
})
(define_expand "mov<mode>"
- [(set (match_operand:VH 0 "s_register_operand")
- (match_operand:VH 1 "s_register_operand"))]
+ [(set (match_operand:VHFBF 0 "s_register_operand")
+ (match_operand:VHFBF 1 "s_register_operand"))]
"TARGET_NEON"
{
gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
(set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
)
-;; HFmode moves
+;; HFmode and BFmode moves
-(define_insn "*movhf_vfp_fp16"
- [(set (match_operand:HF 0 "nonimmediate_operand"
- "= r,m,t,r,t,r,t,t,Um,r")
- (match_operand:HF 1 "general_operand"
- " m,r,t,r,r,t,Dv,Um,t,F"))]
+(define_insn "*mov<mode>_vfp_<mode>16"
+ [(set (match_operand:HFBF 0 "nonimmediate_operand"
+ "= ?r,?m,t,r,t,r,t, t, Um,r")
+ (match_operand:HFBF 1 "general_operand"
+ " m,r,t,r,r,t,Dv,Um,t, F"))]
"TARGET_32BIT
&& TARGET_VFP_FP16INST
- && (s_register_operand (operands[0], HFmode)
- || s_register_operand (operands[1], HFmode))"
+ && (s_register_operand (operands[0], <MODE>mode)
+ || s_register_operand (operands[1], <MODE>mode))"
{
switch (which_alternative)
{
case 0: /* ARM register from memory. */
- return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
+ return \"ldrh%?\\t%0, %1\\t%@ __<fporbf>\";
case 1: /* Memory from ARM register. */
- return \"strh%?\\t%1, %0\\t%@ __fp16\";
+ return \"strh%?\\t%1, %0\\t%@ __<fporbf>\";
case 2: /* S register from S register. */
- return \"vmov\\t%0, %1\t%@ __fp16\";
+ return \"vmov\\t%0, %1\t%@ __<fporbf>\";
case 3: /* ARM register from ARM register. */
- return \"mov%?\\t%0, %1\\t%@ __fp16\";
+ return \"mov%?\\t%0, %1\\t%@ __<fporbf>\";
case 4: /* S register from ARM register. */
case 5: /* ARM register from S register. */
case 6: /* S register from immediate. */
- return \"vmov.f16\\t%0, %1\t%@ __fp16\";
+ return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\";
case 7: /* S register from memory. */
return \"vld1.16\\t{%z0}, %A1\";
case 8: /* Memory from S register. */
rtx ops[4];
bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
- HFmode);
+ <MODE>mode);
ops[0] = operands[0];
ops[1] = GEN_INT (bits);
ops[2] = GEN_INT (bits & 0xff00);
(const_int 8))])]
)
-(define_insn "*movhf_vfp_neon"
- [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
- (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
+(define_insn "*mov<mode>_vfp_neon"
+ [(set (match_operand:HFBF 0 "nonimmediate_operand" "= t,Um,?r,?m,t,r,t,r,r")
+ (match_operand:HFBF 1 "general_operand" " Um, t, m, r,t,r,r,t,F"))]
"TARGET_32BIT
&& TARGET_HARD_FLOAT && TARGET_NEON_FP16
&& !TARGET_VFP_FP16INST
- && ( s_register_operand (operands[0], HFmode)
- || s_register_operand (operands[1], HFmode))"
+ && ( s_register_operand (operands[0], <MODE>mode)
+ || s_register_operand (operands[1], <MODE>mode))"
"*
switch (which_alternative)
{
case 1: /* memory from S register */
return \"vst1.16\\t{%z1}, %A0\";
case 2: /* ARM register from memory */
- return \"ldrh\\t%0, %1\\t%@ __fp16\";
+ return \"ldrh\\t%0, %1\\t%@ __<fporbf>\";
case 3: /* memory from ARM register */
- return \"strh\\t%1, %0\\t%@ __fp16\";
+ return \"strh\\t%1, %0\\t%@ __<fporbf>\";
case 4: /* S register from S register */
return \"vmov.f32\\t%0, %1\";
case 5: /* ARM register from ARM register */
- return \"mov\\t%0, %1\\t%@ __fp16\";
+ return \"mov\\t%0, %1\\t%@ __<fporbf>\";
case 6: /* S register from ARM register */
return \"vmov\\t%0, %1\";
case 7: /* ARM register from S register */
rtx ops[4];
bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
- HFmode);
+ <MODE>mode);
ops[0] = operands[0];
ops[1] = GEN_INT (bits);
ops[2] = GEN_INT (bits & 0xff00);
)
;; FP16 without element load/store instructions.
-(define_insn "*movhf_vfp"
- [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
- (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
+(define_insn "*mov<mode>_vfp"
+ [(set (match_operand:HFBF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
+ (match_operand:HFBF 1 "general_operand" " m,r,t,r,r,t,F"))]
"TARGET_32BIT
&& TARGET_HARD_FLOAT
&& !TARGET_NEON_FP16
&& !TARGET_VFP_FP16INST
- && ( s_register_operand (operands[0], HFmode)
- || s_register_operand (operands[1], HFmode))"
+ && ( s_register_operand (operands[0], <MODE>mode)
+ || s_register_operand (operands[1], <MODE>mode))"
"*
switch (which_alternative)
{
case 0: /* ARM register from memory */
- return \"ldrh\\t%0, %1\\t%@ __fp16\";
+ return \"ldrh\\t%0, %1\\t%@ __<fporbf>\";
case 1: /* memory from ARM register */
- return \"strh\\t%1, %0\\t%@ __fp16\";
+ return \"strh\\t%1, %0\\t%@ __<fporbf>\";
case 2: /* S register from S register */
return \"vmov.f32\\t%0, %1\";
case 3: /* ARM register from ARM register */
- return \"mov\\t%0, %1\\t%@ __fp16\";
+ return \"mov\\t%0, %1\\t%@ __<fporbf>\";
case 4: /* S register from ARM register */
return \"vmov\\t%0, %1\";
case 5: /* ARM register from S register */
rtx ops[4];
bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
- HFmode);
+ <MODE>mode);
ops[0] = operands[0];
ops[1] = GEN_INT (bits);
ops[2] = GEN_INT (bits & 0xff00);
+2020-01-16 Stam Markianos-Wright <stam.markianos-wright@arm.com>
+
+ * g++.dg/abi/mangle-neon.C: Add BF16 SIMD types.
+ * g++.dg/ext/arm-bf16/bf16-mangle-1.C: New test.
+ * gcc.target/arm/bfloat16_scalar_1_1.c: New test.
+ * gcc.target/arm/bfloat16_scalar_1_2.c: New test.
+ * gcc.target/arm/bfloat16_scalar_2_1.c: New test.
+ * gcc.target/arm/bfloat16_scalar_2_2.c: New test.
+ * gcc.target/arm/bfloat16_scalar_3_1.c: New test.
+ * gcc.target/arm/bfloat16_scalar_3_2.c: New test.
+ * gcc.target/arm/bfloat16_scalar_4.c: New test.
+ * gcc.target/arm/bfloat16_simd_1_1.c: New test.
+ * gcc.target/arm/bfloat16_simd_1_2.c: New test.
+ * gcc.target/arm/bfloat16_simd_2_1.c: New test.
+ * gcc.target/arm/bfloat16_simd_2_2.c: New test.
+ * gcc.target/arm/bfloat16_simd_3_1.c: New test.
+ * gcc.target/arm/bfloat16_simd_3_2.c: New test.
+
2020-01-16 Mihail Ionescu <mihail.ionescu@arm.com>
2020-01-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
void f19 (poly8_t a) {}
void f20 (poly16_t a) {}
+void f21 (bfloat16x4_t a) {}
+void f22 (bfloat16x8_t a) {}
+
// { dg-final { scan-assembler "_Z2f015__simd64_int8_t:" } }
// { dg-final { scan-assembler "_Z2f116__simd64_int16_t:" } }
// { dg-final { scan-assembler "_Z2f216__simd64_int32_t:" } }
// { dg-final { scan-assembler "_Z3f1816__simd128_int8_tS_:" } }
// { dg-final { scan-assembler "_Z3f19a:" } }
// { dg-final { scan-assembler "_Z3f20s:" } }
+// { dg-final { scan-assembler "_Z3f2120__simd64_bfloat16_t:" } }
+// { dg-final { scan-assembler "_Z3f2220__simd128_bfloat16_t:" } }
--- /dev/null
+/* { dg-do compile { target arm*-*-* } } */
+
+/* Test mangling */
+
+/* { dg-final { scan-assembler "\t.global\t_Z1fPu6__bf16" } } */
+void f (__bf16 *x) { }
+
+/* { dg-final { scan-assembler "\t.global\t_Z1gPu6__bf16S_" } } */
+void g (__bf16 *x, __bf16 *y) { }
+
+/* { dg-final { scan-assembler "\t.global\t_ZN1SIu6__bf16u6__bf16E1iE" } } */
+template <typename T, typename U> struct S { static int i; };
+template <> int S<__bf16, __bf16>::i = 3;
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a+bf16 -mfloat-abi=softfp -mfpu=auto" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=hard -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+#pragma GCC push_options
+#pragma GCC target ("+bf16")
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+#pragma GCC pop_options
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=softfp -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+#pragma GCC push_options
+#pragma GCC target ("+bf16")
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+#pragma GCC pop_options
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=hard -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=softfp -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_bf16.h>
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**bfloat_mov_ww:
+** ...
+** vmov.f32 s1, s15
+** ...
+** bx lr
+*/
+void bfloat_mov_ww (void)
+{
+ register bfloat16_t x asm ("s15");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_rw:
+** ...
+** vmov s1, r4
+** ...
+** bx lr
+*/
+void bfloat_mov_rw (void)
+{
+ register bfloat16_t x asm ("r4");
+ register bfloat16_t y asm ("s1");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "t" (y));
+}
+
+/*
+**bfloat_mov_wr:
+** ...
+** vmov r4, s1
+** ...
+** bx lr
+*/
+void bfloat_mov_wr (void)
+{
+ register bfloat16_t x asm ("s1");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=t" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rr:
+** ...
+** mov r4, r5 @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rr (void)
+{
+ register bfloat16_t x asm ("r5");
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
+/*
+**bfloat_mov_rm:
+** ...
+** strh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_rm (void)
+{
+ register bfloat16_t x asm ("r4");
+ volatile bfloat16_t y;
+ asm volatile ("#foo" : "=r" (x));
+ y = x;
+ asm volatile ("#foo" : : : "memory");
+}
+
+/*
+**bfloat_mov_mr:
+** ...
+** ldrh r4, \[.*\] @ __bf16
+** ...
+** bx lr
+*/
+void bfloat_mov_mr (void)
+{
+ volatile bfloat16_t x;
+ register bfloat16_t y asm ("r4");
+ asm volatile ("#foo" : : : "memory");
+ y = x;
+ asm volatile ("#foo" :: "r" (y));
+}
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-std=c99 -pedantic-errors -O3 --save-temps" } */
+
+#include <arm_bf16.h>
+
+_Complex bfloat16_t stacktest1 (_Complex bfloat16_t __a)
+{
+ volatile _Complex bfloat16_t b = __a;
+ return b;
+}
+
+/* { dg-error {ISO C does not support plain 'complex' meaning 'double complex'} "" { target *-*-* } 8 } */
+/* { dg-error {expected '=', ',', ';', 'asm' or '__attribute__' before 'stacktest1'} "" { target *-*-* } 8 } */
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** vstr d[0-9]+, \[sp\]
+** vldr d[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** vst1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** vld1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a+bf16 -mfloat-abi=softfp -mfpu=auto" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** strd r[0-9]+, \[sp\]
+** ldrd r[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** stm sp, {r[0-9]+-r[0-9]+}
+** ldmia sp, {r[0-9]+-r[0-9]+}
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=hard -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+#pragma GCC push_options
+#pragma GCC target ("+bf16")
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** vstr d[0-9]+, \[sp\]
+** vldr d[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** vst1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** vld1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
+
+#pragma GCC pop_options
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=softfp -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+#pragma GCC push_options
+#pragma GCC target ("+bf16")
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** strd r[0-9]+, \[sp\]
+** ldrd r[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** stm sp, {r[0-9]+-r[0-9]+}
+** ldmia sp, {r[0-9]+-r[0-9]+}
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
+
+#pragma GCC pop_options
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=hard -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+/*
+**stacktest1:
+** ...
+** vst1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** vld1.16 {d[0-9]+\[[0-9]+\]}, \[r[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** vstr d[0-9]+, \[sp\]
+** vldr d[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** vst1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** vld1.64 {d[0-9]+-d[0-9]+}, \[sp:[0-9]+\]
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
+
--- /dev/null
+/* { dg-do assemble { target { arm*-*-* } } } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a -mfloat-abi=softfp -mfpu=neon-fp-armv8" } */
+/* { dg-additional-options "-O3 --save-temps -std=gnu90" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_neon.h>
+
+/*
+**stacktest1:
+** ...
+** strh r[0-9]+, \[r[0-9]+\] @ __bf16
+** ldrh r[0-9]+, \[sp, #[0-9]+\] @ __bf16
+** ...
+** bx lr
+*/
+bfloat16_t stacktest1 (bfloat16_t __a)
+{
+ volatile bfloat16_t b = __a;
+ return b;
+}
+
+/*
+**stacktest2:
+** ...
+** strd r[0-9]+, \[sp\]
+** ldrd r[0-9]+, \[sp\]
+** ...
+** bx lr
+*/
+bfloat16x4_t stacktest2 (bfloat16x4_t __a)
+{
+ volatile bfloat16x4_t b = __a;
+ return b;
+}
+
+/*
+**stacktest3:
+** ...
+** stm sp, {r[0-9]+-r[0-9]+}
+** ldmia sp, {r[0-9]+-r[0-9]+}
+** ...
+** bx lr
+*/
+bfloat16x8_t stacktest3 (bfloat16x8_t __a)
+{
+ volatile bfloat16x8_t b = __a;
+ return b;
+}
+
+/* Test compilation of __attribute__ vectors of 8, 16, 32, etc. BFloats. */
+typedef bfloat16_t v8bf __attribute__((vector_size(16)));
+typedef bfloat16_t v16bf __attribute__((vector_size(32)));
+typedef bfloat16_t v32bf __attribute__((vector_size(64)));
+typedef bfloat16_t v64bf __attribute__((vector_size(128)));
+typedef bfloat16_t v128bf __attribute__((vector_size(256)));
+
+v8bf stacktest4 (v8bf __a)
+{
+ volatile v8bf b = __a;
+ return b;
+}
+
+v16bf stacktest5 (v16bf __a)
+{
+ volatile v16bf b = __a;
+ return b;
+}
+
+v32bf stacktest6 (v32bf __a)
+{
+ volatile v32bf b = __a;
+ return b;
+}
+
+v64bf stacktest7 (v64bf __a)
+{
+ volatile v64bf b = __a;
+ return b;
+}
+
+v128bf stacktest8 (v128bf __a)
+{
+ volatile v128bf b = __a;
+ return b;
+}
+
+/* Test use of constant values to assign values to vectors. */
+
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf c2 (void) { return (v2bf) 0x12345678; }
+
+