public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][AArch64][GCC 8] Implement __rndr, __rndrrs intrinsics
@ 2020-09-25 10:32 Kyrylo Tkachov
  0 siblings, 0 replies; only message in thread
From: Kyrylo Tkachov @ 2020-09-25 10:32 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2263 bytes --]

Hi all,

We got a request to support the RNG intrinsics on GCC 8 as some cores used with this compiler will support the instructions
and the intrinsics are not very invasive to implement.
This does require adding the +rng arch extension to GCC 8, which is simple to do.
Otherwise the patch looks very much like the GCC 9 version

Bootstrapped and tested on aarch64-none-linux gnu on the branch. Pushed.
Thanks,
Kyrill

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.

[1] https://developer.arm.com/docs/101028/latest/data-processing-intrinsics

gcc/
	PR target/71233
	* 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.
	(AARCH64_FL_RNG): Likewise.
	* config/aarch64/aarch64-option-extensions.def (rng): Define.
	* config/aarch64/aarch64-builtins.c (enum aarch64_builtins):
	Add AARCH64_BUILTIN_RNG_RNDR, AARCH64_BUILTIN_RNG_RNDRRS.
	(aarch64_init_rng_builtins): Define.
	(aarch64_init_builtins): Call aarch64_init_rng_builtins.
	(aarch64_expand_rng_builtin): Define.
	(aarch64_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.

gcc/testsuite/
	PR target/71233
	* gcc.target/aarch64/acle/rng_1.c: New test.

[-- Attachment #2: rndr-8.patch --]
[-- Type: application/octet-stream, Size: 9792 bytes --]

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 9a542e829a46625507809515adc8690e7b370174..e6815900c90e23fcd035d81074db0f98f1962731 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -401,6 +401,9 @@ enum aarch64_builtins
   AARCH64_PAUTH_BUILTIN_XPACLRI,
   /* Builtin for Arm8.3-a Javascript conversion instruction.  */
   AARCH64_JSCVT,
+  /* Armv8.5-a RNG instruction builtins.  */
+  AARCH64_BUILTIN_RNG_RNDR,
+  AARCH64_BUILTIN_RNG_RNDRRS,
   AARCH64_BUILTIN_MAX
 };
 
@@ -975,6 +978,24 @@ aarch64_init_pauth_hint_builtins (void)
 			    NULL_TREE);
 }
 
+/* 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]
+    = add_builtin_function ("__builtin_aarch64_rndr", ftype,
+			    AARCH64_BUILTIN_RNG_RNDR, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
+    = add_builtin_function ("__builtin_aarch64_rndrrs", ftype,
+			    AARCH64_BUILTIN_RNG_RNDRRS, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+}
+
 void
 aarch64_init_builtins (void)
 {
@@ -1003,6 +1024,7 @@ aarch64_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);
@@ -1321,6 +1343,42 @@ aarch64_expand_builtin_rsqrt (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 a built-in function,
    with result going to TARGET if that's convenient.  */
 rtx
@@ -1409,6 +1467,9 @@ aarch64_expand_builtin (tree exp,
 	expand_insn (CODE_FOR_aarch64_fjcvtzs, 2, ops);
 	return ops[0].value;
       }
+    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 fcce3d672b60bbb4066cdc7acdcc8b59f28dfd80..4ad96f5e4af2152f61d221fc118a21d6d27e39ea 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -156,6 +156,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM4", pfile);
   aarch64_def_or_undef (TARGET_F16FML, "__ARM_FEATURE_FP16_FML", 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
      16-bit floating-point extensions.  */
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index a575448e4068f1141899c6a333d7e322fad2a368..bfd9245c595ccc05c728aa43262e333808828770 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -114,4 +114,7 @@ AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP | AARCH64_FL_F
    Disabling "sve" just disables "sve".  */
 AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, 0, false, "sve")
 
+/* Enabling/Disabling "rng" only changes "rng".  */
+AARCH64_OPT_EXTENSION("rng", AARCH64_FL_RNG, 0, 0, false, "")
+
 #undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 8c63733c6996948fe4d6c39cc27d6308776582ad..feda16e80a0645786bc0ec13964919c28e9c328b 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -157,6 +157,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_FL_SM4	      (1 << 17)  /* Has ARMv8.4-A SM3 and SM4.  */
 #define AARCH64_FL_SHA3	      (1 << 18)  /* Has ARMv8.4-a SHA3 and SHA512.  */
 #define AARCH64_FL_F16FML     (1 << 19)  /* Has ARMv8.4-a FP16 extensions.  */
+#define AARCH64_FL_RNG        (1 << 23)  /* ARMv8.5-A Random Number Insns.  */
 
 /* Has FP and SIMD.  */
 #define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -196,6 +197,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
 #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
 #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
+#define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -237,6 +239,9 @@ extern unsigned aarch64_architecture_version;
 /* Javascript conversion instruction from Armv8.3-a.  */
 #define TARGET_JSCVT	(TARGET_FLOAT && AARCH64_ISA_V8_3)
 
+/* 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.md b/gcc/config/aarch64/aarch64.md
index 2b492b53391a9c617f2056159d5237123498279b..9fc555c4006105b87084a07669315d31458400b2 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -201,6 +201,8 @@
     UNSPECV_SET_FPSR		; Represent assign of FPSR content.
     UNSPECV_BLOCKAGE		; Represent a blockage
     UNSPECV_PROBE_STACK_RANGE	; Represent stack range probing.
+    UNSPEC_RNDR			; Represent RNDR
+    UNSPEC_RNDRRS		; Represent RNDRRS
   ]
 )
 
@@ -6098,6 +6100,26 @@
 		   (match_operand 1))
 	      (clobber (reg:CC CC_REGNUM))])])
 
+(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 7bae393c33db4dad6b4728102b57ebab0e4a751a..8d16c8763ffd19e9a15bb52431934a2abfcf12fa 100644
--- a/gcc/config/aarch64/arm_acle.h
+++ b/gcc/config/aarch64/arm_acle.h
@@ -95,6 +95,24 @@ __crc32d (uint32_t __a, uint64_t __b)
   return __builtin_aarch64_crc32x (__a, __b);
 }
 
+#pragma GCC pop_options
+
+#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..90be6939ed9b5ec176fd166d3e60d58ad79628db
--- /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.3-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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-09-25 10:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25 10:32 [PATCH][AArch64][GCC 8] Implement __rndr, __rndrrs intrinsics Kyrylo Tkachov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).