From fdcddba8f29ea3878851b8b4cd37d0fd3476d3bf Mon Sep 17 00:00:00 2001 From: Przemyslaw Wirkus Date: Tue, 14 Dec 2021 14:03:38 +0000 Subject: [PATCH] aarch64: Add LS64 extension and intrinsics This patch is adding support for LS64 (Armv8.7-A Load/Store 64 Byte extension) which is part of Armv8.7-A architecture. Changes include missing plumbing for TARGET_LS64, LS64 data structure and intrinsics defined in ACLE. Machine description of intrinsics is using new V8DI mode added in a separate patch. __ARM_FEATURE_LS64 is defined if the Armv8.7-A LS64 instructions for atomic 64-byte access to device memory are supported. New compiler internal type is added wrapping ACLE struct data512_t: typedef struct { uint64_t val[8]; } __arm_data512_t; gcc/ChangeLog: * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): Define AARCH64_LS64_BUILTIN_LD64B, AARCH64_LS64_BUILTIN_ST64B, AARCH64_LS64_BUILTIN_ST64BV, AARCH64_LS64_BUILTIN_ST64BV0. (aarch64_init_ls64_builtin_decl): Helper function. (aarch64_init_ls64_builtins): Helper function. (aarch64_init_ls64_builtins_types): Helper function. (aarch64_general_init_builtins): Init LS64 intrisics for TARGET_LS64. (aarch64_expand_builtin_ls64): LS64 intrinsics expander. (aarch64_general_expand_builtin): Handle aarch64_expand_builtin_ls64. (ls64_builtins_data): New helper struct. (v8di_UP): New define. * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define __ARM_FEATURE_LS64. * config/aarch64/aarch64.c (aarch64_classify_address): Enforce the V8DI range (7-bit signed scaled) for both ends of the range. * config/aarch64/aarch64-simd.md (movv8di): New pattern. (aarch64_movv8di): New pattern. * config/aarch64/aarch64.h (AARCH64_ISA_LS64): New define. (TARGET_LS64): New define. * config/aarch64/aarch64.md: Add UNSPEC_LD64B, UNSPEC_ST64B, UNSPEC_ST64BV and UNSPEC_ST64BV0. (ld64b): New define_insn. (st64b): New define_insn. (st64bv): New define_insn. (st64bv0): New define_insn. * config/aarch64/arm_acle.h (data512_t): New type derived from __arm_data512_t. (__arm_data512_t): New internal type. (__arm_ld64b): New intrinsic. (__arm_st64b): New intrinsic. (__arm_st64bv): New intrinsic. (__arm_st64bv0): New intrinsic. * config/arm/types.md: Add new type ls64. gcc/testsuite/ChangeLog: * gcc.target/aarch64/acle/ls64_asm.c: New test. * gcc.target/aarch64/acle/ls64_ld64b.c: New test. * gcc.target/aarch64/acle/ls64_ld64b-2.c: New test. * gcc.target/aarch64/acle/ls64_ld64b-3.c: New test. * gcc.target/aarch64/acle/ls64_st64b.c: New test. * gcc.target/aarch64/acle/ls64_ld_st_o0.c: New test. * gcc.target/aarch64/acle/ls64_st64b-2.c: New test. * gcc.target/aarch64/acle/ls64_st64bv.c: New test. * gcc.target/aarch64/acle/ls64_st64bv-2.c: New test. * gcc.target/aarch64/acle/ls64_st64bv-3.c: New test. * gcc.target/aarch64/acle/ls64_st64bv0.c: New test. * gcc.target/aarch64/acle/ls64_st64bv0-2.c: New test. * gcc.target/aarch64/acle/ls64_st64bv0-3.c: New test. * gcc.target/aarch64/pragma_cpp_predefs_2.c: Add checks for __ARM_FEATURE_LS64. --- gcc/config/aarch64/aarch64-builtins.c | 130 +++++++++++++++++++++ gcc/config/aarch64/aarch64-c.c | 2 + gcc/config/aarch64/aarch64-simd.md | 48 ++++++++ gcc/config/aarch64/aarch64.c | 4 + gcc/config/aarch64/aarch64.h | 4 + gcc/config/aarch64/aarch64.md | 52 +++++++++ gcc/config/aarch64/arm_acle.h | 37 ++++++ gcc/config/arm/types.md | 1 + gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c | 58 +++++++++ .../gcc.target/aarch64/acle/ls64_ld64b-2.c | 15 +++ .../gcc.target/aarch64/acle/ls64_ld64b-3.c | 15 +++ gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c | 15 +++ .../gcc.target/aarch64/acle/ls64_ld_st_o0.c | 30 +++++ .../gcc.target/aarch64/acle/ls64_st64b-2.c | 15 +++ gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv-2.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv-3.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv0-2.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv0-3.c | 15 +++ .../gcc.target/aarch64/acle/ls64_st64bv0.c | 15 +++ .../gcc.target/aarch64/pragma_cpp_predefs_2.c | 14 +++ 22 files changed, 545 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 303e1e5..0d09fe9 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -49,6 +49,7 @@ #include "gimple-fold.h" #define v8qi_UP E_V8QImode +#define v8di_UP E_V8DImode #define v4hi_UP E_V4HImode #define v4hf_UP E_V4HFmode #define v2si_UP E_V2SImode @@ -607,6 +608,11 @@ enum aarch64_builtins AARCH64_MEMTAG_BUILTIN_SET_TAG, AARCH64_MEMTAG_BUILTIN_GET_TAG, AARCH64_MEMTAG_BUILTIN_END, + /* LS64 builtins. */ + AARCH64_LS64_BUILTIN_LD64B, + AARCH64_LS64_BUILTIN_ST64B, + AARCH64_LS64_BUILTIN_ST64BV, + AARCH64_LS64_BUILTIN_ST64BV0, AARCH64_BUILTIN_MAX }; @@ -1571,6 +1577,70 @@ aarch64_init_memtag_builtins (void) #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL } +/* Add builtins for Load/store 64 Byte instructions. */ + +typedef struct +{ + const char *name; + unsigned int code; + tree type; +} ls64_builtins_data; + +static GTY(()) tree ls64_arm_data_t = NULL_TREE; + +static void +aarch64_init_ls64_builtins_types (void) +{ + /* Synthesize: + + typedef struct { + uint64_t val[8]; + } __arm_data512_t; */ + const char *tuple_type_name = "__arm_data512_t"; + tree node_type = get_typenode_from_name (UINT64_TYPE); + tree array_type = build_array_type_nelts (node_type, 8); + SET_TYPE_MODE (array_type, V8DImode); + + gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type)); + gcc_assert (TYPE_ALIGN (array_type) == 64); + + tree field = build_decl (input_location, FIELD_DECL, + get_identifier ("val"), array_type); + + ls64_arm_data_t = lang_hooks.types.simulate_record_decl (input_location, + tuple_type_name, + make_array_slice (&field, 1)); + + gcc_assert (TYPE_MODE (ls64_arm_data_t) == V8DImode); + gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t)); + gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == 64); +} + +static void +aarch64_init_ls64_builtins (void) +{ + aarch64_init_ls64_builtins_types (); + + ls64_builtins_data data[4] = { + {"__builtin_aarch64_ld64b", AARCH64_LS64_BUILTIN_LD64B, + build_function_type_list (ls64_arm_data_t, + const_ptr_type_node, NULL_TREE)}, + {"__builtin_aarch64_st64b", AARCH64_LS64_BUILTIN_ST64B, + build_function_type_list (void_type_node, ptr_type_node, + ls64_arm_data_t, NULL_TREE)}, + {"__builtin_aarch64_st64bv", AARCH64_LS64_BUILTIN_ST64BV, + build_function_type_list (uint64_type_node, ptr_type_node, + ls64_arm_data_t, NULL_TREE)}, + {"__builtin_aarch64_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0, + build_function_type_list (uint64_type_node, ptr_type_node, + ls64_arm_data_t, NULL_TREE)}, + }; + + for (size_t i = 0; i < ARRAY_SIZE (data); ++i) + aarch64_builtin_decls[data[i].code] + = aarch64_general_add_builtin (data[i].name, data[i].type, data[i].code); +} + /* Initialize fpsr fpcr getters and setters. */ static void @@ -1660,6 +1730,9 @@ aarch64_general_init_builtins (void) if (TARGET_MEMTAG) aarch64_init_memtag_builtins (); + + if (TARGET_LS64) + aarch64_init_ls64_builtins (); } /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */ @@ -2130,6 +2203,57 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target) return target; } +/* Function to expand an expression EXP which calls one of the Load/Store + 64 Byte extension (LS64) builtins FCODE with the result going to TARGET. */ +static rtx +aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target) +{ + expand_operand ops[3]; + + switch (fcode) + { + case AARCH64_LS64_BUILTIN_LD64B: + { + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + create_output_operand (&ops[0], target, V8DImode); + create_input_operand (&ops[1], op0, DImode); + expand_insn (CODE_FOR_ld64b, 2, ops); + return ops[0].value; + } + case AARCH64_LS64_BUILTIN_ST64B: + { + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1)); + create_output_operand (&ops[0], op0, DImode); + create_input_operand (&ops[1], op1, V8DImode); + expand_insn (CODE_FOR_st64b, 2, ops); + return const0_rtx; + } + case AARCH64_LS64_BUILTIN_ST64BV: + { + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1)); + create_output_operand (&ops[0], target, DImode); + create_input_operand (&ops[1], op0, DImode); + create_input_operand (&ops[2], op1, V8DImode); + expand_insn (CODE_FOR_st64bv, 3, ops); + return ops[0].value; + } + case AARCH64_LS64_BUILTIN_ST64BV0: + { + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1)); + create_output_operand (&ops[0], target, DImode); + create_input_operand (&ops[1], op0, DImode); + create_input_operand (&ops[2], op1, V8DImode); + expand_insn (CODE_FOR_st64bv0, 3, ops); + return ops[0].value; + } + } + + gcc_unreachable (); +} + /* Expand a random number builtin EXP with code FCODE, putting the result int TARGET. If IGNORE is true the return value is ignored. */ @@ -2388,6 +2512,12 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target, || fcode == AARCH64_TME_BUILTIN_TCANCEL) return aarch64_expand_builtin_tme (fcode, exp, target); + if (fcode == AARCH64_LS64_BUILTIN_LD64B + || fcode == AARCH64_LS64_BUILTIN_ST64B + || fcode == AARCH64_LS64_BUILTIN_ST64BV + || fcode == AARCH64_LS64_BUILTIN_ST64BV0) + return aarch64_expand_builtin_ls64 (fcode, exp, target); + if (fcode >= AARCH64_MEMTAG_BUILTIN_START && fcode <= AARCH64_MEMTAG_BUILTIN_END) return aarch64_expand_builtin_memtag (fcode, exp, target); diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c index d6653e4..3af3e5c 100644 --- a/gcc/config/aarch64/aarch64-c.c +++ b/gcc/config/aarch64/aarch64-c.c @@ -200,6 +200,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile); aarch64_def_or_undef (TARGET_BF16_FP, "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); + aarch64_def_or_undef (TARGET_LS64, + "__ARM_FEATURE_LS64", pfile); /* Not for ACLE, but required to keep "float.h" correct if we switch target between implementations that do or do not support ARMv8.2-A diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 175a9f0..9ebf795 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -7123,6 +7123,15 @@ } }) +(define_expand "movv8di" + [(set (match_operand:V8DI 0 "nonimmediate_operand") + (match_operand:V8DI 1 "general_operand"))] + "TARGET_SIMD" +{ + if (can_create_pseudo_p () && MEM_P (operands[0])) + operands[1] = force_reg (V8DImode, operands[1]); +}) + (define_expand "aarch64_ld1x3" [(match_operand:VSTRUCT_3QD 0 "register_operand") (match_operand:DI 1 "register_operand")] @@ -7253,6 +7262,17 @@ (set_attr "length" ",4,4")] ) +(define_insn "*aarch64_movv8di" + [(set (match_operand:V8DI 0 "nonimmediate_operand" "=r,m,r") + (match_operand:V8DI 1 "general_operand" " r,r,m"))] + "!BYTES_BIG_ENDIAN + && (register_operand (operands[0], V8DImode) + || register_operand (operands[1], V8DImode))" + "#" + [(set_attr "type" "multiple,multiple,multiple") + (set_attr "length" "32,16,16")] +) + (define_insn "aarch64_be_ld1" [(set (match_operand:VALLDI_F16 0 "register_operand" "=w") (unspec:VALLDI_F16 [(match_operand:VALLDI_F16 1 @@ -7496,6 +7516,34 @@ FAIL; }) +(define_split + [(set (match_operand:V8DI 0 "nonimmediate_operand") + (match_operand:V8DI 1 "general_operand"))] + "TARGET_SIMD && reload_completed" + [(const_int 0)] +{ + if (register_operand (operands[0], V8DImode) + && register_operand (operands[1], V8DImode)) + { + aarch64_simd_emit_reg_reg_move (operands, DImode, 8); + DONE; + } + else if ((register_operand (operands[0], V8DImode) + && memory_operand (operands[1], V8DImode)) + || (memory_operand (operands[0], V8DImode) + && register_operand (operands[1], V8DImode))) + { + for (int offset = 0; offset < 64; offset += 16) + emit_move_insn (simplify_gen_subreg (TImode, operands[0], + V8DImode, offset), + simplify_gen_subreg (TImode, operands[1], + V8DImode, offset)); + DONE; + } + else + FAIL; +}) + (define_expand "aarch64_ldr" [(match_operand:VSTRUCT_QD 0 "register_operand") (match_operand:DI 1 "register_operand")] diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index d11a40c..f07330c 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10016,6 +10016,10 @@ aarch64_classify_address (struct aarch64_address_info *info, && (aarch64_offset_9bit_signed_unscaled_p (mode, offset) || offset_12bit_unsigned_scaled_p (mode, offset))); + if (mode == V8DImode) + return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) + && aarch64_offset_7bit_signed_scaled_p (DImode, offset + 48)); + /* A 7bit offset check because OImode will emit a ldp/stp instruction (only big endian will get here). For ldp/stp instructions, the offset is scaled for the size of a diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 5a590aa..fb2d2ed 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -319,6 +319,7 @@ extern unsigned aarch64_architecture_version; #define AARCH64_ISA_PAUTH (aarch64_isa_flags & AARCH64_FL_PAUTH) #define AARCH64_ISA_V9 (aarch64_isa_flags & AARCH64_FL_V9) #define AARCH64_ISA_MOPS (aarch64_isa_flags & AARCH64_FL_MOPS) +#define AARCH64_ISA_LS64 (aarch64_isa_flags & AARCH64_FL_LS64) /* Crypto is an optional extension to AdvSIMD. */ #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO) @@ -413,6 +414,9 @@ extern unsigned aarch64_architecture_version; /* MOPS instructions are enabled through +mops. */ #define TARGET_MOPS (AARCH64_ISA_MOPS) +/* LS64 instructions are enabled through +ls64. */ +#define TARGET_LS64 (AARCH64_ISA_LS64) + /* Make sure this is always defined so we don't have to check for ifdefs but rather use normal ifs. */ #ifndef TARGET_FIX_ERR_A53_835769_DEFAULT diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 9e50a26..dcdffc8 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -188,6 +188,12 @@ UNSPEC_LD2_LANE UNSPEC_LD3_LANE UNSPEC_LD4_LANE + UNSPEC_LD64B + UNSPEC_ST64B + UNSPEC_ST64BV + UNSPEC_ST64BV_RET + UNSPEC_ST64BV0 + UNSPEC_ST64BV0_RET UNSPEC_MB UNSPEC_MOVMEM UNSPEC_NOP @@ -7571,6 +7577,52 @@ [(set_attr "type" "memtag")] ) +;; Load/Store 64-bit (LS64) instructions. +(define_insn "ld64b" + [(set (match_operand:V8DI 0 "register_operand" "=r") + (unspec_volatile:V8DI + [(mem:V8DI (match_operand:DI 1 "register_operand" "r"))] + UNSPEC_LD64B) + )] + "TARGET_LS64" + "ld64b\\t%0, [%1]" + [(set_attr "type" "ls64")] +) + +(define_insn "st64b" + [(set (mem:V8DI (match_operand:DI 0 "register_operand" "=r")) + (unspec_volatile:V8DI [(match_operand:V8DI 1 "register_operand" "r")] + UNSPEC_ST64B) + )] + "TARGET_LS64" + "st64b\\t%1, [%0]" + [(set_attr "type" "ls64")] +) + +(define_insn "st64bv" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV_RET)) + (set (mem:V8DI (match_operand:DI 1 "register_operand" "r")) + (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")] + UNSPEC_ST64BV) + )] + "TARGET_LS64" + "st64bv\\t%0, %2, [%1]" + [(set_attr "type" "ls64")] +) + +(define_insn "st64bv0" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV0_RET)) + (set (mem:V8DI (match_operand:DI 1 "register_operand" "r")) + (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")] + UNSPEC_ST64BV0) + )] + "TARGET_LS64" + "st64bv0\\t%0, %2, [%1]" + [(set_attr "type" "ls64")] +) + ;; AdvSIMD Stuff (include "aarch64-simd.md") diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h index 13f2363..030e343 100644 --- a/gcc/config/aarch64/arm_acle.h +++ b/gcc/config/aarch64/arm_acle.h @@ -214,6 +214,43 @@ __ttest (void) #pragma GCC pop_options #endif +#ifdef __ARM_FEATURE_LS64 +#pragma GCC push_options +#pragma GCC target ("+nothing+ls64") + +typedef __arm_data512_t data512_t; + +__extension__ extern __inline data512_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_ld64b (const void *__addr) +{ + return __builtin_aarch64_ld64b (__addr); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_st64b (void *__addr, data512_t __value) +{ + __builtin_aarch64_st64b (__addr, __value); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_st64bv (void *__addr, data512_t __value) +{ + return __builtin_aarch64_st64bv (__addr, __value); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_st64bv0 (void *__addr, data512_t __value) +{ + return __builtin_aarch64_st64bv0 (__addr, __value); +} + +#pragma GCC pop_options +#endif + #pragma GCC push_options #pragma GCC target ("+nothing+rng") __extension__ extern __inline int diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md index b9514da..6dce71f 100644 --- a/gcc/config/arm/types.md +++ b/gcc/config/arm/types.md @@ -1122,6 +1122,7 @@ coproc,\ tme,\ memtag,\ + ls64,\ mve_move,\ mve_store,\ mve_load" diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c new file mode 100644 index 0000000..ba9960c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +/* Inline assembly for LS64 instructions. */ + +#include + +void +ls64_load (data512_t *output, const void *addr) +{ + __asm__ volatile ("ld64b %0, [%1]" + : "=r" (*output) + : "r" (addr) + : "memory"); +} + +/* { dg-final { scan-assembler-times {ld64b } 1 } } */ + +void +ls64_store (const data512_t *input, void *addr) +{ + __asm__ volatile ("st64b %1, [%0]" + : /* No outputs. */ + : "r" (addr), "r" (*input) + : "memory"); +} + +/* { dg-final { scan-assembler-times {st64b } 1 } } */ + +uint64_t +ls64_store_v (const data512_t *input, void *addr) +{ + uint64_t status; + __asm__ volatile ("st64bv %0, %2, [%1]" + : "=r" (status) + : "r" (addr), "r" (*input) + : "memory"); + return status; +} + +/* { dg-final { scan-assembler-times {st64bv } 1 } } */ + +uint64_t +ls64_store_v0 (const data512_t *input, void *addr) +{ + uint64_t status; + __asm__ volatile ("st64bv0 %0, %2, [%1]" + : "=r" (status) + : "r" (addr), "r" (*input) + : "memory"); + return status; +} + +/* { dg-final { scan-assembler-times {st64bv0 } 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c new file mode 100644 index 0000000..2a94657 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func (const void * addr) { + data512_t ret = __arm_ld64b (addr); +} + +/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c new file mode 100644 index 0000000..155ea40 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(const void * addr, data512_t *data) { + *data = __arm_ld64b (addr); +} + +/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c new file mode 100644 index 0000000..e3fc141 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +data512_t +func(const void * addr) { + return __arm_ld64b (addr); +} + +/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c new file mode 100644 index 0000000..550d75c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O0" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +/* Make sure no issues when compile with -O0. */ + +data512_t +func1 (const void * addr) { + return __arm_ld64b (addr); +} + +void +func2 (void *addr, data512_t value) { + __arm_st64b (addr, value); +} + +uint64_t +func3 (void *addr, data512_t value) { + return __arm_st64bv (addr, value); +} + +uint64_t +func4 (void *addr, data512_t value) { + return __arm_st64bv0 (addr, value); +} diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c new file mode 100644 index 0000000..bfd737b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t *value) { + __arm_st64b (addr, *value); +} + +/* { dg-final { scan-assembler-times {st64b\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c new file mode 100644 index 0000000..75b9180 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t value) { + __arm_st64b (addr, value); +} + +/* { dg-final { scan-assembler-times {st64b\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c new file mode 100644 index 0000000..c3ef83e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t value) { + __arm_st64bv (addr, value); +} + +/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c new file mode 100644 index 0000000..370db79 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t *value) { + __arm_st64bv (addr, *value); +} + +/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c new file mode 100644 index 0000000..52ef9c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +uint64_t +func(void *addr, data512_t value) { + return __arm_st64bv (addr, value); +} + +/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c new file mode 100644 index 0000000..c49fa56 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t value) { + __arm_st64bv0 (addr, value); +} + +/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c new file mode 100644 index 0000000..af6917c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +void +func(void *addr, data512_t *value) { + __arm_st64bv0 (addr, *value); +} + +/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c new file mode 100644 index 0000000..bce10ae --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a+ls64 -O2" } */ + +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif + +#include + +uint64_t +func(void *addr, data512_t value) { + return __arm_st64bv0 (addr, value); +} + +/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c index 7244359..2d76bfc 100644 --- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c +++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c @@ -240,6 +240,20 @@ #endif #pragma GCC pop_options +#pragma GCC push_options +#pragma GCC target ("arch=armv8.7-a") +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.7-a+ls64") +#ifndef __ARM_FEATURE_LS64 +#error "__ARM_FEATURE_LS64 is not defined but should be!" +#endif +#pragma GCC pop_options + #pragma GCC pop_options int -- 2.7.4