This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][ARM] Implement CRC32 intrinsics for AArch32 in ARMv8-A


On 19/11/13 16:26, Joseph S. Myers wrote:
In any target header installed for user use, such as arm_acle.h, you need
to be namespace-clean.  In this case, that means you need to use
implementation-namespace identifiers such as __a, __b and __d in case the
user has defined macros with names such as a, b and d (unless the ACLE
says that identifiers a, b and d are in the implementation's namespace
when this header is included, which would be a very odd thing for it to
do).


Hi Joseph,

Thanks for the catch. ACLE doesn't expect a,b,d to be in the implementation namespace. I've added underscores before them.

Made sure tests pass.

Revised patch attached.
How's this?

Kyrill

gcc/
2013-11-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    * Makefile.in (TEXI_GCC_FILES): Add arm-acle-intrinsics.texi.
    * config.gcc (extra_headers): Add arm_acle.h.
    * config/arm/arm.c (FL_CRC32): Define.
    (arm_have_crc): Likewise.
    (arm_option_override): Set arm_have_crc.
    (arm_builtins): Add CRC32 builtins.
    (bdesc_2arg): Likewise.
    (arm_init_crc32_builtins): New function.
    (arm_init_builtins): Initialise CRC32 builtins.
    (arm_file_start): Handle architecture extensions.
    * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define __ARM_FEATURE_CRC32.
    Define __ARM_32BIT_STATE.
    (TARGET_CRC32): Define.
    * config/arm/arm-arches.def: Add armv8-a+crc.
    * config/arm/arm-tables.opt: Regenerate.
    * config/arm/arm.md (type): Add crc.
    (<crc_variant>): New insn.
    * config/arm/arm_acle.h: New file.
    * config/arm/iterators.md (CRC): New int iterator.
    (crc_variant, crc_mode): New int attributes.
    * confg/arm/unspecs.md (UNSPEC_CRC32B, UNSPEC_CRC32H, UNSPEC_CRC32W,
    UNSPEC_CRC32CB, UNSPEC_CRC32CH, UNSPEC_CRC32CW): New unspecs.
    * doc/invoke.texi: Document -march=armv8-a+crc option.
    * doc/extend.texi: Document ACLE intrinsics.
    * doc/arm-acle-intrinsics.texi: New.


gcc/testsuite
2013-11-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    * lib/target-supports.exp (add_options_for_arm_crc): New procedure.
    (check_effective_target_arm_crc_ok_nocache): Likewise.
    (check_effective_target_arm_crc_ok): Likewise.
    * gcc.target/arm/acle/: New directory.
    * gcc.target/arm/acle/acle.exp: New.
    * gcc.target/arm/acle/crc32b.c: New test.
    * gcc.target/arm/acle/crc32h.c: Likewise.
    * gcc.target/arm/acle/crc32w.c: Likewise.
    * gcc.target/arm/acle/crc32d.c: Likewise.
    * gcc.target/arm/acle/crc32cb.c: Likewise.
    * gcc.target/arm/acle/crc32ch.c: Likewise.
    * gcc.target/arm/acle/crc32cw.c: Likewise.
    * gcc.target/arm/acle/crc32cd.c: Likewise.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 8cc8341..455c80b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2793,7 +2793,8 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi	\
 	 gcov.texi trouble.texi bugreport.texi service.texi		\
 	 contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi	\
 	 fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi	\
-	 implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi
+	 implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi	\
+	 arm-acle-intrinsics.texi
 
 # we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with
 # the generated tm.texi; the latter might have a more recent timestamp,
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2907018..ebbdc59 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -329,8 +329,8 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_headers="mmintrin.h arm_neon.h"
 	extra_objs="aarch-common.o"
+	extra_headers="mmintrin.h arm_neon.h arm_acle.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
 	cxx_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-arches.def b/gcc/config/arm/arm-arches.def
