From d6add4cbc814e4d3193bfb4b702767d9af596298 Mon Sep 17 00:00:00 2001 From: ktkachov Date: Wed, 11 Jun 2014 09:17:18 +0000 Subject: [PATCH] [AArch64] Implement CRC32 ACLE intrinsics. * config.gcc (aarch64*-*-*): Add arm_acle.h to extra headers. * Makefile.in (TEXI_GCC_FILES): Add aarch64-acle-intrinsics.texi to dependencies. * config/aarch64/aarch64-builtins.c (AARCH64_CRC32_BUILTINS): Define. (aarch64_crc_builtin_datum): New struct. (aarch64_crc_builtin_data): New. (aarch64_init_crc32_builtins): New function. (aarch64_init_builtins): Initialise CRC32 builtins when appropriate. (aarch64_crc32_expand_builtin): New. (aarch64_expand_builtin): Add CRC32 builtin expansion case. * config/aarch64/aarch64.h (TARGET_CPU_CPP_BUILTINS): Define __ARM_FEATURE_CRC32 when appropriate. (TARGET_CRC32): Define. * config/aarch64/aarch64.md (UNSPEC_CRC32B, UNSPEC_CRC32H, UNSPEC_CRC32W, UNSPEC_CRC32X, UNSPEC_CRC32CB, UNSPEC_CRC32CH, UNSPEC_CRC32CW, UNSPEC_CRC32CX): New unspec values. (aarch64_): New pattern. * config/aarch64/arm_acle.h: New file. * config/aarch64/iterators.md (CRC): New int iterator. (crc_variant, crc_mode): New int attributes. * doc/aarch64-acle-intrinsics.texi: New file. * doc/extend.texi (aarch64): Document aarch64 ACLE intrinsics. Include aarch64-acle-intrinsics.texi. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211440 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 26 ++++++++++ gcc/Makefile.in | 2 +- gcc/config.gcc | 2 +- gcc/config/aarch64/aarch64-builtins.c | 94 ++++++++++++++++++++++++++++++++++- gcc/config/aarch64/aarch64.h | 6 +++ gcc/config/aarch64/aarch64.md | 25 ++++++++++ gcc/config/aarch64/arm_acle.h | 90 +++++++++++++++++++++++++++++++++ gcc/config/aarch64/iterators.md | 14 ++++++ gcc/doc/aarch64-acle-intrinsics.texi | 55 ++++++++++++++++++++ gcc/doc/extend.texi | 6 +++ 10 files changed, 317 insertions(+), 3 deletions(-) create mode 100644 gcc/config/aarch64/arm_acle.h create mode 100644 gcc/doc/aarch64-acle-intrinsics.texi diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d361c443ca7..9dc917791e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2014-06-11 Kyrylo Tkachov + + * config.gcc (aarch64*-*-*): Add arm_acle.h to extra headers. + * Makefile.in (TEXI_GCC_FILES): Add aarch64-acle-intrinsics.texi to + dependencies. + * config/aarch64/aarch64-builtins.c (AARCH64_CRC32_BUILTINS): Define. + (aarch64_crc_builtin_datum): New struct. + (aarch64_crc_builtin_data): New. + (aarch64_init_crc32_builtins): New function. + (aarch64_init_builtins): Initialise CRC32 builtins when appropriate. + (aarch64_crc32_expand_builtin): New. + (aarch64_expand_builtin): Add CRC32 builtin expansion case. + * config/aarch64/aarch64.h (TARGET_CPU_CPP_BUILTINS): Define + __ARM_FEATURE_CRC32 when appropriate. + (TARGET_CRC32): Define. + * config/aarch64/aarch64.md (UNSPEC_CRC32B, UNSPEC_CRC32H, + UNSPEC_CRC32W, UNSPEC_CRC32X, UNSPEC_CRC32CB, UNSPEC_CRC32CH, + UNSPEC_CRC32CW, UNSPEC_CRC32CX): New unspec values. + (aarch64_): New pattern. + * config/aarch64/arm_acle.h: New file. + * config/aarch64/iterators.md (CRC): New int iterator. + (crc_variant, crc_mode): New int attributes. + * doc/aarch64-acle-intrinsics.texi: New file. + * doc/extend.texi (aarch64): Document aarch64 ACLE intrinsics. + Include aarch64-acle-intrinsics.texi. + 2014-06-11 Evgeny Stupachenko * tree-vect-data-refs.c (vect_grouped_store_supported): New diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 335018606e5..a6fba3342c0 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2801,7 +2801,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.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 \ - arm-acle-intrinsics.texi + arm-acle-intrinsics.texi aarch64-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 c3f3ea6646c..80bb3db4d0e 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -302,7 +302,7 @@ m32c*-*-*) ;; aarch64*-*-*) cpu_type=aarch64 - extra_headers="arm_neon.h" + extra_headers="arm_neon.h arm_acle.h" extra_objs="aarch64-builtins.o aarch-common.o" target_has_targetm_common=yes ;; diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index fe4d39283b0..a94ef52f71a 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -411,6 +411,28 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = { #include "aarch64-simd-builtins.def" }; +/* There's only 8 CRC32 builtins. Probably not worth their own .def file. */ +#define AARCH64_CRC32_BUILTINS \ + CRC32_BUILTIN (crc32b, QI) \ + CRC32_BUILTIN (crc32h, HI) \ + CRC32_BUILTIN (crc32w, SI) \ + CRC32_BUILTIN (crc32x, DI) \ + CRC32_BUILTIN (crc32cb, QI) \ + CRC32_BUILTIN (crc32ch, HI) \ + CRC32_BUILTIN (crc32cw, SI) \ + CRC32_BUILTIN (crc32cx, DI) + +typedef struct +{ + const char *name; + enum machine_mode mode; + const enum insn_code icode; + unsigned int fcode; +} aarch64_crc_builtin_datum; + +#define CRC32_BUILTIN(N, M) \ + AARCH64_BUILTIN_##N, + #undef VAR1 #define VAR1(T, N, MAP, A) \ AARCH64_SIMD_BUILTIN_##T##_##N##A, @@ -428,9 +450,22 @@ enum aarch64_builtins #include "aarch64-simd-builtins.def" AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE + ARRAY_SIZE (aarch64_simd_builtin_data), + AARCH64_CRC32_BUILTIN_BASE, + AARCH64_CRC32_BUILTINS + AARCH64_CRC32_BUILTIN_MAX, AARCH64_BUILTIN_MAX }; +#undef CRC32_BUILTIN +#define CRC32_BUILTIN(N, M) \ + {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N}, + +static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = { + AARCH64_CRC32_BUILTINS +}; + +#undef CRC32_BUILTIN + static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX]; #define NUM_DREG_TYPES 6 @@ -802,6 +837,24 @@ aarch64_init_simd_builtins (void) } } +static void +aarch64_init_crc32_builtins () +{ + tree usi_type = aarch64_build_unsigned_type (SImode); + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i) + { + aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i]; + tree argtype = aarch64_build_unsigned_type (d->mode); + tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE); + tree fndecl = add_builtin_function (d->name, ftype, d->fcode, + BUILT_IN_MD, NULL, NULL_TREE); + + aarch64_builtin_decls[d->fcode] = fndecl; + } +} + void aarch64_init_builtins (void) { @@ -825,6 +878,8 @@ aarch64_init_builtins (void) if (TARGET_SIMD) aarch64_init_simd_builtins (); + if (TARGET_CRC32) + aarch64_init_crc32_builtins (); } tree @@ -1024,6 +1079,41 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target) SIMD_ARG_STOP); } +rtx +aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target) +{ + rtx pat; + aarch64_crc_builtin_datum *d + = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)]; + enum insn_code icode = d->icode; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode0 = insn_data[icode].operand[1].mode; + enum machine_mode mode1 = insn_data[icode].operand[2].mode; + + if (! target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode) + && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + pat = GEN_FCN (icode) (target, op0, op1); + if (! pat) + return 0; + emit_insn (pat); + return target; +} + /* Expand an expression EXP that calls a built-in function, with result going to TARGET if that's convenient. */ rtx @@ -1066,8 +1156,10 @@ aarch64_expand_builtin (tree exp, return target; } - if (fcode >= AARCH64_SIMD_BUILTIN_BASE) + if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX) return aarch64_simd_expand_builtin (fcode, exp, target); + else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX) + return aarch64_crc32_expand_builtin (fcode, exp, target); return NULL_RTX; } diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index a191162daf8..b95365a6eca 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -35,6 +35,9 @@ if (TARGET_SIMD) \ builtin_define ("__ARM_NEON"); \ \ + if (TARGET_CRC32) \ + builtin_define ("__ARM_FEATURE_CRC32"); \ + \ switch (aarch64_cmodel) \ { \ case AARCH64_CMODEL_TINY: \ @@ -188,6 +191,9 @@ extern unsigned long aarch64_tune_flags; /* Crypto is an optional extension to AdvSIMD. */ #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO) +/* CRC instructions that can be enabled through +crc arch extension. */ +#define TARGET_CRC32 (AARCH64_ISA_CRC) + /* Standard register usage. */ /* 31 64-bit general purpose registers R0-R30: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 662d26aa407..a4d88878d9b 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -68,6 +68,14 @@ (define_c_enum "unspec" [ UNSPEC_CASESI UNSPEC_CLS + UNSPEC_CRC32B + UNSPEC_CRC32CB + UNSPEC_CRC32CH + UNSPEC_CRC32CW + UNSPEC_CRC32CX + UNSPEC_CRC32H + UNSPEC_CRC32W + UNSPEC_CRC32X UNSPEC_FRECPE UNSPEC_FRECPS UNSPEC_FRECPX @@ -2481,6 +2489,23 @@ } ) + +;; CRC32 instructions. +(define_insn "aarch64_" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand: 2 "register_operand" "r")] + CRC))] + "TARGET_CRC32" + { + if (GET_MODE_BITSIZE (GET_MODE (operands[2])) >= 64) + return "\\t%w0, %w1, %x2"; + else + return "\\t%w0, %w1, %w2"; + } + [(set_attr "type" "crc")] +) + (define_insn "*csinc2_insn" [(set (match_operand:GPI 0 "register_operand" "=r") (plus:GPI (match_operator:GPI 2 "aarch64_comparison_operator" diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h new file mode 100644 index 00000000000..2e74696e204 --- /dev/null +++ b/gcc/config/aarch64/arm_acle.h @@ -0,0 +1,90 @@ +/* AArch64 Non-NEON ACLE intrinsics include file. + + Copyright (C) 2014 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 + . */ + +#ifndef _GCC_ARM_ACLE_H +#define _GCC_ARM_ACLE_H + +#include +#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_aarch64_crc32b (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32cb (uint32_t __a, uint8_t __b) +{ + return __builtin_aarch64_crc32cb (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32ch (uint32_t __a, uint16_t __b) +{ + return __builtin_aarch64_crc32ch (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32cw (uint32_t __a, uint32_t __b) +{ + return __builtin_aarch64_crc32cw (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32cd (uint32_t __a, uint64_t __b) +{ + return __builtin_aarch64_crc32cx (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32h (uint32_t __a, uint16_t __b) +{ + return __builtin_aarch64_crc32h (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32w (uint32_t __a, uint32_t __b) +{ + return __builtin_aarch64_crc32w (__a, __b); +} + +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +__crc32d (uint32_t __a, uint64_t __b) +{ + return __builtin_aarch64_crc32x (__a, __b); +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 05c4f7ea543..bf7b6830e00 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -910,6 +910,10 @@ (define_int_iterator FRECP [UNSPEC_FRECPE UNSPEC_FRECPX]) +(define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H UNSPEC_CRC32W + UNSPEC_CRC32X UNSPEC_CRC32CB UNSPEC_CRC32CH + UNSPEC_CRC32CW UNSPEC_CRC32CX]) + (define_int_iterator CRYPTO_AES [UNSPEC_AESE UNSPEC_AESD]) (define_int_iterator CRYPTO_AESMC [UNSPEC_AESMC UNSPEC_AESIMC]) @@ -1038,6 +1042,16 @@ (define_int_attr frecp_suffix [(UNSPEC_FRECPE "e") (UNSPEC_FRECPX "x")]) +(define_int_attr crc_variant [(UNSPEC_CRC32B "crc32b") (UNSPEC_CRC32H "crc32h") + (UNSPEC_CRC32W "crc32w") (UNSPEC_CRC32X "crc32x") + (UNSPEC_CRC32CB "crc32cb") (UNSPEC_CRC32CH "crc32ch") + (UNSPEC_CRC32CW "crc32cw") (UNSPEC_CRC32CX "crc32cx")]) + +(define_int_attr crc_mode [(UNSPEC_CRC32B "QI") (UNSPEC_CRC32H "HI") + (UNSPEC_CRC32W "SI") (UNSPEC_CRC32X "DI") + (UNSPEC_CRC32CB "QI") (UNSPEC_CRC32CH "HI") + (UNSPEC_CRC32CW "SI") (UNSPEC_CRC32CX "DI")]) + (define_int_attr aes_op [(UNSPEC_AESE "e") (UNSPEC_AESD "d")]) (define_int_attr aesmc_op [(UNSPEC_AESMC "mc") (UNSPEC_AESIMC "imc")]) diff --git a/gcc/doc/aarch64-acle-intrinsics.texi b/gcc/doc/aarch64-acle-intrinsics.texi new file mode 100644 index 00000000000..3194511a8d6 --- /dev/null +++ b/gcc/doc/aarch64-acle-intrinsics.texi @@ -0,0 +1,55 @@ +@c Copyright (C) 2014 Free Software Foundation, Inc. +@c This is part of the GCC manual. +@c For copying conditions, see the file gcc.texi. + +@subsubsection CRC32 intrinsics + +These intrinsics are available when the CRC32 architecture extension is +specified, e.g. when the @option{-march=armv8-a+crc} switch is used, or when +the target processor specified with @option{-mcpu} supports it. + +@itemize @bullet +@item uint32_t __crc32b (uint32_t, uint8_t) +@*@emph{Form of expected instruction(s):} @code{crc32b @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32h (uint32_t, uint16_t) +@*@emph{Form of expected instruction(s):} @code{crc32h @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32w (uint32_t, uint32_t) +@*@emph{Form of expected instruction(s):} @code{crc32w @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32d (uint32_t, uint64_t) +@*@emph{Form of expected instruction(s):} @code{crc32x @var{w0}, @var{w1}, @var{x2}} +@end itemize + +@itemize @bullet +@item uint32_t __crc32cb (uint32_t, uint8_t) +@*@emph{Form of expected instruction(s):} @code{crc32cb @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32ch (uint32_t, uint16_t) +@*@emph{Form of expected instruction(s):} @code{crc32ch @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32cw (uint32_t, uint32_t) +@*@emph{Form of expected instruction(s):} @code{crc32cw @var{w0}, @var{w1}, @var{w2}} +@end itemize + + +@itemize @bullet +@item uint32_t __crc32cd (uint32_t, uint64_t) +@*@emph{Form of expected instruction(s):} @code{crc32cx @var{w0}, @var{w1}, @var{x2}} +@end itemize diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index a79dbbfbade..c34c1b6e431 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9697,6 +9697,7 @@ instructions, but allow the compiler to schedule those calls. @menu * AArch64 Built-in Functions:: +* AArch64 intrinsics:: * Alpha Built-in Functions:: * Altera Nios II Built-in Functions:: * ARC Built-in Functions:: @@ -9742,6 +9743,11 @@ unsigned int __builtin_aarch64_get_fpsr () void __builtin_aarch64_set_fpsr (unsigned int) @end smallexample +@node AArch64 intrinsics +@subsection ACLE Intrinsics for AArch64 + +@include aarch64-acle-intrinsics.texi + @node Alpha Built-in Functions @subsection Alpha Built-in Functions -- 2.11.4.GIT