+2019-10-21 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.md (UNSPEC_RNDR, UNSPEC_RNDRRS): Define.
+ (aarch64_rndr): New define_insn.
+ (aarch64_rndrrs): Likewise.
+ * config/aarch64/aarch64.h (AARCH64_ISA_RNG): Define.
+ (TARGET_RNG): Likewise.
+ * config/aarch64/aarch64.c (aarch64_expand_builtin): Use IGNORE
+ argument.
+ * config/aarch64/aarch64-protos.h (aarch64_general_expand_builtin):
+ Add fourth argument in prototype.
+ * config/aarch64/aarch64-builtins.c (enum aarch64_builtins):
+ Add AARCH64_BUILTIN_RNG_RNDR, AARCH64_BUILTIN_RNG_RNDRRS.
+ (aarch64_init_rng_builtins): Define.
+ (aarch64_general_init_builtins): Call aarch64_init_rng_builtins.
+ (aarch64_expand_rng_builtin): Define.
+ (aarch64_general_expand_builtin): Use IGNORE argument, handle
+ RNG builtins.
+ * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define
+ __ARM_FEATURE_RNG when TARGET_RNG.
+ * config/aarch64/arm_acle.h (__rndr, __rndrrs): Define.
+
2019-10-21 Andre Vieira <andre.simoesdiasvieira@arm.com>
* tree-vect-stmts (ensure_base_align): Only change alignment if new
AARCH64_TME_BUILTIN_TCOMMIT,
AARCH64_TME_BUILTIN_TTEST,
AARCH64_TME_BUILTIN_TCANCEL,
+ /* Armv8.5-a RNG instruction builtins. */
+ AARCH64_BUILTIN_RNG_RNDR,
+ AARCH64_BUILTIN_RNG_RNDRRS,
AARCH64_BUILTIN_MAX
};
AARCH64_TME_BUILTIN_TCANCEL);
}
+/* Add builtins for Random Number instructions. */
+
+static void
+aarch64_init_rng_builtins (void)
+{
+ tree unsigned_ptr_type = build_pointer_type (unsigned_intDI_type_node);
+ tree ftype
+ = build_function_type_list (integer_type_node, unsigned_ptr_type, NULL);
+ aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDR]
+ = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype,
+ AARCH64_BUILTIN_RNG_RNDR);
+ aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
+ = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype,
+ AARCH64_BUILTIN_RNG_RNDRRS);
+}
+
+
/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
+
void
aarch64_general_init_builtins (void)
{
aarch64_init_crc32_builtins ();
aarch64_init_builtin_rsqrt ();
+ aarch64_init_rng_builtins ();
tree ftype_jcvt
= build_function_type_list (intSI_type_node, double_type_node, NULL);
return target;
}
+/* Expand a random number builtin EXP with code FCODE, putting the result
+ int TARGET. If IGNORE is true the return value is ignored. */
+
+rtx
+aarch64_expand_rng_builtin (tree exp, rtx target, int fcode, int ignore)
+{
+ rtx pat;
+ enum insn_code icode;
+ if (fcode == AARCH64_BUILTIN_RNG_RNDR)
+ icode = CODE_FOR_aarch64_rndr;
+ else if (fcode == AARCH64_BUILTIN_RNG_RNDRRS)
+ icode = CODE_FOR_aarch64_rndrrs;
+ else
+ gcc_unreachable ();
+
+ rtx rand = gen_reg_rtx (DImode);
+ pat = GEN_FCN (icode) (rand);
+ if (!pat)
+ return NULL_RTX;
+
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ rtx res_addr = expand_normal (arg0);
+ res_addr = convert_memory_address (Pmode, res_addr);
+ rtx res_mem = gen_rtx_MEM (DImode, res_addr);
+ emit_insn (pat);
+ emit_move_insn (res_mem, rand);
+ /* If the status result is unused don't generate the CSET code. */
+ if (ignore)
+ return target;
+
+ rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
+ rtx cmp_rtx = gen_rtx_fmt_ee (NE, SImode, cc_reg, const0_rtx);
+ emit_insn (gen_aarch64_cstoresi (target, cmp_rtx, cc_reg));
+ return target;
+}
+
/* Expand an expression EXP that calls built-in function FCODE,
- with result going to TARGET if that's convenient. */
+ with result going to TARGET if that's convenient. IGNORE is true
+ if the result of the builtin is ignored. */
rtx
-aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target)
+aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
+ int ignore)
{
int icode;
rtx pat, op0;
case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF:
case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF:
return aarch64_expand_fcmla_builtin (exp, target, fcode);
+ case AARCH64_BUILTIN_RNG_RNDR:
+ case AARCH64_BUILTIN_RNG_RNDRRS:
+ return aarch64_expand_rng_builtin (exp, target, fcode, ignore);
}
if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
aarch64_def_or_undef (TARGET_FRINT, "__ARM_FEATURE_FRINT", pfile);
aarch64_def_or_undef (TARGET_TME, "__ARM_FEATURE_TME", pfile);
+ aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", 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
void aarch64_general_init_builtins (void);
tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *);
gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *);
-rtx aarch64_general_expand_builtin (unsigned int, tree, rtx);
+rtx aarch64_general_expand_builtin (unsigned int, tree, rtx, int);
tree aarch64_general_builtin_decl (unsigned, bool);
tree aarch64_general_builtin_rsqrt (unsigned int);
tree aarch64_builtin_vectorized_function (unsigned int, tree, tree);
/* Implement TARGET_EXPAND_BUILTIN. */
static rtx
-aarch64_expand_builtin (tree exp, rtx target, rtx, machine_mode, int)
+aarch64_expand_builtin (tree exp, rtx target, rtx, machine_mode, int ignore)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
switch (code & AARCH64_BUILTIN_CLASS)
{
case AARCH64_BUILTIN_GENERAL:
- return aarch64_general_expand_builtin (subcode, exp, target);
+ return aarch64_general_expand_builtin (subcode, exp, target, ignore);
}
gcc_unreachable ();
}
#define AARCH64_ISA_SHA3 (aarch64_isa_flags & AARCH64_FL_SHA3)
#define AARCH64_ISA_F16FML (aarch64_isa_flags & AARCH64_FL_F16FML)
#define AARCH64_ISA_RCPC8_4 (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
+#define AARCH64_ISA_RNG (aarch64_isa_flags & AARCH64_FL_RNG)
#define AARCH64_ISA_V8_5 (aarch64_isa_flags & AARCH64_FL_V8_5)
#define AARCH64_ISA_TME (aarch64_isa_flags & AARCH64_FL_TME)
/* TME instructions are enabled. */
#define TARGET_TME (AARCH64_ISA_TME)
+/* Random number instructions from Armv8.5-a. */
+#define TARGET_RNG (AARCH64_ISA_RNG)
+
/* 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
UNSPECV_TSTART ; Represent transaction start.
UNSPECV_TCOMMIT ; Represent transaction commit.
UNSPECV_TCANCEL ; Represent transaction cancel.
+ UNSPEC_RNDR ; Represent RNDR
+ UNSPEC_RNDRRS ; Represent RNDRRS
]
)
[(set_attr "type" "tme")]
)
+(define_insn "aarch64_rndr"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDR))
+ (set (reg:CC_Z CC_REGNUM)
+ (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDR))]
+ "TARGET_RNG"
+ "mrs\t%0, RNDR"
+ [(set_attr "type" "mrs")]
+)
+
+(define_insn "aarch64_rndrrs"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDRRS))
+ (set (reg:CC_Z CC_REGNUM)
+ (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDRRS))]
+ "TARGET_RNG"
+ "mrs\t%0, RNDRRS"
+ [(set_attr "type" "mrs")]
+)
+
;; AdvSIMD Stuff
(include "aarch64-simd.md")
#pragma GCC pop_options
#endif
+#pragma GCC push_options
+#pragma GCC target ("+nothing+rng")
+__extension__ static __inline int __attribute__ ((__always_inline__))
+__rndr (uint64_t *__res)
+{
+ return __builtin_aarch64_rndr (__res);
+}
+
+__extension__ static __inline int __attribute__ ((__always_inline__))
+__rndrrs (uint64_t *__res)
+{
+ return __builtin_aarch64_rndrrs (__res);
+}
+
+#pragma GCC pop_options
+
#ifdef __cplusplus
}
#endif
+2019-10-21 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/acle/rng_1.c: New test.
+
2019-10-21 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
PR tree-optimization/91532
--- /dev/null
+/* Test the __rndr ACLE intrinsic. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8.5-a+rng" } */
+
+#include <arm_acle.h>
+
+#ifdef __ARM_FEATURE_RNG
+/* Check that instruction is generated when status result is unused. */
+uint64_t
+test_rndr_no_stat (void)
+{
+ uint64_t res;
+ __rndr (&res);
+ return res;
+}
+
+/* Check that instruction is generated when random number result
+ is unused. */
+int
+test_rndr_error_check (void)
+{
+ uint64_t res;
+ int fail = __rndr (&res);
+ if (fail)
+ return 0;
+ return -1;
+}
+
+/* { dg-final { scan-assembler-times "mrs\tx..?, RNDR\n" 2 } } */
+
+/* Check that instruction is generated when status result is unused. */
+uint64_t
+test_rndrrs_no_stat (void)
+{
+ uint64_t res;
+ __rndrrs (&res);
+ return res;
+}
+
+/* Check that instruction is generated when random number result
+ is unused. */
+int
+test_rndrrs_error_check (void)
+{
+ uint64_t res;
+ int fail = __rndrrs (&res);
+ if (fail)
+ return 0;
+ return -1;
+}
+
+/* { dg-final { scan-assembler-times "mrs\tx..?, RNDRRS\n" 2 } } */
+#endif