index fcf3401..9b7d20c 100644
--- a/gcc/config/arm/arm-arches.def
+++ b/gcc/config/arm/arm-arches.def
@@ -54,5 +54,6 @@ ARM_ARCH("armv7-r", cortexr4,	7R,  FL_CO_PROC |	      FL_FOR_ARCH7R)
 ARM_ARCH("armv7-m", cortexm3,	7M,  FL_CO_PROC |	      FL_FOR_ARCH7M)
 ARM_ARCH("armv7e-m", cortexm4,  7EM, FL_CO_PROC |	      FL_FOR_ARCH7EM)
 ARM_ARCH("armv8-a", cortexa53,  8A,  FL_CO_PROC |             FL_FOR_ARCH8A)
+ARM_ARCH("armv8-a+crc",cortexa53, 8A,FL_CO_PROC | FL_CRC32  | FL_FOR_ARCH8A)
 ARM_ARCH("iwmmxt",  iwmmxt,     5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT)
 ARM_ARCH("iwmmxt2", iwmmxt2,    5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2)
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index b3e7a7c..8851876 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -362,10 +362,13 @@ EnumValue
 Enum(arm_arch) String(armv8-a) Value(23)
 
 EnumValue
-Enum(arm_arch) String(iwmmxt) Value(24)
+Enum(arm_arch) String(armv8-a+crc) Value(24)
 
 EnumValue
-Enum(arm_arch) String(iwmmxt2) Value(25)
+Enum(arm_arch) String(iwmmxt) Value(25)
+
+EnumValue
+Enum(arm_arch) String(iwmmxt2) Value(26)
 
 Enum
 Name(arm_fpu) Type(int)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 590c577..490b76f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -736,6 +736,7 @@ static int thumb_call_reg_needed;
 #define FL_ARCH7      (1 << 22)       /* Architecture 7.  */
 #define FL_ARM_DIV    (1 << 23)	      /* Hardware divide (ARM mode).  */
 #define FL_ARCH8      (1 << 24)       /* Architecture 8.  */
+#define FL_CRC32      (1 << 25)	      /* ARMv8 CRC32 instructions.  */
 
 #define FL_IWMMXT     (1 << 29)	      /* XScale v2 or "Intel Wireless MMX technology".  */
 #define FL_IWMMXT2    (1 << 30)       /* "Intel Wireless MMX2 technology".  */
@@ -898,6 +899,9 @@ int arm_condexec_mask = 0;
 /* The number of bits used in arm_condexec_mask.  */
 int arm_condexec_masklen = 0;
 
+/* Nonzero if chip supports the ARMv8 CRC instructions.  */
+int arm_arch_crc = 0;
+
 /* The condition codes of the ARM, and the inverse function.  */
 static const char * const arm_condition_codes[] =
 {
@@ -2374,6 +2378,7 @@ arm_option_override (void)
   arm_arch_thumb_hwdiv = (insn_flags & FL_THUMB_DIV) != 0;
   arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0;
   arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0;
+  arm_arch_crc = (insn_flags & FL_CRC32) != 0;
   if (arm_restrict_it == 2)
     arm_restrict_it = arm_arch8 && TARGET_THUMB2;
 
@@ -22924,6 +22929,13 @@ enum arm_builtins
 
   ARM_BUILTIN_WMERGE,
 
+  ARM_BUILTIN_CRC32B,
+  ARM_BUILTIN_CRC32H,
+  ARM_BUILTIN_CRC32W,
+  ARM_BUILTIN_CRC32CB,
+  ARM_BUILTIN_CRC32CH,
+  ARM_BUILTIN_CRC32CW,
+
 #include "arm_neon_builtins.def"
 
   ,ARM_BUILTIN_MAX
@@ -23503,7 +23515,7 @@ struct builtin_description
   const enum rtx_code      comparison;
   const unsigned int       flag;
 };
-  
+
 static const struct builtin_description bdesc_2arg[] =
 {
 #define IWMMXT_BUILTIN(code, string, builtin) \
@@ -23609,6 +23621,17 @@ static const struct builtin_description bdesc_2arg[] =
   IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS)
   IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
   IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
