From patchwork Mon Oct 21 09:40:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kyrill Tkachov X-Patchwork-Id: 1180438 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-511404-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=foss.arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="MNtJLNzZ"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46xWps3CZ0z9sPL for ; Mon, 21 Oct 2019 20:40:53 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=rdaAr2r0iClbpNd1zysm4CByp/Yh9RLhCr6OGcPDP1mBP2vD6k Xs9sQsE56Tq07hc03i83czh9QUByYD5EiBV1Lp834PKP8gj80CTzmxLhgyaEGRX+ EiEHVf45GX/PyTIPV8B93opbukGWw6FKi9u4aZ9YSyD1HPslaD396Nn2E= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=xOJnTY5bmmVRMAB4nY8kY3Y7748=; b=MNtJLNzZLSVxrpqN0vP0 OvizTV9RGJpOm9cAU49iwrKWudmzOgWwTsuPhh+dRfzc+Xy+xfPR8J3v+Y8koj9l NAEKsdyPqx4LuX8QXm+TJUQ4/9AfIjALwVzs7BEfZWEaEWYoQjsAqNv7OKzjo5qb 5FGgcmYSlh4IZZqMuwYImYo= Received: (qmail 82321 invoked by alias); 21 Oct 2019 09:40:46 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 82310 invoked by uid 89); 21 Oct 2019 09:40:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LOTSOFHASH autolearn=ham version=3.3.1 spammy=fourth, rng X-HELO: foss.arm.com Received: from Unknown (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 21 Oct 2019 09:40:43 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id EE76846A for ; Mon, 21 Oct 2019 02:40:35 -0700 (PDT) Received: from [10.2.206.47] (e120808-lin.cambridge.arm.com [10.2.206.47]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9797C3F718 for ; Mon, 21 Oct 2019 02:40:35 -0700 (PDT) To: "gcc-patches@gcc.gnu.org" From: Kyrill Tkachov Subject: [PATCH][AArch64] Implement __rndr, __rndrrs intrinsics Message-ID: <4bf0ec75-340c-6580-988e-5756eb123d99@foss.arm.com> Date: Mon, 21 Oct 2019 10:40:34 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.1 MIME-Version: 1.0 Hi all, This patch implements the recently published[1] __rndr and __rndrrs intrinsics used to access the RNG in Armv8.5-A. The __rndrrs intrinsics can be used to reseed the generator too. They are guarded by the __ARM_FEATURE_RNG feature macro. A quirk with these intrinsics is that they store the random number in their pointer argument and return a status code if the generation succeeded. The instructions themselves write the CC flags indicating the success of the operation that we can then read with a CSET. Therefore this implementation makes use of the IGNORE indicator to the builtin expand machinery to avoid generating the CSET if its result is unused (the CC reg clobbering effect is still reflected in the pattern). I've checked that using unspec_volatile prevents undesirable CSEing of the instructions. Bootstrapped and tested on aarch64-none-linux-gnu. Committing to trunk. Thanks, Kyrill [1] https://developer.arm.com/docs/101028/latest/data-processing-intrinsics 2019-10-21  Kyrylo Tkachov      * 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  Kyrylo Tkachov      * gcc.target/aarch64/acle/rng_1.c: New test. diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index e02ece8672a633833a63993e24a156dd5ff64e69..23a0db4f74f56c48b0d0c34d5ac61e5d8334bc43 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -445,6 +445,9 @@ enum aarch64_builtins 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 }; @@ -1111,7 +1114,25 @@ aarch64_init_tme_builtins (void) 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) { @@ -1144,6 +1165,7 @@ 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); @@ -1607,10 +1629,48 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target) 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; @@ -1717,6 +1777,9 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target) 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) diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c index 137aa18af4620d4cefce1dfe5d92e4df67a278ba..85b68317b938a37090ec401618b7f540fc243fde 100644 --- a/gcc/config/aarch64/aarch64-c.c +++ b/gcc/config/aarch64/aarch64-c.c @@ -160,6 +160,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) 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 diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index ab27a1263f54981586f2b9d036f143030820208b..ca235085bfbc7560cdfb8a6f767f0bd634067d24 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -659,7 +659,7 @@ const char *aarch64_general_mangle_builtin_type (const_tree); 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); diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index abd14a2f92c06828adfc6d2e2e81b63a6163d3a3..b68594d10def8e6ec749aefcfc3c9fd5b907ecc8 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -245,6 +245,7 @@ extern unsigned aarch64_architecture_version; #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) @@ -300,6 +301,9 @@ extern unsigned aarch64_architecture_version; /* 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 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index d2c62621adb5f779d666e993962ecb5e0aaaa045..109dd1f40a8794f3e228d7cd15a8348ec624bd63 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -11694,7 +11694,7 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi) /* 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); @@ -11702,7 +11702,7 @@ aarch64_expand_builtin (tree exp, rtx target, rtx, machine_mode, int) 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 (); } diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index af170999f5f215a48b65efed4de7486f0f68b199..5b8484d408b0d1139ecc629cc1bd684ee034713d 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -264,6 +264,8 @@ UNSPECV_TSTART ; Represent transaction start. UNSPECV_TCOMMIT ; Represent transaction commit. UNSPECV_TCANCEL ; Represent transaction cancel. + UNSPEC_RNDR ; Represent RNDR + UNSPEC_RNDRRS ; Represent RNDRRS ] ) @@ -7374,6 +7376,26 @@ [(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") diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h index 147dfe0585cbae6b2d53ca3ead3edddf49d779a5..2284e71648a4992c9959c7eed064d64a086d339b 100644 --- a/gcc/config/aarch64/arm_acle.h +++ b/gcc/config/aarch64/arm_acle.h @@ -193,6 +193,22 @@ __ttest (void) #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 diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rng_1.c b/gcc/testsuite/gcc.target/aarch64/acle/rng_1.c new file mode 100644 index 0000000000000000000000000000000000000000..1fbdb6276632221d5daa7805a19c86f20cae880e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/rng_1.c @@ -0,0 +1,53 @@ +/* Test the __rndr ACLE intrinsic. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv8.5-a+rng" } */ + +#include + +#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