AARCH64_BUILTIN_GCSPR,
AARCH64_BUILTIN_GCSPOPM,
AARCH64_BUILTIN_GCSSS,
+ /* Armv9.6-A builtins. */
+ AARCH64_BUILTIN_STSHH_QI,
+ AARCH64_BUILTIN_STSHH_HI,
+ AARCH64_BUILTIN_STSHH_SI,
+ AARCH64_BUILTIN_STSHH_DI,
+ AARCH64_BUILTIN_STSHH_SF,
+ AARCH64_BUILTIN_STSHH_DF,
AARCH64_BUILTIN_MAX
};
AARCH64_BUILTIN_GCSSS);
}
+/* Add builtins for FEAT_PCDPHINT. */
+
+static void
+aarch64_init_pcdphint_builtins (void)
+{
+ tree ftype;
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ unsigned_char_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_QI]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_qi", ftype,
+ AARCH64_BUILTIN_STSHH_QI);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ short_unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_HI]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_hi", ftype,
+ AARCH64_BUILTIN_STSHH_HI);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_SI]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_si", ftype,
+ AARCH64_BUILTIN_STSHH_SI);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ long_long_unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_DI]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_di", ftype,
+ AARCH64_BUILTIN_STSHH_DI);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ float_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_SF]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_sf", ftype,
+ AARCH64_BUILTIN_STSHH_SF);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node,
+ double_type_node,
+ unsigned_type_node,
+ unsigned_type_node, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_STSHH_DF]
+ = aarch64_general_add_builtin ("__builtin_aarch64_stshh_df", ftype,
+ AARCH64_BUILTIN_STSHH_DF);
+}
+
/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
void
AARCH64_BUILTIN_CHKFEAT);
aarch64_init_gcs_builtins ();
+ aarch64_init_pcdphint_builtins ();
if (in_lto_p)
handle_arm_acle_h ();
return result;
}
+void
+aarch64_expand_stshh_builtin (tree exp, int fcode)
+{
+ machine_mode mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
+ rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
+ rtx mem_order = expand_normal (CALL_EXPR_ARG (exp, 2));
+ rtx ret = expand_normal (CALL_EXPR_ARG (exp, 3));
+
+ require_const_argument (exp, 3, 0, 2);
+ require_const_argument (exp, 2, 0, 6);
+ if (seen_error ())
+ return;
+
+ switch (fcode)
+ {
+ case AARCH64_BUILTIN_STSHH_SF:
+ {
+ val = force_lowpart_subreg (SImode, val, SFmode);
+ mode = SImode;
+ break;
+ }
+ case AARCH64_BUILTIN_STSHH_DF:
+ {
+ val = force_lowpart_subreg (DImode, val, DFmode);
+ mode = DImode;
+ break;
+ }
+ default:
+ {
+ if (val != CONST0_RTX (mode))
+ val = force_reg (mode, val);
+ break;
+ }
+ }
+
+ rtx addr = expand_normal (CALL_EXPR_ARG (exp, 0));
+ addr = convert_memory_address (Pmode, addr);
+ rtx mem = gen_rtx_MEM (mode, addr);
+ set_mem_align (mem, GET_MODE_ALIGNMENT (mode));
+
+ expand_operand ops[4];
+ enum insn_code icode = code_for_aarch64_atomic_store_stshh (mode);
+ create_output_operand (&ops[0], mem, mode);
+ create_input_operand (&ops[1], val, mode);
+ create_input_operand (&ops[2], mem_order, SImode);
+ create_input_operand (&ops[3], ret, SImode);
+
+ expand_insn (icode, 4, ops);
+}
+
/* Expand CALL_EXPR EXP, given that it is a call to the function described
by BUILTIN_DATA, and return the function's return value. Put the result
in TARGET if convenient. */
case AARCH64_BUILTIN_GCSPOPM:
case AARCH64_BUILTIN_GCSSS:
return aarch64_expand_gcs_builtin (exp, target, fcode, ignore);
+
+ case AARCH64_BUILTIN_STSHH_QI:
+ case AARCH64_BUILTIN_STSHH_HI:
+ case AARCH64_BUILTIN_STSHH_SI:
+ case AARCH64_BUILTIN_STSHH_DI:
+ case AARCH64_BUILTIN_STSHH_SF:
+ case AARCH64_BUILTIN_STSHH_DF:
+ aarch64_expand_stshh_builtin (exp, fcode);
+ return target;
}
if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
return __builtin_aarch64_sqrtsf (__x);
}
+#define __atomic_store_with_stshh(addr, value, memory_order, ret) \
+({ \
+ __auto_type ptr = (addr); \
+ typedef __typeof__ (*ptr) ptr_type; \
+ _Generic ((*ptr), \
+ char: __builtin_aarch64_stshh_qi, \
+ unsigned char: __builtin_aarch64_stshh_qi, \
+ signed char: __builtin_aarch64_stshh_qi, \
+ unsigned short: __builtin_aarch64_stshh_hi, \
+ short: __builtin_aarch64_stshh_hi, \
+ unsigned int: __builtin_aarch64_stshh_si, \
+ int: __builtin_aarch64_stshh_si, \
+ unsigned long: __builtin_aarch64_stshh_di, \
+ long: __builtin_aarch64_stshh_di, \
+ unsigned long long: __builtin_aarch64_stshh_di, \
+ long long: __builtin_aarch64_stshh_di, \
+ float: __builtin_aarch64_stshh_sf, \
+ double: __builtin_aarch64_stshh_df, \
+ default: __builtin_aarch64_stshh_di \
+ )((ptr), (ptr_type)(value), (memory_order), (ret)); \
+})
+
#pragma GCC push_options
#pragma GCC target ("+nothing+jscvt")
__extension__ extern __inline int32_t
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8-a -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_acle.h>
+
+/*
+** testFun1:
+** ...
+** stshh keep
+** strb w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun1 ()
+{
+ char item1 = 0;
+ char* ptr1 = &item1;
+ char test1 = 1;
+
+ __atomic_store_with_stshh (ptr1, test1, __ATOMIC_RELAXED, 0);
+}
+
+/*
+** testFun2:
+** ...
+** stshh keep
+** stlrh w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun2 ()
+{
+ short item2 = 10;
+ short* ptr2 = &item2;
+ short test2 = 11;
+ __atomic_store_with_stshh (ptr2, test2, __ATOMIC_RELEASE, 0);
+}
+
+/*
+** testFun3:
+** ...
+** stshh strm
+** stlr w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun3 ()
+{
+ unsigned int item3 = 10;
+ unsigned int* ptr3 = &item3;
+ unsigned int test3 = 11;
+ __atomic_store_with_stshh (ptr3, test3, __ATOMIC_SEQ_CST, 1);
+}
+
+/*
+** testFun4:
+** ...
+** stshh strm
+** str x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun4 ()
+{
+ long item4 = 10;
+ long* ptr4 = &item4;
+ long test4 = 11;
+ __atomic_store_with_stshh (ptr4, test4, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** testFun5:
+** ...
+** stshh keep
+** stlr x[0-9]+, \[sp\]
+** ...
+*/
+void
+testFun5 ()
+{
+ long item5 = 10;
+ long* ptr5 = &item5;
+ long test5item = 11;
+ long* test5 = &test5item;
+ __atomic_store_with_stshh (ptr5, test5, __ATOMIC_SEQ_CST, 0);
+}
+
+/*
+** testFun6:
+** ...
+** stshh keep
+** stlr w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun6 ()
+{
+ float item6 = 10;
+ float* ptr6 = &item6;
+ float test6 = 11;
+ __atomic_store_with_stshh (ptr6, test6, __ATOMIC_SEQ_CST, 0);
+}
+
+/*
+** testFun7:
+** ...
+** stshh strm
+** str x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun7 ()
+{
+ double item7 = 10;
+ double* ptr7 = &item7;
+ double test7 = 11;
+ __atomic_store_with_stshh (ptr7, test7, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** testFun8:
+** ...
+** stshh keep
+** strb w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun8 ()
+{
+ char item8 = 0;
+ char* ptr8 = &item8;
+ long test8 = 1;
+
+ __atomic_store_with_stshh (ptr8, test8, __ATOMIC_RELAXED, 0);
+}
+
+/*
+** testFun9:
+** ...
+** stshh strm
+** str w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun9 ()
+{
+ int item9 = 0;
+ int* ptr9 = &item9;
+ float test9 = 1;
+
+ __atomic_store_with_stshh (ptr9, test9, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** testFun10:
+** ...
+** add (x[0-9]+), \1, 1
+** mov (w[0-9]+), 7
+** stshh strm
+** strb \2, \[\1\]
+** ...
+*/
+static char buf[8];
+void
+testFun10 (void)
+{
+ __atomic_store_with_stshh((buf + 1), (char)7, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** testFun11:
+** ...
+** stshh strm
+** str wzr, \[x[0-9]+\]
+** ...
+*/
+void
+testFun11 ()
+{
+ int item11 = 10;
+ int* ptr11 = &item11;
+
+ __atomic_store_with_stshh (ptr11, 0, __ATOMIC_RELAXED, 1);
+}