+
+#define CRC32_BUILTIN(L, U) \
+  {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
+   UNKNOWN, 0},
+   CRC32_BUILTIN (crc32b, CRC32B)
+   CRC32_BUILTIN (crc32h, CRC32H)
+   CRC32_BUILTIN (crc32w, CRC32W)
+   CRC32_BUILTIN (crc32cb, CRC32CB)
+   CRC32_BUILTIN (crc32ch, CRC32CH)
+   CRC32_BUILTIN (crc32cw, CRC32CW)
+#undef CRC32_BUILTIN
 };
 
 static const struct builtin_description bdesc_1arg[] =
@@ -24028,6 +24051,42 @@ arm_init_fp16_builtins (void)
 }
 
 static void
+arm_init_crc32_builtins ()
+{
+  tree si_ftype_si_qi
+    = build_function_type_list (unsigned_intSI_type_node,
+                                unsigned_intSI_type_node,
+                                unsigned_intQI_type_node, NULL_TREE);
+  tree si_ftype_si_hi
+    = build_function_type_list (unsigned_intSI_type_node,
+                                unsigned_intSI_type_node,
+                                unsigned_intHI_type_node, NULL_TREE);
+  tree si_ftype_si_si
+    = build_function_type_list (unsigned_intSI_type_node,
+                                unsigned_intSI_type_node,
+                                unsigned_intSI_type_node, NULL_TREE);
+
+  arm_builtin_decls[ARM_BUILTIN_CRC32B]
+    = add_builtin_function ("__builtin_arm_crc32b", si_ftype_si_qi,
+                            ARM_BUILTIN_CRC32B, BUILT_IN_MD, NULL, NULL_TREE);
+  arm_builtin_decls[ARM_BUILTIN_CRC32H]
+    = add_builtin_function ("__builtin_arm_crc32h", si_ftype_si_hi,
+                            ARM_BUILTIN_CRC32H, BUILT_IN_MD, NULL, NULL_TREE);
+  arm_builtin_decls[ARM_BUILTIN_CRC32W]
+    = add_builtin_function ("__builtin_arm_crc32w", si_ftype_si_si,
+                            ARM_BUILTIN_CRC32W, BUILT_IN_MD, NULL, NULL_TREE);
+  arm_builtin_decls[ARM_BUILTIN_CRC32CB]
+    = add_builtin_function ("__builtin_arm_crc32cb", si_ftype_si_qi,
+                            ARM_BUILTIN_CRC32CB, BUILT_IN_MD, NULL, NULL_TREE);
+  arm_builtin_decls[ARM_BUILTIN_CRC32CH]
+    = add_builtin_function ("__builtin_arm_crc32ch", si_ftype_si_hi,
+                            ARM_BUILTIN_CRC32CH, BUILT_IN_MD, NULL, NULL_TREE);
+  arm_builtin_decls[ARM_BUILTIN_CRC32CW]
+    = add_builtin_function ("__builtin_arm_crc32cw", si_ftype_si_si,
+                            ARM_BUILTIN_CRC32CW, BUILT_IN_MD, NULL, NULL_TREE);
+}
+
+static void
 arm_init_builtins (void)
 {
   if (TARGET_REALLY_IWMMXT)
@@ -24038,6 +24097,9 @@ arm_init_builtins (void)
 
   if (arm_fp16_format)
     arm_init_fp16_builtins ();
+
+  if (TARGET_CRC32)
+    arm_init_crc32_builtins ();
 }
 
 /* Return the ARM builtin for CODE.  */
@@ -27311,7 +27373,22 @@ arm_file_start (void)
     {
       const char *fpu_name;
       if (arm_selected_arch)
-	asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_arch->name);
+        {
+          const char* pos = strchr (arm_selected_arch->name, '+');
+	  if (pos)
+	    {
+	      char buf[15];
+	      gcc_assert (strlen (arm_selected_arch->name)
+	                  <= sizeof (buf) / sizeof (*pos));
+	      strncpy (buf, arm_selected_arch->name,
+	                    (pos - arm_selected_arch->name) * sizeof (*pos));
+	      buf[pos - arm_selected_arch->name] = '\0';
+	      asm_fprintf (asm_out_file, "\t.arch %s\n", buf);
+	      asm_fprintf (asm_out_file, "\t.arch_extension %s\n", pos + 1);
+	    }
+	  else
+	    asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_arch->name);
+        }
       else if (strncmp (arm_selected_cpu->name, "generic", 7) == 0)
 	asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_cpu->name + 8);
       else
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index dbd841e..0043c9b 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -51,6 +51,10 @@ extern char arm_arch_name[];
            builtin_define ("__ARM_FEATURE_SAT");	\
 	if (unaligned_access)				\
 	  builtin_define ("__ARM_FEATURE_UNALIGNED");	\
+	if (TARGET_CRC32)				\
+	  builtin_define ("__ARM_FEATURE_CRC32");	\
+	if (TARGET_32BIT)				\
+	  builtin_define ("__ARM_32BIT_STATE");		\
 	if (TARGET_ARM_FEATURE_LDREX)				\
 	  builtin_define_with_int_value (			\
 	    "__ARM_FEATURE_LDREX", TARGET_ARM_FEATURE_LDREX);	\
@@ -274,6 +278,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_LDRD			(arm_arch5e && ARM_DOUBLEWORD_ALIGN \
                                          && !TARGET_THUMB1)
 
+#define TARGET_CRC32			(arm_arch_crc)
+
 /* The following two macros concern the ability to execute coprocessor
    instructions for VFPv3 or NEON.  TARGET_VFP3/TARGET_VFPD32 are currently
    only ever tested when we know we are generating for VFP hardware; we need
@@ -554,6 +560,9 @@ extern int arm_arch_thumb_hwdiv;
    than core registers.  */
 extern int prefer_neon_for_64bits;
 
+/* Nonzero if chip supports the ARMv8 CRC instructions.  */
+extern int arm_arch_crc;
+
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT  (MASK_APCS_FRAME)
 #endif
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 3726201..75444d2 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12756,6 +12756,16 @@
    (set_attr "predicable" "yes")
    (set_attr "predicable_short_it" "no")])
 
+;; ARMv8 CRC32 instructions.
+(define_insn "<crc_variant>"
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+        (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
+                    (match_operand:<crc_mode> 2 "s_register_operand" "r")]
+         CRC))]
+  "TARGET_CRC32"
+  "<crc_variant>\\t%0, %1, %2"
+  [(set_attr "type" "crc")]
+)
 
 ;; Load the load/store double peephole optimizations.
 (include "ldrdstrd.md")
diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h
new file mode 100644
index 0000000..ac3a15c
--- /dev/null
+++ b/gcc/config/arm/arm_acle.h
@@ -0,0 +1,100 @@
+/* ARM Non-NEON ACLE intrinsics include file.
+
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GCC_ARM_ACLE_H
+#define _GCC_ARM_ACLE_H
+
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __ARM_FEATURE_CRC32
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32b (uint32_t __a, uint8_t __b)
+{
+  return __builtin_arm_crc32b (__a, __b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32h (uint32_t __a, uint16_t __b)
+{
+  return __builtin_arm_crc32h (__a, __b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32w (uint32_t __a, uint32_t __b)
+{
+  return __builtin_arm_crc32w (__a, __b);
+}
+
+#ifdef __ARM_32BIT_STATE
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32d (uint32_t __a, uint64_t __b)
+{
+  uint32_t __d;
+
+  __d = __crc32w (__crc32w (__a, __b & 0xffffffffULL), __b >> 32);
+  return __d;
+}
+#endif
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cb (uint32_t __a, uint8_t __b)
+{
+  return __builtin_arm_crc32cb (__a, __b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32ch (uint32_t __a, uint16_t __b)
+{
+  return __builtin_arm_crc32ch (__a, __b);
+}
+
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cw (uint32_t __a, uint32_t __b)
+{
+  return __builtin_arm_crc32cw (__a, __b);
+}
+
+#ifdef __ARM_32BIT_STATE
+__extension__ static __inline uint32_t __attribute__ ((__always_inline__))
+__crc32cd (uint32_t __a, uint64_t __b)
+{
+  uint32_t __d;
+
+  __d = __crc32cw (__crc32cw (__a, __b & 0xffffffffULL), __b >> 32);
+  return __d;
+}
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 38777b8..fcffc87 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -201,6 +201,9 @@
 (define_int_iterator NEON_VRINT [UNSPEC_NVRINTP UNSPEC_NVRINTZ UNSPEC_NVRINTM
                               UNSPEC_NVRINTX UNSPEC_NVRINTA UNSPEC_NVRINTN])
 
+(define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H UNSPEC_CRC32W
+                          UNSPEC_CRC32CB UNSPEC_CRC32CH UNSPEC_CRC32CW])
+
 ;;----------------------------------------------------------------------------
 ;; Mode attributes
 ;;----------------------------------------------------------------------------
@@ -514,6 +517,15 @@
 (define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p")
                                 (UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m")
                                 (UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")])
+
+(define_int_attr crc_variant [(UNSPEC_CRC32B "crc32b") (UNSPEC_CRC32H "crc32h")
+                        (UNSPEC_CRC32W "crc32w") (UNSPEC_CRC32CB "crc32cb")
+                        (UNSPEC_CRC32CH "crc32ch") (UNSPEC_CRC32CW "crc32cw")])
+
+(define_int_attr crc_mode [(UNSPEC_CRC32B "QI") (UNSPEC_CRC32H "HI")
+                        (UNSPEC_CRC32W "SI") (UNSPEC_CRC32CB "QI")
+                        (UNSPEC_CRC32CH "HI") (UNSPEC_CRC32CW "SI")])
+
 ;; Both kinds of return insn.
 (define_code_iterator returns [return simple_return])
 (define_code_attr return_str [(return "") (simple_return "simple_")])
diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
index 1c4b9e3..b505be3 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -543,6 +543,7 @@
   clz,\
   no_insn,\
   csel,\
+  crc,\
   extend,\
   f_cvt,\
   f_cvtf2i,\
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 508603c..f8faba3 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -149,6 +149,12 @@
 (define_c_enum "unspec" [
   UNSPEC_ASHIFT_SIGNED
   UNSPEC_ASHIFT_UNSIGNED
+  UNSPEC_CRC32B
+  UNSPEC_CRC32H
+  UNSPEC_CRC32W
+  UNSPEC_CRC32CB
+  UNSPEC_CRC32CH
+  UNSPEC_CRC32CW
   UNSPEC_LOAD_COUNT
   UNSPEC_VABD
   UNSPEC_VABDL
diff --git a/gcc/doc/arm-acle-intrinsics.texi b/gcc/doc/arm-acle-intrinsics.texi
new file mode 100644
index 0000000..bb6290b
--- /dev/null
+++ b/gcc/doc/arm-acle-intrinsics.texi
@@ -0,0 +1,55 @@
+@c Copyright (C) 2013 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+
+@subsubsection CRC32 intrinsics
+
+@itemize @bullet
+@item uint32_t __crc32b (uint32_t, uint8_t)
+@*@emph{Form of expected instruction(s):} @code{crc32b @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32h (uint32_t, uint16_t)
+@*@emph{Form of expected instruction(s):} @code{crc32h @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32w (uint32_t, uint32_t)
+@*@emph{Form of expected instruction(s):} @code{crc32w @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32d (uint32_t, uint64_t)
+@*@emph{Form of expected instruction(s):} Two @code{crc32w @var{r0}, @var{r0}, @var{r0}}
+instructions for AArch32. One @code{crc32w @var{w0}, @var{w0}, @var{x0}} instruction for
+AArch64.
+@end itemize
+
+@itemize @bullet
+@item uint32_t __crc32cb (uint32_t, uint8_t)
+@*@emph{Form of expected instruction(s):} @code{crc32cb @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32ch (uint32_t, uint16_t)
+@*@emph{Form of expected instruction(s):} @code{crc32ch @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32cw (uint32_t, uint32_t)
+@*@emph{Form of expected instruction(s):} @code{crc32cw @var{r0}, @var{r0}, @var{r0}}
+@end itemize
+
+
+@itemize @bullet
+@item uint32_t __crc32cd (uint32_t, uint64_t)
+@*@emph{Form of expected instruction(s):} Two @code{crc32cw @var{r0}, @var{r0}, @var{r0}}
+instructions for AArch32. One @code{crc32cw @var{w0}, @var{w0}, @var{x0}} instruction for
+AArch64.
+@end itemize
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 88eba80..2880953 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -9204,6 +9204,7 @@ instructions, but allow the compiler to schedule those calls.
 * ARC SIMD Built-in Functions::
 * ARM iWMMXt Built-in Functions::
 * ARM NEON Intrinsics::
+* ARM ACLE Intrinsics::
 * AVR Built-in Functions::
 * Blackfin Built-in Functions::
 * FR-V Built-in Functions::
@@ -9895,6 +9896,14 @@ when the @option{-mfpu=neon} switch is used:
 
 @include arm-neon-intrinsics.texi
 
+@node ARM ACLE Intrinsics
+@subsection ARM ACLE Intrinsics
+
+These built-in intrinsics for the ARMv8-A CRC32 extension are available when
+the @option{-march=armv8-a+crc} switch is used:
+
+@include arm-acle-intrinsics.texi
+
 @node AVR Built-in Functions
 @subsection AVR Built-in Functions
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c250385..c38740c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -12093,9 +12093,12 @@ of the @option{-mcpu=} option.  Permissible names are: @samp{armv2},
 @samp{armv6}, @samp{armv6j},
 @samp{armv6t2}, @samp{armv6z}, @samp{armv6zk}, @samp{armv6-m},
 @samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m},
-@samp{armv8-a},
+@samp{armv8-a}, @samp{armv8-a+crc},
 @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
 
+@option{-march=armv8-a+crc} enables code generation for the ARMv8-A
+architecture together with the optional CRC32 extensions.
+
 @option{-march=native} causes the compiler to auto-detect the architecture
 of the build computer.  At present, this feature is only supported on
 Linux, and not all architectures are recognized.  If the auto-detect is
diff --git a/gcc/testsuite/gcc.target/arm/acle/acle.exp b/gcc/testsuite/gcc.target/arm/acle/acle.exp
new file mode 100644
index 0000000..a1822a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/acle.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an ARM target.
+if ![istarget arm*-*-*] then {
+  return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+	"" ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32b.c b/gcc/testsuite/gcc.target/arm/acle/crc32b.c
new file mode 100644
index 0000000..d6f35e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32b.c
@@ -0,0 +1,20 @@
+/* Test the crc32b ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32b (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint8_t arg1_uint8_t;
+
+  out_uint32_t = __crc32b (arg0_uint32_t, arg1_uint8_t);
+}
+
+/* { dg-final { scan-assembler "crc32b\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cb.c b/gcc/testsuite/gcc.target/arm/acle/crc32cb.c
new file mode 100644
index 0000000..44aea21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cb.c
@@ -0,0 +1,20 @@
+/* Test the crc32cb ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cb (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint8_t arg1_uint8_t;
+
+  out_uint32_t = __crc32cb (arg0_uint32_t, arg1_uint8_t);
+}
+
+/* { dg-final { scan-assembler "crc32cb\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cd.c b/gcc/testsuite/gcc.target/arm/acle/crc32cd.c
new file mode 100644
index 0000000..cb7ee0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cd.c
@@ -0,0 +1,20 @@
+/* Test the crc32cd ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cd (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint64_t arg1_uint64_t;
+
+  out_uint32_t = __crc32cd (arg0_uint32_t, arg1_uint64_t);
+}
+
+/* { dg-final { scan-assembler-times "crc32cw\t...?, ...?, ...?\n" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32ch.c b/gcc/testsuite/gcc.target/arm/acle/crc32ch.c
new file mode 100644
index 0000000..d8e7338
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32ch.c
@@ -0,0 +1,20 @@
+/* Test the crc32ch ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32ch (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint16_t arg1_uint16_t;
+
+  out_uint32_t = __crc32ch (arg0_uint32_t, arg1_uint16_t);
+}
+
+/* { dg-final { scan-assembler "crc32ch\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32cw.c b/gcc/testsuite/gcc.target/arm/acle/crc32cw.c
new file mode 100644
index 0000000..84384c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32cw.c
@@ -0,0 +1,20 @@
+/* Test the crc32cw ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32cw (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint32_t arg1_uint32_t;
+
+  out_uint32_t = __crc32cw (arg0_uint32_t, arg1_uint32_t);
+}
+
+/* { dg-final { scan-assembler "crc32cw\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32d.c b/gcc/testsuite/gcc.target/arm/acle/crc32d.c
new file mode 100644
index 0000000..c90fad9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32d.c
@@ -0,0 +1,20 @@
+/* Test the crc32d ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32d (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint64_t arg1_uint64_t;
+
+  out_uint32_t = __crc32d (arg0_uint32_t, arg1_uint64_t);
+}
+
+/* { dg-final { scan-assembler-times "crc32w\t...?, ...?, ...?\n" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32h.c b/gcc/testsuite/gcc.target/arm/acle/crc32h.c
new file mode 100644
index 0000000..c21a4ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32h.c
@@ -0,0 +1,20 @@
+/* Test the crc32h ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32h (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint16_t arg1_uint16_t;
+
+  out_uint32_t = __crc32h (arg0_uint32_t, arg1_uint16_t);
+}
+
+/* { dg-final { scan-assembler "crc32h\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/crc32w.c b/gcc/testsuite/gcc.target/arm/acle/crc32w.c
new file mode 100644
index 0000000..60cd09e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/crc32w.c
@@ -0,0 +1,20 @@
+/* Test the crc32w ACLE intrinsic.  */
+
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_crc_ok } */
+/* { dg-options "-save-temps -O0" } */
+/* { dg-add-options arm_crc } */
+
+#include "arm_acle.h"
+
+void test_crc32w (void)
+{
+  uint32_t out_uint32_t;
+  uint32_t arg0_uint32_t;
+  uint32_t arg1_uint32_t;
+
+  out_uint32_t = __crc32w (arg0_uint32_t, arg1_uint32_t);
+}
+
+/* { dg-final { scan-assembler "crc32w\t...?, ...?, ...?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 104818d..a256b12 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2300,6 +2300,14 @@ proc add_options_for_arm_v8_neon { flags } {
     return "$flags $et_arm_v8_neon_flags -march=armv8-a"
 }
 
+proc add_options_for_arm_crc { flags } {
+    if { ! [check_effective_target_arm_crc_ok] } {
+        return "$flags"
+    }
+    global et_arm_crc_flags
+    return "$flags $et_arm_crc_flags"
+}
+
 # Add the options needed for NEON.  We need either -mfloat-abi=softfp
 # or -mfloat-abi=hard, but if one is already specified by the
 # multilib, use it.  Similarly, if a -mfpu option already enables
@@ -2341,6 +2349,21 @@ proc check_effective_target_arm_neon_ok { } {
 		check_effective_target_arm_neon_ok_nocache]
 }
 
+proc check_effective_target_arm_crc_ok_nocache { } {
+    global et_arm_crc_flags
+    set et_arm_crc_flags "-march=armv8-a+crc"
+    return [check_no_compiler_messages_nocache arm_crc_ok object {
+	#if !defined (__ARM_FEATURE_CRC32)
+	#error FOO
+	#endif
+    } "$et_arm_crc_flags"]
+}
+
+proc check_effective_target_arm_crc_ok { } {
+    return [check_cached_effective_target arm_crc_ok \
+		check_effective_target_arm_crc_ok_nocache]
+}
+
 # Return 1 if this is an ARM target supporting -mfpu=neon-fp16
 # -mfloat-abi=softfp or equivalent options.  Some multilibs may be
 # incompatible with these options.  Also set et_arm_neon_flags to the

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]