Home | History | Annotate | Line # | Download | only in aarch64
      1  1.1  mrg /* Builtins' description for AArch64 SIMD architecture.
      2  1.1  mrg    Copyright (C) 2011-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by ARM Ltd.
      4  1.1  mrg 
      5  1.1  mrg    This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg    GCC is free software; you can redistribute it and/or modify it
      8  1.1  mrg    under the terms of the GNU General Public License as published by
      9  1.1  mrg    the Free Software Foundation; either version 3, or (at your option)
     10  1.1  mrg    any later version.
     11  1.1  mrg 
     12  1.1  mrg    GCC is distributed in the hope that it will be useful, but
     13  1.1  mrg    WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  1.1  mrg    General Public License for more details.
     16  1.1  mrg 
     17  1.1  mrg    You should have received a copy of the GNU General Public License
     18  1.1  mrg    along with GCC; see the file COPYING3.  If not see
     19  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #define IN_TARGET_CODE 1
     22  1.1  mrg 
     23  1.1  mrg #include "config.h"
     24  1.1  mrg #include "system.h"
     25  1.1  mrg #include "coretypes.h"
     26  1.1  mrg #include "tm.h"
     27  1.1  mrg #include "function.h"
     28  1.1  mrg #include "basic-block.h"
     29  1.1  mrg #include "rtl.h"
     30  1.1  mrg #include "tree.h"
     31  1.1  mrg #include "gimple.h"
     32  1.1  mrg #include "ssa.h"
     33  1.1  mrg #include "memmodel.h"
     34  1.1  mrg #include "tm_p.h"
     35  1.1  mrg #include "expmed.h"
     36  1.1  mrg #include "optabs.h"
     37  1.1  mrg #include "recog.h"
     38  1.1  mrg #include "diagnostic-core.h"
     39  1.1  mrg #include "fold-const.h"
     40  1.1  mrg #include "stor-layout.h"
     41  1.1  mrg #include "explow.h"
     42  1.1  mrg #include "expr.h"
     43  1.1  mrg #include "langhooks.h"
     44  1.1  mrg #include "gimple-iterator.h"
     45  1.1  mrg #include "case-cfn-macros.h"
     46  1.1  mrg #include "emit-rtl.h"
     47  1.1  mrg #include "stringpool.h"
     48  1.1  mrg #include "attribs.h"
     49  1.1  mrg #include "gimple-fold.h"
     50  1.1  mrg 
     51  1.1  mrg #define v8qi_UP  E_V8QImode
     52  1.1  mrg #define v8di_UP  E_V8DImode
     53  1.1  mrg #define v4hi_UP  E_V4HImode
     54  1.1  mrg #define v4hf_UP  E_V4HFmode
     55  1.1  mrg #define v2si_UP  E_V2SImode
     56  1.1  mrg #define v2sf_UP  E_V2SFmode
     57  1.1  mrg #define v1df_UP  E_V1DFmode
     58  1.1  mrg #define di_UP    E_DImode
     59  1.1  mrg #define df_UP    E_DFmode
     60  1.1  mrg #define v16qi_UP E_V16QImode
     61  1.1  mrg #define v8hi_UP  E_V8HImode
     62  1.1  mrg #define v8hf_UP  E_V8HFmode
     63  1.1  mrg #define v4si_UP  E_V4SImode
     64  1.1  mrg #define v4sf_UP  E_V4SFmode
     65  1.1  mrg #define v2di_UP  E_V2DImode
     66  1.1  mrg #define v2df_UP  E_V2DFmode
     67  1.1  mrg #define ti_UP	 E_TImode
     68  1.1  mrg #define oi_UP	 E_OImode
     69  1.1  mrg #define ci_UP	 E_CImode
     70  1.1  mrg #define xi_UP	 E_XImode
     71  1.1  mrg #define si_UP    E_SImode
     72  1.1  mrg #define sf_UP    E_SFmode
     73  1.1  mrg #define hi_UP    E_HImode
     74  1.1  mrg #define hf_UP    E_HFmode
     75  1.1  mrg #define qi_UP    E_QImode
     76  1.1  mrg #define bf_UP    E_BFmode
     77  1.1  mrg #define v4bf_UP  E_V4BFmode
     78  1.1  mrg #define v8bf_UP  E_V8BFmode
     79  1.1  mrg #define v2x8qi_UP  E_V2x8QImode
     80  1.1  mrg #define v2x4hi_UP  E_V2x4HImode
     81  1.1  mrg #define v2x4hf_UP  E_V2x4HFmode
     82  1.1  mrg #define v2x4bf_UP  E_V2x4BFmode
     83  1.1  mrg #define v2x2si_UP  E_V2x2SImode
     84  1.1  mrg #define v2x2sf_UP  E_V2x2SFmode
     85  1.1  mrg #define v2x1di_UP  E_V2x1DImode
     86  1.1  mrg #define v2x1df_UP  E_V2x1DFmode
     87  1.1  mrg #define v2x16qi_UP E_V2x16QImode
     88  1.1  mrg #define v2x8hi_UP  E_V2x8HImode
     89  1.1  mrg #define v2x8hf_UP  E_V2x8HFmode
     90  1.1  mrg #define v2x8bf_UP  E_V2x8BFmode
     91  1.1  mrg #define v2x4si_UP  E_V2x4SImode
     92  1.1  mrg #define v2x4sf_UP  E_V2x4SFmode
     93  1.1  mrg #define v2x2di_UP  E_V2x2DImode
     94  1.1  mrg #define v2x2df_UP  E_V2x2DFmode
     95  1.1  mrg #define v3x8qi_UP  E_V3x8QImode
     96  1.1  mrg #define v3x4hi_UP  E_V3x4HImode
     97  1.1  mrg #define v3x4hf_UP  E_V3x4HFmode
     98  1.1  mrg #define v3x4bf_UP  E_V3x4BFmode
     99  1.1  mrg #define v3x2si_UP  E_V3x2SImode
    100  1.1  mrg #define v3x2sf_UP  E_V3x2SFmode
    101  1.1  mrg #define v3x1di_UP  E_V3x1DImode
    102  1.1  mrg #define v3x1df_UP  E_V3x1DFmode
    103  1.1  mrg #define v3x16qi_UP E_V3x16QImode
    104  1.1  mrg #define v3x8hi_UP  E_V3x8HImode
    105  1.1  mrg #define v3x8hf_UP  E_V3x8HFmode
    106  1.1  mrg #define v3x8bf_UP  E_V3x8BFmode
    107  1.1  mrg #define v3x4si_UP  E_V3x4SImode
    108  1.1  mrg #define v3x4sf_UP  E_V3x4SFmode
    109  1.1  mrg #define v3x2di_UP  E_V3x2DImode
    110  1.1  mrg #define v3x2df_UP  E_V3x2DFmode
    111  1.1  mrg #define v4x8qi_UP  E_V4x8QImode
    112  1.1  mrg #define v4x4hi_UP  E_V4x4HImode
    113  1.1  mrg #define v4x4hf_UP  E_V4x4HFmode
    114  1.1  mrg #define v4x4bf_UP  E_V4x4BFmode
    115  1.1  mrg #define v4x2si_UP  E_V4x2SImode
    116  1.1  mrg #define v4x2sf_UP  E_V4x2SFmode
    117  1.1  mrg #define v4x1di_UP  E_V4x1DImode
    118  1.1  mrg #define v4x1df_UP  E_V4x1DFmode
    119  1.1  mrg #define v4x16qi_UP E_V4x16QImode
    120  1.1  mrg #define v4x8hi_UP  E_V4x8HImode
    121  1.1  mrg #define v4x8hf_UP  E_V4x8HFmode
    122  1.1  mrg #define v4x8bf_UP  E_V4x8BFmode
    123  1.1  mrg #define v4x4si_UP  E_V4x4SImode
    124  1.1  mrg #define v4x4sf_UP  E_V4x4SFmode
    125  1.1  mrg #define v4x2di_UP  E_V4x2DImode
    126  1.1  mrg #define v4x2df_UP  E_V4x2DFmode
    127  1.1  mrg #define UP(X) X##_UP
    128  1.1  mrg 
    129  1.1  mrg #define SIMD_MAX_BUILTIN_ARGS 5
    130  1.1  mrg 
    131  1.1  mrg enum aarch64_type_qualifiers
    132  1.1  mrg {
    133  1.1  mrg   /* T foo.  */
    134  1.1  mrg   qualifier_none = 0x0,
    135  1.1  mrg   /* unsigned T foo.  */
    136  1.1  mrg   qualifier_unsigned = 0x1, /* 1 << 0  */
    137  1.1  mrg   /* const T foo.  */
    138  1.1  mrg   qualifier_const = 0x2, /* 1 << 1  */
    139  1.1  mrg   /* T *foo.  */
    140  1.1  mrg   qualifier_pointer = 0x4, /* 1 << 2  */
    141  1.1  mrg   /* Used when expanding arguments if an operand could
    142  1.1  mrg      be an immediate.  */
    143  1.1  mrg   qualifier_immediate = 0x8, /* 1 << 3  */
    144  1.1  mrg   qualifier_maybe_immediate = 0x10, /* 1 << 4  */
    145  1.1  mrg   /* void foo (...).  */
    146  1.1  mrg   qualifier_void = 0x20, /* 1 << 5  */
    147  1.1  mrg   /* Some patterns may have internal operands, this qualifier is an
    148  1.1  mrg      instruction to the initialisation code to skip this operand.  */
    149  1.1  mrg   qualifier_internal = 0x40, /* 1 << 6  */
    150  1.1  mrg   /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
    151  1.1  mrg      rather than using the type of the operand.  */
    152  1.1  mrg   qualifier_map_mode = 0x80, /* 1 << 7  */
    153  1.1  mrg   /* qualifier_pointer | qualifier_map_mode  */
    154  1.1  mrg   qualifier_pointer_map_mode = 0x84,
    155  1.1  mrg   /* qualifier_const | qualifier_pointer | qualifier_map_mode  */
    156  1.1  mrg   qualifier_const_pointer_map_mode = 0x86,
    157  1.1  mrg   /* Polynomial types.  */
    158  1.1  mrg   qualifier_poly = 0x100,
    159  1.1  mrg   /* Lane indices - must be in range, and flipped for bigendian.  */
    160  1.1  mrg   qualifier_lane_index = 0x200,
    161  1.1  mrg   /* Lane indices for single lane structure loads and stores.  */
    162  1.1  mrg   qualifier_struct_load_store_lane_index = 0x400,
    163  1.1  mrg   /* Lane indices selected in pairs. - must be in range, and flipped for
    164  1.1  mrg      bigendian.  */
    165  1.1  mrg   qualifier_lane_pair_index = 0x800,
    166  1.1  mrg   /* Lane indices selected in quadtuplets. - must be in range, and flipped for
    167  1.1  mrg      bigendian.  */
    168  1.1  mrg   qualifier_lane_quadtup_index = 0x1000,
    169  1.1  mrg };
    170  1.1  mrg 
    171  1.1  mrg /* Flags that describe what a function might do.  */
    172  1.1  mrg const unsigned int FLAG_NONE = 0U;
    173  1.1  mrg const unsigned int FLAG_READ_FPCR = 1U << 0;
    174  1.1  mrg const unsigned int FLAG_RAISE_FP_EXCEPTIONS = 1U << 1;
    175  1.1  mrg const unsigned int FLAG_READ_MEMORY = 1U << 2;
    176  1.1  mrg const unsigned int FLAG_PREFETCH_MEMORY = 1U << 3;
    177  1.1  mrg const unsigned int FLAG_WRITE_MEMORY = 1U << 4;
    178  1.1  mrg 
    179  1.1  mrg /* Not all FP intrinsics raise FP exceptions or read FPCR register,
    180  1.1  mrg    use this flag to suppress it.  */
    181  1.1  mrg const unsigned int FLAG_AUTO_FP = 1U << 5;
    182  1.1  mrg 
    183  1.1  mrg const unsigned int FLAG_FP = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS;
    184  1.1  mrg const unsigned int FLAG_ALL = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS
    185  1.1  mrg   | FLAG_READ_MEMORY | FLAG_PREFETCH_MEMORY | FLAG_WRITE_MEMORY;
    186  1.1  mrg const unsigned int FLAG_STORE = FLAG_WRITE_MEMORY | FLAG_AUTO_FP;
    187  1.1  mrg const unsigned int FLAG_LOAD = FLAG_READ_MEMORY | FLAG_AUTO_FP;
    188  1.1  mrg 
    189  1.1  mrg typedef struct
    190  1.1  mrg {
    191  1.1  mrg   const char *name;
    192  1.1  mrg   machine_mode mode;
    193  1.1  mrg   const enum insn_code code;
    194  1.1  mrg   unsigned int fcode;
    195  1.1  mrg   enum aarch64_type_qualifiers *qualifiers;
    196  1.1  mrg   unsigned int flags;
    197  1.1  mrg } aarch64_simd_builtin_datum;
    198  1.1  mrg 
    199  1.1  mrg static enum aarch64_type_qualifiers
    200  1.1  mrg aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    201  1.1  mrg   = { qualifier_none, qualifier_none };
    202  1.1  mrg #define TYPES_UNOP (aarch64_types_unop_qualifiers)
    203  1.1  mrg static enum aarch64_type_qualifiers
    204  1.1  mrg aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    205  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned };
    206  1.1  mrg #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
    207  1.1  mrg static enum aarch64_type_qualifiers
    208  1.1  mrg aarch64_types_unopus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    209  1.1  mrg   = { qualifier_unsigned, qualifier_none };
    210  1.1  mrg #define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
    211  1.1  mrg static enum aarch64_type_qualifiers
    212  1.1  mrg aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    213  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
    214  1.1  mrg #define TYPES_BINOP (aarch64_types_binop_qualifiers)
    215  1.1  mrg static enum aarch64_type_qualifiers
    216  1.1  mrg aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    217  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
    218  1.1  mrg #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
    219  1.1  mrg static enum aarch64_type_qualifiers
    220  1.1  mrg aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    221  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
    222  1.1  mrg #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
    223  1.1  mrg static enum aarch64_type_qualifiers
    224  1.1  mrg aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    225  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_unsigned };
    226  1.1  mrg #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
    227  1.1  mrg static enum aarch64_type_qualifiers
    228  1.1  mrg aarch64_types_binop_uss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    229  1.1  mrg   = { qualifier_unsigned, qualifier_none, qualifier_none };
    230  1.1  mrg #define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
    231  1.1  mrg static enum aarch64_type_qualifiers
    232  1.1  mrg aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    233  1.1  mrg   = { qualifier_poly, qualifier_poly, qualifier_poly };
    234  1.1  mrg #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
    235  1.1  mrg static enum aarch64_type_qualifiers
    236  1.1  mrg aarch64_types_binop_ppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    237  1.1  mrg   = { qualifier_poly, qualifier_poly, qualifier_unsigned };
    238  1.1  mrg #define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
    239  1.1  mrg 
    240  1.1  mrg static enum aarch64_type_qualifiers
    241  1.1  mrg aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    242  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
    243  1.1  mrg #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
    244  1.1  mrg static enum aarch64_type_qualifiers
    245  1.1  mrg aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    246  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
    247  1.1  mrg #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
    248  1.1  mrg static enum aarch64_type_qualifiers
    249  1.1  mrg aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    250  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned,
    251  1.1  mrg       qualifier_unsigned, qualifier_unsigned };
    252  1.1  mrg #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
    253  1.1  mrg static enum aarch64_type_qualifiers
    254  1.1  mrg aarch64_types_ternopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    255  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned,
    256  1.1  mrg       qualifier_unsigned, qualifier_lane_index };
    257  1.1  mrg #define TYPES_TERNOPU_LANE (aarch64_types_ternopu_lane_qualifiers)
    258  1.1  mrg static enum aarch64_type_qualifiers
    259  1.1  mrg aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    260  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned,
    261  1.1  mrg       qualifier_unsigned, qualifier_immediate };
    262  1.1  mrg #define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
    263  1.1  mrg static enum aarch64_type_qualifiers
    264  1.1  mrg aarch64_types_ternop_sssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    265  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none, qualifier_unsigned };
    266  1.1  mrg #define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
    267  1.1  mrg static enum aarch64_type_qualifiers
    268  1.1  mrg aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    269  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
    270  1.1  mrg #define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
    271  1.1  mrg static enum aarch64_type_qualifiers
    272  1.1  mrg aarch64_types_ternop_suss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    273  1.1  mrg   = { qualifier_none, qualifier_unsigned, qualifier_none, qualifier_none };
    274  1.1  mrg #define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
    275  1.1  mrg static enum aarch64_type_qualifiers
    276  1.1  mrg aarch64_types_binop_pppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    277  1.1  mrg   = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_unsigned };
    278  1.1  mrg #define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
    279  1.1  mrg 
    280  1.1  mrg static enum aarch64_type_qualifiers
    281  1.1  mrg aarch64_types_quadop_lane_pair_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    282  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none,
    283  1.1  mrg       qualifier_none, qualifier_lane_pair_index };
    284  1.1  mrg #define TYPES_QUADOP_LANE_PAIR (aarch64_types_quadop_lane_pair_qualifiers)
    285  1.1  mrg static enum aarch64_type_qualifiers
    286  1.1  mrg aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    287  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none,
    288  1.1  mrg       qualifier_none, qualifier_lane_index };
    289  1.1  mrg #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
    290  1.1  mrg static enum aarch64_type_qualifiers
    291  1.1  mrg aarch64_types_quadopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    292  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
    293  1.1  mrg       qualifier_unsigned, qualifier_lane_index };
    294  1.1  mrg #define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
    295  1.1  mrg 
    296  1.1  mrg static enum aarch64_type_qualifiers
    297  1.1  mrg aarch64_types_quadopssus_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    298  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_unsigned,
    299  1.1  mrg       qualifier_none, qualifier_lane_quadtup_index };
    300  1.1  mrg #define TYPES_QUADOPSSUS_LANE_QUADTUP \
    301  1.1  mrg 	(aarch64_types_quadopssus_lane_quadtup_qualifiers)
    302  1.1  mrg static enum aarch64_type_qualifiers
    303  1.1  mrg aarch64_types_quadopsssu_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    304  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none,
    305  1.1  mrg       qualifier_unsigned, qualifier_lane_quadtup_index };
    306  1.1  mrg #define TYPES_QUADOPSSSU_LANE_QUADTUP \
    307  1.1  mrg 	(aarch64_types_quadopsssu_lane_quadtup_qualifiers)
    308  1.1  mrg 
    309  1.1  mrg static enum aarch64_type_qualifiers
    310  1.1  mrg aarch64_types_quadopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    311  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
    312  1.1  mrg       qualifier_unsigned, qualifier_immediate };
    313  1.1  mrg #define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
    314  1.1  mrg 
    315  1.1  mrg static enum aarch64_type_qualifiers
    316  1.1  mrg aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    317  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_immediate };
    318  1.1  mrg #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
    319  1.1  mrg #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
    320  1.1  mrg static enum aarch64_type_qualifiers
    321  1.1  mrg aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    322  1.1  mrg   = { qualifier_unsigned, qualifier_none, qualifier_immediate };
    323  1.1  mrg #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
    324  1.1  mrg static enum aarch64_type_qualifiers
    325  1.1  mrg aarch64_types_fcvt_from_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    326  1.1  mrg   = { qualifier_none, qualifier_unsigned, qualifier_immediate };
    327  1.1  mrg #define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
    328  1.1  mrg static enum aarch64_type_qualifiers
    329  1.1  mrg aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    330  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
    331  1.1  mrg #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
    332  1.1  mrg #define TYPES_USHIFT2IMM (aarch64_types_ternopu_imm_qualifiers)
    333  1.1  mrg static enum aarch64_type_qualifiers
    334  1.1  mrg aarch64_types_shift2_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    335  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_immediate };
    336  1.1  mrg #define TYPES_SHIFT2IMM_UUSS (aarch64_types_shift2_to_unsigned_qualifiers)
    337  1.1  mrg 
    338  1.1  mrg static enum aarch64_type_qualifiers
    339  1.1  mrg aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    340  1.1  mrg   = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate};
    341  1.1  mrg #define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
    342  1.1  mrg #define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
    343  1.1  mrg #define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
    344  1.1  mrg #define TYPES_SHIFT2IMM (aarch64_types_ternop_s_imm_qualifiers)
    345  1.1  mrg 
    346  1.1  mrg static enum aarch64_type_qualifiers
    347  1.1  mrg aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    348  1.1  mrg   = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_immediate};
    349  1.1  mrg #define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
    350  1.1  mrg 
    351  1.1  mrg static enum aarch64_type_qualifiers
    352  1.1  mrg aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    353  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
    354  1.1  mrg       qualifier_immediate };
    355  1.1  mrg #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
    356  1.1  mrg 
    357  1.1  mrg static enum aarch64_type_qualifiers
    358  1.1  mrg aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    359  1.1  mrg   = { qualifier_none, qualifier_const_pointer_map_mode };
    360  1.1  mrg #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
    361  1.1  mrg #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
    362  1.1  mrg static enum aarch64_type_qualifiers
    363  1.1  mrg aarch64_types_load1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    364  1.1  mrg   = { qualifier_unsigned, qualifier_const_pointer_map_mode };
    365  1.1  mrg #define TYPES_LOAD1_U (aarch64_types_load1_u_qualifiers)
    366  1.1  mrg #define TYPES_LOADSTRUCT_U (aarch64_types_load1_u_qualifiers)
    367  1.1  mrg static enum aarch64_type_qualifiers
    368  1.1  mrg aarch64_types_load1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    369  1.1  mrg   = { qualifier_poly, qualifier_const_pointer_map_mode };
    370  1.1  mrg #define TYPES_LOAD1_P (aarch64_types_load1_p_qualifiers)
    371  1.1  mrg #define TYPES_LOADSTRUCT_P (aarch64_types_load1_p_qualifiers)
    372  1.1  mrg 
    373  1.1  mrg static enum aarch64_type_qualifiers
    374  1.1  mrg aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    375  1.1  mrg   = { qualifier_none, qualifier_const_pointer_map_mode,
    376  1.1  mrg       qualifier_none, qualifier_struct_load_store_lane_index };
    377  1.1  mrg #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
    378  1.1  mrg static enum aarch64_type_qualifiers
    379  1.1  mrg aarch64_types_loadstruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    380  1.1  mrg   = { qualifier_unsigned, qualifier_const_pointer_map_mode,
    381  1.1  mrg       qualifier_unsigned, qualifier_struct_load_store_lane_index };
    382  1.1  mrg #define TYPES_LOADSTRUCT_LANE_U (aarch64_types_loadstruct_lane_u_qualifiers)
    383  1.1  mrg static enum aarch64_type_qualifiers
    384  1.1  mrg aarch64_types_loadstruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    385  1.1  mrg   = { qualifier_poly, qualifier_const_pointer_map_mode,
    386  1.1  mrg       qualifier_poly, qualifier_struct_load_store_lane_index };
    387  1.1  mrg #define TYPES_LOADSTRUCT_LANE_P (aarch64_types_loadstruct_lane_p_qualifiers)
    388  1.1  mrg 
    389  1.1  mrg static enum aarch64_type_qualifiers
    390  1.1  mrg aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    391  1.1  mrg   = { qualifier_poly, qualifier_unsigned,
    392  1.1  mrg       qualifier_poly, qualifier_poly };
    393  1.1  mrg #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
    394  1.1  mrg static enum aarch64_type_qualifiers
    395  1.1  mrg aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    396  1.1  mrg   = { qualifier_none, qualifier_unsigned,
    397  1.1  mrg       qualifier_none, qualifier_none };
    398  1.1  mrg #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
    399  1.1  mrg static enum aarch64_type_qualifiers
    400  1.1  mrg aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    401  1.1  mrg   = { qualifier_unsigned, qualifier_unsigned,
    402  1.1  mrg       qualifier_unsigned, qualifier_unsigned };
    403  1.1  mrg #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
    404  1.1  mrg 
    405  1.1  mrg /* The first argument (return type) of a store should be void type,
    406  1.1  mrg    which we represent with qualifier_void.  Their first operand will be
    407  1.1  mrg    a DImode pointer to the location to store to, so we must use
    408  1.1  mrg    qualifier_map_mode | qualifier_pointer to build a pointer to the
    409  1.1  mrg    element type of the vector.  */
    410  1.1  mrg static enum aarch64_type_qualifiers
    411  1.1  mrg aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    412  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
    413  1.1  mrg #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
    414  1.1  mrg #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
    415  1.1  mrg static enum aarch64_type_qualifiers
    416  1.1  mrg aarch64_types_store1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    417  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode, qualifier_unsigned };
    418  1.1  mrg #define TYPES_STORE1_U (aarch64_types_store1_u_qualifiers)
    419  1.1  mrg #define TYPES_STORESTRUCT_U (aarch64_types_store1_u_qualifiers)
    420  1.1  mrg static enum aarch64_type_qualifiers
    421  1.1  mrg aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    422  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
    423  1.1  mrg #define TYPES_STORE1_P (aarch64_types_store1_p_qualifiers)
    424  1.1  mrg #define TYPES_STORESTRUCT_P (aarch64_types_store1_p_qualifiers)
    425  1.1  mrg 
    426  1.1  mrg static enum aarch64_type_qualifiers
    427  1.1  mrg aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    428  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode,
    429  1.1  mrg       qualifier_none, qualifier_struct_load_store_lane_index };
    430  1.1  mrg #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
    431  1.1  mrg static enum aarch64_type_qualifiers
    432  1.1  mrg aarch64_types_storestruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    433  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode,
    434  1.1  mrg       qualifier_unsigned, qualifier_struct_load_store_lane_index };
    435  1.1  mrg #define TYPES_STORESTRUCT_LANE_U (aarch64_types_storestruct_lane_u_qualifiers)
    436  1.1  mrg static enum aarch64_type_qualifiers
    437  1.1  mrg aarch64_types_storestruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
    438  1.1  mrg   = { qualifier_void, qualifier_pointer_map_mode,
    439  1.1  mrg       qualifier_poly, qualifier_struct_load_store_lane_index };
    440  1.1  mrg #define TYPES_STORESTRUCT_LANE_P (aarch64_types_storestruct_lane_p_qualifiers)
    441  1.1  mrg 
    442  1.1  mrg #define CF0(N, X) CODE_FOR_aarch64_##N##X
    443  1.1  mrg #define CF1(N, X) CODE_FOR_##N##X##1
    444  1.1  mrg #define CF2(N, X) CODE_FOR_##N##X##2
    445  1.1  mrg #define CF3(N, X) CODE_FOR_##N##X##3
    446  1.1  mrg #define CF4(N, X) CODE_FOR_##N##X##4
    447  1.1  mrg #define CF10(N, X) CODE_FOR_##N##X
    448  1.1  mrg 
    449  1.1  mrg #define VAR1(T, N, MAP, FLAG, A) \
    450  1.1  mrg   {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG},
    451  1.1  mrg #define VAR2(T, N, MAP, FLAG, A, B) \
    452  1.1  mrg   VAR1 (T, N, MAP, FLAG, A) \
    453  1.1  mrg   VAR1 (T, N, MAP, FLAG, B)
    454  1.1  mrg #define VAR3(T, N, MAP, FLAG, A, B, C) \
    455  1.1  mrg   VAR2 (T, N, MAP, FLAG, A, B) \
    456  1.1  mrg   VAR1 (T, N, MAP, FLAG, C)
    457  1.1  mrg #define VAR4(T, N, MAP, FLAG, A, B, C, D) \
    458  1.1  mrg   VAR3 (T, N, MAP, FLAG, A, B, C) \
    459  1.1  mrg   VAR1 (T, N, MAP, FLAG, D)
    460  1.1  mrg #define VAR5(T, N, MAP, FLAG, A, B, C, D, E) \
    461  1.1  mrg   VAR4 (T, N, MAP, FLAG, A, B, C, D) \
    462  1.1  mrg   VAR1 (T, N, MAP, FLAG, E)
    463  1.1  mrg #define VAR6(T, N, MAP, FLAG, A, B, C, D, E, F) \
    464  1.1  mrg   VAR5 (T, N, MAP, FLAG, A, B, C, D, E) \
    465  1.1  mrg   VAR1 (T, N, MAP, FLAG, F)
    466  1.1  mrg #define VAR7(T, N, MAP, FLAG, A, B, C, D, E, F, G) \
    467  1.1  mrg   VAR6 (T, N, MAP, FLAG, A, B, C, D, E, F) \
    468  1.1  mrg   VAR1 (T, N, MAP, FLAG, G)
    469  1.1  mrg #define VAR8(T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
    470  1.1  mrg   VAR7 (T, N, MAP, FLAG, A, B, C, D, E, F, G) \
    471  1.1  mrg   VAR1 (T, N, MAP, FLAG, H)
    472  1.1  mrg #define VAR9(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
    473  1.1  mrg   VAR8 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
    474  1.1  mrg   VAR1 (T, N, MAP, FLAG, I)
    475  1.1  mrg #define VAR10(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
    476  1.1  mrg   VAR9 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
    477  1.1  mrg   VAR1 (T, N, MAP, FLAG, J)
    478  1.1  mrg #define VAR11(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
    479  1.1  mrg   VAR10 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
    480  1.1  mrg   VAR1 (T, N, MAP, FLAG, K)
    481  1.1  mrg #define VAR12(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
    482  1.1  mrg   VAR11 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
    483  1.1  mrg   VAR1 (T, N, MAP, FLAG, L)
    484  1.1  mrg #define VAR13(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
    485  1.1  mrg   VAR12 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
    486  1.1  mrg   VAR1 (T, N, MAP, FLAG, M)
    487  1.1  mrg #define VAR14(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
    488  1.1  mrg   VAR13 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
    489  1.1  mrg   VAR1 (T, X, MAP, FLAG, N)
    490  1.1  mrg #define VAR15(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
    491  1.1  mrg   VAR14 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
    492  1.1  mrg   VAR1 (T, X, MAP, FLAG, O)
    493  1.1  mrg #define VAR16(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
    494  1.1  mrg   VAR15 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
    495  1.1  mrg   VAR1 (T, X, MAP, FLAG, P)
    496  1.1  mrg 
    497  1.1  mrg #include "aarch64-builtin-iterators.h"
    498  1.1  mrg 
    499  1.1  mrg static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
    500  1.1  mrg #include "aarch64-simd-builtins.def"
    501  1.1  mrg };
    502  1.1  mrg 
    503  1.1  mrg /* There's only 8 CRC32 builtins.  Probably not worth their own .def file.  */
    504  1.1  mrg #define AARCH64_CRC32_BUILTINS \
    505  1.1  mrg   CRC32_BUILTIN (crc32b, QI) \
    506  1.1  mrg   CRC32_BUILTIN (crc32h, HI) \
    507  1.1  mrg   CRC32_BUILTIN (crc32w, SI) \
    508  1.1  mrg   CRC32_BUILTIN (crc32x, DI) \
    509  1.1  mrg   CRC32_BUILTIN (crc32cb, QI) \
    510  1.1  mrg   CRC32_BUILTIN (crc32ch, HI) \
    511  1.1  mrg   CRC32_BUILTIN (crc32cw, SI) \
    512  1.1  mrg   CRC32_BUILTIN (crc32cx, DI)
    513  1.1  mrg 
    514  1.1  mrg /* The next 8 FCMLA instrinsics require some special handling compared the
    515  1.1  mrg    normal simd intrinsics.  */
    516  1.1  mrg #define AARCH64_SIMD_FCMLA_LANEQ_BUILTINS \
    517  1.1  mrg   FCMLA_LANEQ_BUILTIN (0, v2sf, fcmla, V2SF, false) \
    518  1.1  mrg   FCMLA_LANEQ_BUILTIN (90, v2sf, fcmla, V2SF, false) \
    519  1.1  mrg   FCMLA_LANEQ_BUILTIN (180, v2sf, fcmla, V2SF, false) \
    520  1.1  mrg   FCMLA_LANEQ_BUILTIN (270, v2sf, fcmla, V2SF, false) \
    521  1.1  mrg   FCMLA_LANEQ_BUILTIN (0, v4hf, fcmla_laneq, V4HF, true) \
    522  1.1  mrg   FCMLA_LANEQ_BUILTIN (90, v4hf, fcmla_laneq, V4HF, true) \
    523  1.1  mrg   FCMLA_LANEQ_BUILTIN (180, v4hf, fcmla_laneq, V4HF, true) \
    524  1.1  mrg   FCMLA_LANEQ_BUILTIN (270, v4hf, fcmla_laneq, V4HF, true) \
    525  1.1  mrg 
    526  1.1  mrg typedef struct
    527  1.1  mrg {
    528  1.1  mrg   const char *name;
    529  1.1  mrg   machine_mode mode;
    530  1.1  mrg   const enum insn_code icode;
    531  1.1  mrg   unsigned int fcode;
    532  1.1  mrg } aarch64_crc_builtin_datum;
    533  1.1  mrg 
    534  1.1  mrg /* Hold information about how to expand the FCMLA_LANEQ builtins.  */
    535  1.1  mrg typedef struct
    536  1.1  mrg {
    537  1.1  mrg   const char *name;
    538  1.1  mrg   machine_mode mode;
    539  1.1  mrg   const enum insn_code icode;
    540  1.1  mrg   unsigned int fcode;
    541  1.1  mrg   bool lane;
    542  1.1  mrg } aarch64_fcmla_laneq_builtin_datum;
    543  1.1  mrg 
    544  1.1  mrg #define CRC32_BUILTIN(N, M) \
    545  1.1  mrg   AARCH64_BUILTIN_##N,
    546  1.1  mrg 
    547  1.1  mrg #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
    548  1.1  mrg   AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M,
    549  1.1  mrg 
    550  1.1  mrg #undef VAR1
    551  1.1  mrg #define VAR1(T, N, MAP, FLAG, A) \
    552  1.1  mrg   AARCH64_SIMD_BUILTIN_##T##_##N##A,
    553  1.1  mrg 
    554  1.1  mrg enum aarch64_builtins
    555  1.1  mrg {
    556  1.1  mrg   AARCH64_BUILTIN_MIN,
    557  1.1  mrg 
    558  1.1  mrg   AARCH64_BUILTIN_GET_FPCR,
    559  1.1  mrg   AARCH64_BUILTIN_SET_FPCR,
    560  1.1  mrg   AARCH64_BUILTIN_GET_FPSR,
    561  1.1  mrg   AARCH64_BUILTIN_SET_FPSR,
    562  1.1  mrg 
    563  1.1  mrg   AARCH64_BUILTIN_GET_FPCR64,
    564  1.1  mrg   AARCH64_BUILTIN_SET_FPCR64,
    565  1.1  mrg   AARCH64_BUILTIN_GET_FPSR64,
    566  1.1  mrg   AARCH64_BUILTIN_SET_FPSR64,
    567  1.1  mrg 
    568  1.1  mrg   AARCH64_BUILTIN_RSQRT_DF,
    569  1.1  mrg   AARCH64_BUILTIN_RSQRT_SF,
    570  1.1  mrg   AARCH64_BUILTIN_RSQRT_V2DF,
    571  1.1  mrg   AARCH64_BUILTIN_RSQRT_V2SF,
    572  1.1  mrg   AARCH64_BUILTIN_RSQRT_V4SF,
    573  1.1  mrg   AARCH64_SIMD_BUILTIN_BASE,
    574  1.1  mrg   AARCH64_SIMD_BUILTIN_LANE_CHECK,
    575  1.1  mrg #include "aarch64-simd-builtins.def"
    576  1.1  mrg   /* The first enum element which is based on an insn_data pattern.  */
    577  1.1  mrg   AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
    578  1.1  mrg   AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
    579  1.1  mrg 			      + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
    580  1.1  mrg   AARCH64_CRC32_BUILTIN_BASE,
    581  1.1  mrg   AARCH64_CRC32_BUILTINS
    582  1.1  mrg   AARCH64_CRC32_BUILTIN_MAX,
    583  1.1  mrg   /* ARMv8.3-A Pointer Authentication Builtins.  */
    584  1.1  mrg   AARCH64_PAUTH_BUILTIN_AUTIA1716,
    585  1.1  mrg   AARCH64_PAUTH_BUILTIN_PACIA1716,
    586  1.1  mrg   AARCH64_PAUTH_BUILTIN_AUTIB1716,
    587  1.1  mrg   AARCH64_PAUTH_BUILTIN_PACIB1716,
    588  1.1  mrg   AARCH64_PAUTH_BUILTIN_XPACLRI,
    589  1.1  mrg   /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins.  */
    590  1.1  mrg   AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE,
    591  1.1  mrg   AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
    592  1.1  mrg   /* Builtin for Arm8.3-a Javascript conversion instruction.  */
    593  1.1  mrg   AARCH64_JSCVT,
    594  1.1  mrg   /* TME builtins.  */
    595  1.1  mrg   AARCH64_TME_BUILTIN_TSTART,
    596  1.1  mrg   AARCH64_TME_BUILTIN_TCOMMIT,
    597  1.1  mrg   AARCH64_TME_BUILTIN_TTEST,
    598  1.1  mrg   AARCH64_TME_BUILTIN_TCANCEL,
    599  1.1  mrg   /* Armv8.5-a RNG instruction builtins.  */
    600  1.1  mrg   AARCH64_BUILTIN_RNG_RNDR,
    601  1.1  mrg   AARCH64_BUILTIN_RNG_RNDRRS,
    602  1.1  mrg   /* MEMTAG builtins.  */
    603  1.1  mrg   AARCH64_MEMTAG_BUILTIN_START,
    604  1.1  mrg   AARCH64_MEMTAG_BUILTIN_IRG,
    605  1.1  mrg   AARCH64_MEMTAG_BUILTIN_GMI,
    606  1.1  mrg   AARCH64_MEMTAG_BUILTIN_SUBP,
    607  1.1  mrg   AARCH64_MEMTAG_BUILTIN_INC_TAG,
    608  1.1  mrg   AARCH64_MEMTAG_BUILTIN_SET_TAG,
    609  1.1  mrg   AARCH64_MEMTAG_BUILTIN_GET_TAG,
    610  1.1  mrg   AARCH64_MEMTAG_BUILTIN_END,
    611  1.1  mrg   /* LS64 builtins.  */
    612  1.1  mrg   AARCH64_LS64_BUILTIN_LD64B,
    613  1.1  mrg   AARCH64_LS64_BUILTIN_ST64B,
    614  1.1  mrg   AARCH64_LS64_BUILTIN_ST64BV,
    615  1.1  mrg   AARCH64_LS64_BUILTIN_ST64BV0,
    616  1.1  mrg   AARCH64_REV16,
    617  1.1  mrg   AARCH64_REV16L,
    618  1.1  mrg   AARCH64_REV16LL,
    619  1.1  mrg   AARCH64_RBIT,
    620  1.1  mrg   AARCH64_RBITL,
    621  1.1  mrg   AARCH64_RBITLL,
    622  1.1  mrg   AARCH64_BUILTIN_MAX
    623  1.1  mrg };
    624  1.1  mrg 
    625  1.1  mrg #undef CRC32_BUILTIN
    626  1.1  mrg #define CRC32_BUILTIN(N, M) \
    627  1.1  mrg   {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
    628  1.1  mrg 
    629  1.1  mrg static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
    630  1.1  mrg   AARCH64_CRC32_BUILTINS
    631  1.1  mrg };
    632  1.1  mrg 
    633  1.1  mrg 
    634  1.1  mrg #undef FCMLA_LANEQ_BUILTIN
    635  1.1  mrg #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
    636  1.1  mrg   {"__builtin_aarch64_fcmla_laneq"#I#N, E_##M##mode, CODE_FOR_aarch64_##X##I##N, \
    637  1.1  mrg    AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M, T},
    638  1.1  mrg 
    639  1.1  mrg /* This structure contains how to manage the mapping form the builtin to the
    640  1.1  mrg    instruction to generate in the backend and how to invoke the instruction.  */
    641  1.1  mrg static aarch64_fcmla_laneq_builtin_datum aarch64_fcmla_lane_builtin_data[] = {
    642  1.1  mrg   AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
    643  1.1  mrg };
    644  1.1  mrg 
    645  1.1  mrg #undef CRC32_BUILTIN
    646  1.1  mrg 
    647  1.1  mrg static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
    648  1.1  mrg 
    649  1.1  mrg #define NUM_DREG_TYPES 6
    650  1.1  mrg #define NUM_QREG_TYPES 6
    651  1.1  mrg 
    652  1.1  mrg /* Internal scalar builtin types.  These types are used to support
    653  1.1  mrg    neon intrinsic builtins.  They are _not_ user-visible types.  Therefore
    654  1.1  mrg    the mangling for these types are implementation defined.  */
    655  1.1  mrg const char *aarch64_scalar_builtin_types[] = {
    656  1.1  mrg   "__builtin_aarch64_simd_qi",
    657  1.1  mrg   "__builtin_aarch64_simd_hi",
    658  1.1  mrg   "__builtin_aarch64_simd_si",
    659  1.1  mrg   "__builtin_aarch64_simd_hf",
    660  1.1  mrg   "__builtin_aarch64_simd_sf",
    661  1.1  mrg   "__builtin_aarch64_simd_di",
    662  1.1  mrg   "__builtin_aarch64_simd_df",
    663  1.1  mrg   "__builtin_aarch64_simd_poly8",
    664  1.1  mrg   "__builtin_aarch64_simd_poly16",
    665  1.1  mrg   "__builtin_aarch64_simd_poly64",
    666  1.1  mrg   "__builtin_aarch64_simd_poly128",
    667  1.1  mrg   "__builtin_aarch64_simd_ti",
    668  1.1  mrg   "__builtin_aarch64_simd_uqi",
    669  1.1  mrg   "__builtin_aarch64_simd_uhi",
    670  1.1  mrg   "__builtin_aarch64_simd_usi",
    671  1.1  mrg   "__builtin_aarch64_simd_udi",
    672  1.1  mrg   "__builtin_aarch64_simd_ei",
    673  1.1  mrg   "__builtin_aarch64_simd_oi",
    674  1.1  mrg   "__builtin_aarch64_simd_ci",
    675  1.1  mrg   "__builtin_aarch64_simd_xi",
    676  1.1  mrg   "__builtin_aarch64_simd_bf",
    677  1.1  mrg   NULL
    678  1.1  mrg };
    679  1.1  mrg 
    680  1.1  mrg #define ENTRY(E, M, Q, G) E,
    681  1.1  mrg enum aarch64_simd_type
    682  1.1  mrg {
    683  1.1  mrg #include "aarch64-simd-builtin-types.def"
    684  1.1  mrg   ARM_NEON_H_TYPES_LAST
    685  1.1  mrg };
    686  1.1  mrg #undef ENTRY
    687  1.1  mrg 
    688  1.1  mrg struct GTY(()) aarch64_simd_type_info
    689  1.1  mrg {
    690  1.1  mrg   enum aarch64_simd_type type;
    691  1.1  mrg 
    692  1.1  mrg   /* Internal type name.  */
    693  1.1  mrg   const char *name;
    694  1.1  mrg 
    695  1.1  mrg   /* Internal type name(mangled).  The mangled names conform to the
    696  1.1  mrg      AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
    697  1.1  mrg      Appendix A).  To qualify for emission with the mangled names defined in
    698  1.1  mrg      that document, a vector type must not only be of the correct mode but also
    699  1.1  mrg      be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
    700  1.1  mrg      types are registered by aarch64_init_simd_builtin_types ().  In other
    701  1.1  mrg      words, vector types defined in other ways e.g. via vector_size attribute
    702  1.1  mrg      will get default mangled names.  */
    703  1.1  mrg   const char *mangle;
    704  1.1  mrg 
    705  1.1  mrg   /* Internal type.  */
    706  1.1  mrg   tree itype;
    707  1.1  mrg 
    708  1.1  mrg   /* Element type.  */
    709  1.1  mrg   tree eltype;
    710  1.1  mrg 
    711  1.1  mrg   /* Machine mode the internal type maps to.  */
    712  1.1  mrg   enum machine_mode mode;
    713  1.1  mrg 
    714  1.1  mrg   /* Qualifiers.  */
    715  1.1  mrg   enum aarch64_type_qualifiers q;
    716  1.1  mrg };
    717  1.1  mrg 
    718  1.1  mrg #define ENTRY(E, M, Q, G)  \
    719  1.1  mrg   {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
    720  1.1  mrg static GTY(()) struct aarch64_simd_type_info aarch64_simd_types [] = {
    721  1.1  mrg #include "aarch64-simd-builtin-types.def"
    722  1.1  mrg };
    723  1.1  mrg #undef ENTRY
    724  1.1  mrg 
    725  1.1  mrg static machine_mode aarch64_simd_tuple_modes[ARM_NEON_H_TYPES_LAST][3];
    726  1.1  mrg static GTY(()) tree aarch64_simd_tuple_types[ARM_NEON_H_TYPES_LAST][3];
    727  1.1  mrg 
    728  1.1  mrg static GTY(()) tree aarch64_simd_intOI_type_node = NULL_TREE;
    729  1.1  mrg static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE;
    730  1.1  mrg static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE;
    731  1.1  mrg 
    732  1.1  mrg /* The user-visible __fp16 type, and a pointer to that type.  Used
    733  1.1  mrg    across the back-end.  */
    734  1.1  mrg tree aarch64_fp16_type_node = NULL_TREE;
    735  1.1  mrg tree aarch64_fp16_ptr_type_node = NULL_TREE;
    736  1.1  mrg 
    737  1.1  mrg /* Back-end node type for brain float (bfloat) types.  */
    738  1.1  mrg tree aarch64_bf16_type_node = NULL_TREE;
    739  1.1  mrg tree aarch64_bf16_ptr_type_node = NULL_TREE;
    740  1.1  mrg 
    741  1.1  mrg /* Wrapper around add_builtin_function.  NAME is the name of the built-in
    742  1.1  mrg    function, TYPE is the function type, CODE is the function subcode
    743  1.1  mrg    (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
    744  1.1  mrg    attributes.  */
    745  1.1  mrg static tree
    746  1.1  mrg aarch64_general_add_builtin (const char *name, tree type, unsigned int code,
    747  1.1  mrg 			     tree attrs = NULL_TREE)
    748  1.1  mrg {
    749  1.1  mrg   code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
    750  1.1  mrg   return add_builtin_function (name, type, code, BUILT_IN_MD,
    751  1.1  mrg 			       NULL, attrs);
    752  1.1  mrg }
    753  1.1  mrg 
    754  1.1  mrg static tree
    755  1.1  mrg aarch64_general_simulate_builtin (const char *name, tree fntype,
    756  1.1  mrg 				  unsigned int code,
    757  1.1  mrg 				  tree attrs = NULL_TREE)
    758  1.1  mrg {
    759  1.1  mrg   code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
    760  1.1  mrg   return simulate_builtin_function_decl (input_location, name, fntype,
    761  1.1  mrg 					 code, NULL, attrs);
    762  1.1  mrg }
    763  1.1  mrg 
    764  1.1  mrg static const char *
    765  1.1  mrg aarch64_mangle_builtin_scalar_type (const_tree type)
    766  1.1  mrg {
    767  1.1  mrg   int i = 0;
    768  1.1  mrg 
    769  1.1  mrg   while (aarch64_scalar_builtin_types[i] != NULL)
    770  1.1  mrg     {
    771  1.1  mrg       const char *name = aarch64_scalar_builtin_types[i];
    772  1.1  mrg 
    773  1.1  mrg       if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
    774  1.1  mrg 	  && DECL_NAME (TYPE_NAME (type))
    775  1.1  mrg 	  && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
    776  1.1  mrg 	return aarch64_scalar_builtin_types[i];
    777  1.1  mrg       i++;
    778  1.1  mrg     }
    779  1.1  mrg   return NULL;
    780  1.1  mrg }
    781  1.1  mrg 
    782  1.1  mrg static const char *
    783  1.1  mrg aarch64_mangle_builtin_vector_type (const_tree type)
    784  1.1  mrg {
    785  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (type);
    786  1.1  mrg   if (tree attr = lookup_attribute ("Advanced SIMD type", attrs))
    787  1.1  mrg     {
    788  1.1  mrg       tree mangled_name = TREE_VALUE (TREE_VALUE (attr));
    789  1.1  mrg       return IDENTIFIER_POINTER (mangled_name);
    790  1.1  mrg     }
    791  1.1  mrg 
    792  1.1  mrg   return NULL;
    793  1.1  mrg }
    794  1.1  mrg 
    795  1.1  mrg const char *
    796  1.1  mrg aarch64_general_mangle_builtin_type (const_tree type)
    797  1.1  mrg {
    798  1.1  mrg   const char *mangle;
    799  1.1  mrg   /* Walk through all the AArch64 builtins types tables to filter out the
    800  1.1  mrg      incoming type.  */
    801  1.1  mrg   if ((mangle = aarch64_mangle_builtin_vector_type (type))
    802  1.1  mrg       || (mangle = aarch64_mangle_builtin_scalar_type (type)))
    803  1.1  mrg     return mangle;
    804  1.1  mrg 
    805  1.1  mrg   return NULL;
    806  1.1  mrg }
    807  1.1  mrg 
    808  1.1  mrg static tree
    809  1.1  mrg aarch64_simd_builtin_std_type (machine_mode mode,
    810  1.1  mrg 			       enum aarch64_type_qualifiers q)
    811  1.1  mrg {
    812  1.1  mrg #define QUAL_TYPE(M)  \
    813  1.1  mrg   ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
    814  1.1  mrg   switch (mode)
    815  1.1  mrg     {
    816  1.1  mrg     case E_QImode:
    817  1.1  mrg       return QUAL_TYPE (QI);
    818  1.1  mrg     case E_HImode:
    819  1.1  mrg       return QUAL_TYPE (HI);
    820  1.1  mrg     case E_SImode:
    821  1.1  mrg       return QUAL_TYPE (SI);
    822  1.1  mrg     case E_DImode:
    823  1.1  mrg       return QUAL_TYPE (DI);
    824  1.1  mrg     case E_TImode:
    825  1.1  mrg       return QUAL_TYPE (TI);
    826  1.1  mrg     case E_OImode:
    827  1.1  mrg       return aarch64_simd_intOI_type_node;
    828  1.1  mrg     case E_CImode:
    829  1.1  mrg       return aarch64_simd_intCI_type_node;
    830  1.1  mrg     case E_XImode:
    831  1.1  mrg       return aarch64_simd_intXI_type_node;
    832  1.1  mrg     case E_HFmode:
    833  1.1  mrg       return aarch64_fp16_type_node;
    834  1.1  mrg     case E_SFmode:
    835  1.1  mrg       return float_type_node;
    836  1.1  mrg     case E_DFmode:
    837  1.1  mrg       return double_type_node;
    838  1.1  mrg     case E_BFmode:
    839  1.1  mrg       return aarch64_bf16_type_node;
    840  1.1  mrg     default:
    841  1.1  mrg       gcc_unreachable ();
    842  1.1  mrg     }
    843  1.1  mrg #undef QUAL_TYPE
    844  1.1  mrg }
    845  1.1  mrg 
    846  1.1  mrg static tree
    847  1.1  mrg aarch64_lookup_simd_builtin_type (machine_mode mode,
    848  1.1  mrg 				  enum aarch64_type_qualifiers q)
    849  1.1  mrg {
    850  1.1  mrg   int i;
    851  1.1  mrg   int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
    852  1.1  mrg 
    853  1.1  mrg   /* Non-poly scalar modes map to standard types not in the table.  */
    854  1.1  mrg   if (q != qualifier_poly && !VECTOR_MODE_P (mode))
    855  1.1  mrg     return aarch64_simd_builtin_std_type (mode, q);
    856  1.1  mrg 
    857  1.1  mrg   for (i = 0; i < nelts; i++)
    858  1.1  mrg     {
    859  1.1  mrg       if (aarch64_simd_types[i].mode == mode
    860  1.1  mrg 	  && aarch64_simd_types[i].q == q)
    861  1.1  mrg 	return aarch64_simd_types[i].itype;
    862  1.1  mrg       if (aarch64_simd_tuple_types[i][0] != NULL_TREE)
    863  1.1  mrg 	for (int j = 0; j < 3; j++)
    864  1.1  mrg 	  if (aarch64_simd_tuple_modes[i][j] == mode
    865  1.1  mrg 	      && aarch64_simd_types[i].q == q)
    866  1.1  mrg 	    return aarch64_simd_tuple_types[i][j];
    867  1.1  mrg     }
    868  1.1  mrg 
    869  1.1  mrg   return NULL_TREE;
    870  1.1  mrg }
    871  1.1  mrg 
    872  1.1  mrg static tree
    873  1.1  mrg aarch64_simd_builtin_type (machine_mode mode,
    874  1.1  mrg 			   bool unsigned_p, bool poly_p)
    875  1.1  mrg {
    876  1.1  mrg   if (poly_p)
    877  1.1  mrg     return aarch64_lookup_simd_builtin_type (mode, qualifier_poly);
    878  1.1  mrg   else if (unsigned_p)
    879  1.1  mrg     return aarch64_lookup_simd_builtin_type (mode, qualifier_unsigned);
    880  1.1  mrg   else
    881  1.1  mrg     return aarch64_lookup_simd_builtin_type (mode, qualifier_none);
    882  1.1  mrg }
    883  1.1  mrg 
    884  1.1  mrg static void
    885  1.1  mrg aarch64_init_simd_builtin_types (void)
    886  1.1  mrg {
    887  1.1  mrg   int i;
    888  1.1  mrg   int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
    889  1.1  mrg   tree tdecl;
    890  1.1  mrg 
    891  1.1  mrg   /* Init all the element types built by the front-end.  */
    892  1.1  mrg   aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
    893  1.1  mrg   aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
    894  1.1  mrg   aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
    895  1.1  mrg   aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
    896  1.1  mrg   aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
    897  1.1  mrg   aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
    898  1.1  mrg   aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
    899  1.1  mrg   aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
    900  1.1  mrg   aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
    901  1.1  mrg   aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
    902  1.1  mrg   aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
    903  1.1  mrg   aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
    904  1.1  mrg   aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
    905  1.1  mrg   aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
    906  1.1  mrg   aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
    907  1.1  mrg   aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
    908  1.1  mrg 
    909  1.1  mrg   /* Poly types are a world of their own.  */
    910  1.1  mrg   aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
    911  1.1  mrg     build_distinct_type_copy (unsigned_intQI_type_node);
    912  1.1  mrg   /* Prevent front-ends from transforming Poly8_t arrays into string
    913  1.1  mrg      literals.  */
    914  1.1  mrg   TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
    915  1.1  mrg 
    916  1.1  mrg   aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
    917  1.1  mrg     build_distinct_type_copy (unsigned_intHI_type_node);
    918  1.1  mrg   aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
    919  1.1  mrg     build_distinct_type_copy (unsigned_intDI_type_node);
    920  1.1  mrg   aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
    921  1.1  mrg     build_distinct_type_copy (unsigned_intTI_type_node);
    922  1.1  mrg   /* Init poly vector element types with scalar poly types.  */
    923  1.1  mrg   aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
    924  1.1  mrg   aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
    925  1.1  mrg   aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
    926  1.1  mrg   aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
    927  1.1  mrg   aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
    928  1.1  mrg   aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
    929  1.1  mrg 
    930  1.1  mrg   /* Continue with standard types.  */
    931  1.1  mrg   aarch64_simd_types[Float16x4_t].eltype = aarch64_fp16_type_node;
    932  1.1  mrg   aarch64_simd_types[Float16x8_t].eltype = aarch64_fp16_type_node;
    933  1.1  mrg   aarch64_simd_types[Float32x2_t].eltype = float_type_node;
    934  1.1  mrg   aarch64_simd_types[Float32x4_t].eltype = float_type_node;
    935  1.1  mrg   aarch64_simd_types[Float64x1_t].eltype = double_type_node;
    936  1.1  mrg   aarch64_simd_types[Float64x2_t].eltype = double_type_node;
    937  1.1  mrg 
    938  1.1  mrg   /* Init Bfloat vector types with underlying __bf16 type.  */
    939  1.1  mrg   aarch64_simd_types[Bfloat16x4_t].eltype = aarch64_bf16_type_node;
    940  1.1  mrg   aarch64_simd_types[Bfloat16x8_t].eltype = aarch64_bf16_type_node;
    941  1.1  mrg 
    942  1.1  mrg   for (i = 0; i < nelts; i++)
    943  1.1  mrg     {
    944  1.1  mrg       tree eltype = aarch64_simd_types[i].eltype;
    945  1.1  mrg       machine_mode mode = aarch64_simd_types[i].mode;
    946  1.1  mrg 
    947  1.1  mrg       if (aarch64_simd_types[i].itype == NULL)
    948  1.1  mrg 	{
    949  1.1  mrg 	  tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode));
    950  1.1  mrg 	  type = build_distinct_type_copy (type);
    951  1.1  mrg 	  SET_TYPE_STRUCTURAL_EQUALITY (type);
    952  1.1  mrg 
    953  1.1  mrg 	  tree mangled_name = get_identifier (aarch64_simd_types[i].mangle);
    954  1.1  mrg 	  tree value = tree_cons (NULL_TREE, mangled_name, NULL_TREE);
    955  1.1  mrg 	  TYPE_ATTRIBUTES (type)
    956  1.1  mrg 	    = tree_cons (get_identifier ("Advanced SIMD type"), value,
    957  1.1  mrg 			 TYPE_ATTRIBUTES (type));
    958  1.1  mrg 	  aarch64_simd_types[i].itype = type;
    959  1.1  mrg 	}
    960  1.1  mrg 
    961  1.1  mrg       tdecl = add_builtin_type (aarch64_simd_types[i].name,
    962  1.1  mrg 				aarch64_simd_types[i].itype);
    963  1.1  mrg       TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
    964  1.1  mrg     }
    965  1.1  mrg 
    966  1.1  mrg #define AARCH64_BUILD_SIGNED_TYPE(mode)  \
    967  1.1  mrg   make_signed_type (GET_MODE_PRECISION (mode));
    968  1.1  mrg   aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
    969  1.1  mrg   aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
    970  1.1  mrg   aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
    971  1.1  mrg #undef AARCH64_BUILD_SIGNED_TYPE
    972  1.1  mrg 
    973  1.1  mrg   tdecl = add_builtin_type
    974  1.1  mrg 	    ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
    975  1.1  mrg   TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
    976  1.1  mrg   tdecl = add_builtin_type
    977  1.1  mrg 	    ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
    978  1.1  mrg   TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
    979  1.1  mrg   tdecl = add_builtin_type
    980  1.1  mrg 	    ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
    981  1.1  mrg   TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
    982  1.1  mrg }
    983  1.1  mrg 
    984  1.1  mrg static void
    985  1.1  mrg aarch64_init_simd_builtin_scalar_types (void)
    986  1.1  mrg {
    987  1.1  mrg   /* Define typedefs for all the standard scalar types.  */
    988  1.1  mrg   (*lang_hooks.types.register_builtin_type) (intQI_type_node,
    989  1.1  mrg 					     "__builtin_aarch64_simd_qi");
    990  1.1  mrg   (*lang_hooks.types.register_builtin_type) (intHI_type_node,
    991  1.1  mrg 					     "__builtin_aarch64_simd_hi");
    992  1.1  mrg   (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node,
    993  1.1  mrg 					     "__builtin_aarch64_simd_hf");
    994  1.1  mrg   (*lang_hooks.types.register_builtin_type) (intSI_type_node,
    995  1.1  mrg 					     "__builtin_aarch64_simd_si");
    996  1.1  mrg   (*lang_hooks.types.register_builtin_type) (float_type_node,
    997  1.1  mrg 					     "__builtin_aarch64_simd_sf");
    998  1.1  mrg   (*lang_hooks.types.register_builtin_type) (intDI_type_node,
    999  1.1  mrg 					     "__builtin_aarch64_simd_di");
   1000  1.1  mrg   (*lang_hooks.types.register_builtin_type) (double_type_node,
   1001  1.1  mrg 					     "__builtin_aarch64_simd_df");
   1002  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
   1003  1.1  mrg 					     "__builtin_aarch64_simd_poly8");
   1004  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
   1005  1.1  mrg 					     "__builtin_aarch64_simd_poly16");
   1006  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
   1007  1.1  mrg 					     "__builtin_aarch64_simd_poly64");
   1008  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
   1009  1.1  mrg 					     "__builtin_aarch64_simd_poly128");
   1010  1.1  mrg   (*lang_hooks.types.register_builtin_type) (intTI_type_node,
   1011  1.1  mrg 					     "__builtin_aarch64_simd_ti");
   1012  1.1  mrg   (*lang_hooks.types.register_builtin_type) (aarch64_bf16_type_node,
   1013  1.1  mrg 					     "__builtin_aarch64_simd_bf");
   1014  1.1  mrg   /* Unsigned integer types for various mode sizes.  */
   1015  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
   1016  1.1  mrg 					     "__builtin_aarch64_simd_uqi");
   1017  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
   1018  1.1  mrg 					     "__builtin_aarch64_simd_uhi");
   1019  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
   1020  1.1  mrg 					     "__builtin_aarch64_simd_usi");
   1021  1.1  mrg   (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
   1022  1.1  mrg 					     "__builtin_aarch64_simd_udi");
   1023  1.1  mrg }
   1024  1.1  mrg 
   1025  1.1  mrg /* Return a set of FLAG_* flags derived from FLAGS
   1026  1.1  mrg    that describe what a function with result MODE could do,
   1027  1.1  mrg    taking the command-line flags into account.  */
   1028  1.1  mrg static unsigned int
   1029  1.1  mrg aarch64_call_properties (unsigned int flags, machine_mode mode)
   1030  1.1  mrg {
   1031  1.1  mrg   if (!(flags & FLAG_AUTO_FP) && FLOAT_MODE_P (mode))
   1032  1.1  mrg     flags |= FLAG_FP;
   1033  1.1  mrg 
   1034  1.1  mrg   /* -fno-trapping-math means that we can assume any FP exceptions
   1035  1.1  mrg      are not user-visible.  */
   1036  1.1  mrg   if (!flag_trapping_math)
   1037  1.1  mrg     flags &= ~FLAG_RAISE_FP_EXCEPTIONS;
   1038  1.1  mrg 
   1039  1.1  mrg   return flags;
   1040  1.1  mrg }
   1041  1.1  mrg 
   1042  1.1  mrg /* Return true if calls to a function with flags F and mode MODE
   1043  1.1  mrg    could modify some form of global state.  */
   1044  1.1  mrg static bool
   1045  1.1  mrg aarch64_modifies_global_state_p (unsigned int f, machine_mode mode)
   1046  1.1  mrg {
   1047  1.1  mrg   unsigned int flags = aarch64_call_properties (f, mode);
   1048  1.1  mrg 
   1049  1.1  mrg   if (flags & FLAG_RAISE_FP_EXCEPTIONS)
   1050  1.1  mrg     return true;
   1051  1.1  mrg 
   1052  1.1  mrg   if (flags & FLAG_PREFETCH_MEMORY)
   1053  1.1  mrg     return true;
   1054  1.1  mrg 
   1055  1.1  mrg   return flags & FLAG_WRITE_MEMORY;
   1056  1.1  mrg }
   1057  1.1  mrg 
   1058  1.1  mrg /* Return true if calls to a function with flags F and mode MODE
   1059  1.1  mrg    could read some form of global state.  */
   1060  1.1  mrg static bool
   1061  1.1  mrg aarch64_reads_global_state_p (unsigned int f, machine_mode mode)
   1062  1.1  mrg {
   1063  1.1  mrg   unsigned int flags = aarch64_call_properties (f,  mode);
   1064  1.1  mrg 
   1065  1.1  mrg   if (flags & FLAG_READ_FPCR)
   1066  1.1  mrg     return true;
   1067  1.1  mrg 
   1068  1.1  mrg   return flags & FLAG_READ_MEMORY;
   1069  1.1  mrg }
   1070  1.1  mrg 
   1071  1.1  mrg /* Return true if calls to a function with flags F and mode MODE
   1072  1.1  mrg    could raise a signal.  */
   1073  1.1  mrg static bool
   1074  1.1  mrg aarch64_could_trap_p (unsigned int f, machine_mode mode)
   1075  1.1  mrg {
   1076  1.1  mrg   unsigned int flags = aarch64_call_properties (f, mode);
   1077  1.1  mrg 
   1078  1.1  mrg   if (flags & FLAG_RAISE_FP_EXCEPTIONS)
   1079  1.1  mrg     return true;
   1080  1.1  mrg 
   1081  1.1  mrg   if (flags & (FLAG_READ_MEMORY | FLAG_WRITE_MEMORY))
   1082  1.1  mrg     return true;
   1083  1.1  mrg 
   1084  1.1  mrg   return false;
   1085  1.1  mrg }
   1086  1.1  mrg 
   1087  1.1  mrg /* Add attribute NAME to ATTRS.  */
   1088  1.1  mrg static tree
   1089  1.1  mrg aarch64_add_attribute (const char *name, tree attrs)
   1090  1.1  mrg {
   1091  1.1  mrg   return tree_cons (get_identifier (name), NULL_TREE, attrs);
   1092  1.1  mrg }
   1093  1.1  mrg 
   1094  1.1  mrg /* Return the appropriate attributes for a function that has
   1095  1.1  mrg    flags F and mode MODE.  */
   1096  1.1  mrg static tree
   1097  1.1  mrg aarch64_get_attributes (unsigned int f, machine_mode mode)
   1098  1.1  mrg {
   1099  1.1  mrg   tree attrs = NULL_TREE;
   1100  1.1  mrg 
   1101  1.1  mrg   if (!aarch64_modifies_global_state_p (f, mode))
   1102  1.1  mrg     {
   1103  1.1  mrg       if (aarch64_reads_global_state_p (f, mode))
   1104  1.1  mrg 	attrs = aarch64_add_attribute ("pure", attrs);
   1105  1.1  mrg       else
   1106  1.1  mrg 	attrs = aarch64_add_attribute ("const", attrs);
   1107  1.1  mrg     }
   1108  1.1  mrg 
   1109  1.1  mrg   if (!flag_non_call_exceptions || !aarch64_could_trap_p (f, mode))
   1110  1.1  mrg     attrs = aarch64_add_attribute ("nothrow", attrs);
   1111  1.1  mrg 
   1112  1.1  mrg   return aarch64_add_attribute ("leaf", attrs);
   1113  1.1  mrg }
   1114  1.1  mrg 
   1115  1.1  mrg static bool aarch64_simd_builtins_initialized_p = false;
   1116  1.1  mrg 
   1117  1.1  mrg /* Due to the architecture not providing lane variant of the lane instructions
   1118  1.1  mrg    for fcmla we can't use the standard simd builtin expansion code, but we
   1119  1.1  mrg    still want the majority of the validation that would normally be done.  */
   1120  1.1  mrg 
   1121  1.1  mrg void
   1122  1.1  mrg aarch64_init_fcmla_laneq_builtins (void)
   1123  1.1  mrg {
   1124  1.1  mrg   unsigned int i = 0;
   1125  1.1  mrg 
   1126  1.1  mrg   for (i = 0; i < ARRAY_SIZE (aarch64_fcmla_lane_builtin_data); ++i)
   1127  1.1  mrg     {
   1128  1.1  mrg       aarch64_fcmla_laneq_builtin_datum* d
   1129  1.1  mrg 	= &aarch64_fcmla_lane_builtin_data[i];
   1130  1.1  mrg       tree argtype = aarch64_lookup_simd_builtin_type (d->mode, qualifier_none);
   1131  1.1  mrg       machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
   1132  1.1  mrg       tree quadtype
   1133  1.1  mrg 	= aarch64_lookup_simd_builtin_type (quadmode, qualifier_none);
   1134  1.1  mrg       tree lanetype
   1135  1.1  mrg 	= aarch64_simd_builtin_std_type (SImode, qualifier_lane_pair_index);
   1136  1.1  mrg       tree ftype = build_function_type_list (argtype, argtype, argtype,
   1137  1.1  mrg 					     quadtype, lanetype, NULL_TREE);
   1138  1.1  mrg       tree attrs = aarch64_get_attributes (FLAG_FP, d->mode);
   1139  1.1  mrg       tree fndecl
   1140  1.1  mrg 	= aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
   1141  1.1  mrg 
   1142  1.1  mrg       aarch64_builtin_decls[d->fcode] = fndecl;
   1143  1.1  mrg     }
   1144  1.1  mrg }
   1145  1.1  mrg 
   1146  1.1  mrg void
   1147  1.1  mrg aarch64_init_simd_builtin_functions (bool called_from_pragma)
   1148  1.1  mrg {
   1149  1.1  mrg   unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
   1150  1.1  mrg 
   1151  1.1  mrg   if (!called_from_pragma)
   1152  1.1  mrg     {
   1153  1.1  mrg       tree lane_check_fpr = build_function_type_list (void_type_node,
   1154  1.1  mrg 						      size_type_node,
   1155  1.1  mrg 						      size_type_node,
   1156  1.1  mrg 						      intSI_type_node,
   1157  1.1  mrg 						      NULL);
   1158  1.1  mrg       aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK]
   1159  1.1  mrg 	= aarch64_general_add_builtin ("__builtin_aarch64_im_lane_boundsi",
   1160  1.1  mrg 				       lane_check_fpr,
   1161  1.1  mrg 				       AARCH64_SIMD_BUILTIN_LANE_CHECK);
   1162  1.1  mrg     }
   1163  1.1  mrg 
   1164  1.1  mrg   for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
   1165  1.1  mrg     {
   1166  1.1  mrg       bool print_type_signature_p = false;
   1167  1.1  mrg       char type_signature[SIMD_MAX_BUILTIN_ARGS + 1] = { 0 };
   1168  1.1  mrg       aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
   1169  1.1  mrg       char namebuf[60];
   1170  1.1  mrg       tree ftype = NULL;
   1171  1.1  mrg       tree fndecl = NULL;
   1172  1.1  mrg 
   1173  1.1  mrg       d->fcode = fcode;
   1174  1.1  mrg 
   1175  1.1  mrg       /* We must track two variables here.  op_num is
   1176  1.1  mrg 	 the operand number as in the RTL pattern.  This is
   1177  1.1  mrg 	 required to access the mode (e.g. V4SF mode) of the
   1178  1.1  mrg 	 argument, from which the base type can be derived.
   1179  1.1  mrg 	 arg_num is an index in to the qualifiers data, which
   1180  1.1  mrg 	 gives qualifiers to the type (e.g. const unsigned).
   1181  1.1  mrg 	 The reason these two variables may differ by one is the
   1182  1.1  mrg 	 void return type.  While all return types take the 0th entry
   1183  1.1  mrg 	 in the qualifiers array, there is no operand for them in the
   1184  1.1  mrg 	 RTL pattern.  */
   1185  1.1  mrg       int op_num = insn_data[d->code].n_operands - 1;
   1186  1.1  mrg       int arg_num = d->qualifiers[0] & qualifier_void
   1187  1.1  mrg 		      ? op_num + 1
   1188  1.1  mrg 		      : op_num;
   1189  1.1  mrg       tree return_type = void_type_node, args = void_list_node;
   1190  1.1  mrg       tree eltype;
   1191  1.1  mrg 
   1192  1.1  mrg       int struct_mode_args = 0;
   1193  1.1  mrg       for (int j = op_num; j >= 0; j--)
   1194  1.1  mrg 	{
   1195  1.1  mrg 	  machine_mode op_mode = insn_data[d->code].operand[j].mode;
   1196  1.1  mrg 	  if (aarch64_advsimd_struct_mode_p (op_mode))
   1197  1.1  mrg 	    struct_mode_args++;
   1198  1.1  mrg 	}
   1199  1.1  mrg 
   1200  1.1  mrg       if ((called_from_pragma && struct_mode_args == 0)
   1201  1.1  mrg 	  || (!called_from_pragma && struct_mode_args > 0))
   1202  1.1  mrg 	continue;
   1203  1.1  mrg 
   1204  1.1  mrg       /* Build a function type directly from the insn_data for this
   1205  1.1  mrg 	 builtin.  The build_function_type () function takes care of
   1206  1.1  mrg 	 removing duplicates for us.  */
   1207  1.1  mrg       for (; op_num >= 0; arg_num--, op_num--)
   1208  1.1  mrg 	{
   1209  1.1  mrg 	  machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
   1210  1.1  mrg 	  enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
   1211  1.1  mrg 
   1212  1.1  mrg 	  if (qualifiers & qualifier_unsigned)
   1213  1.1  mrg 	    {
   1214  1.1  mrg 	      type_signature[op_num] = 'u';
   1215  1.1  mrg 	      print_type_signature_p = true;
   1216  1.1  mrg 	    }
   1217  1.1  mrg 	  else if (qualifiers & qualifier_poly)
   1218  1.1  mrg 	    {
   1219  1.1  mrg 	      type_signature[op_num] = 'p';
   1220  1.1  mrg 	      print_type_signature_p = true;
   1221  1.1  mrg 	    }
   1222  1.1  mrg 	  else
   1223  1.1  mrg 	    type_signature[op_num] = 's';
   1224  1.1  mrg 
   1225  1.1  mrg 	  /* Skip an internal operand for vget_{low, high}.  */
   1226  1.1  mrg 	  if (qualifiers & qualifier_internal)
   1227  1.1  mrg 	    continue;
   1228  1.1  mrg 
   1229  1.1  mrg 	  /* Some builtins have different user-facing types
   1230  1.1  mrg 	     for certain arguments, encoded in d->mode.  */
   1231  1.1  mrg 	  if (qualifiers & qualifier_map_mode)
   1232  1.1  mrg 	      op_mode = d->mode;
   1233  1.1  mrg 
   1234  1.1  mrg 	  /* For pointers, we want a pointer to the basic type
   1235  1.1  mrg 	     of the vector.  */
   1236  1.1  mrg 	  if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
   1237  1.1  mrg 	    op_mode = GET_MODE_INNER (op_mode);
   1238  1.1  mrg 
   1239  1.1  mrg 	  eltype = aarch64_simd_builtin_type
   1240  1.1  mrg 		     (op_mode,
   1241  1.1  mrg 		      (qualifiers & qualifier_unsigned) != 0,
   1242  1.1  mrg 		      (qualifiers & qualifier_poly) != 0);
   1243  1.1  mrg 	  gcc_assert (eltype != NULL);
   1244  1.1  mrg 
   1245  1.1  mrg 	  /* Add qualifiers.  */
   1246  1.1  mrg 	  if (qualifiers & qualifier_const)
   1247  1.1  mrg 	    eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
   1248  1.1  mrg 
   1249  1.1  mrg 	  if (qualifiers & qualifier_pointer)
   1250  1.1  mrg 	      eltype = build_pointer_type (eltype);
   1251  1.1  mrg 
   1252  1.1  mrg 	  /* If we have reached arg_num == 0, we are at a non-void
   1253  1.1  mrg 	     return type.  Otherwise, we are still processing
   1254  1.1  mrg 	     arguments.  */
   1255  1.1  mrg 	  if (arg_num == 0)
   1256  1.1  mrg 	    return_type = eltype;
   1257  1.1  mrg 	  else
   1258  1.1  mrg 	    args = tree_cons (NULL_TREE, eltype, args);
   1259  1.1  mrg 	}
   1260  1.1  mrg 
   1261  1.1  mrg       ftype = build_function_type (return_type, args);
   1262  1.1  mrg 
   1263  1.1  mrg       gcc_assert (ftype != NULL);
   1264  1.1  mrg 
   1265  1.1  mrg       if (print_type_signature_p)
   1266  1.1  mrg 	snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
   1267  1.1  mrg 		  d->name, type_signature);
   1268  1.1  mrg       else
   1269  1.1  mrg 	snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
   1270  1.1  mrg 		  d->name);
   1271  1.1  mrg 
   1272  1.1  mrg       tree attrs = aarch64_get_attributes (d->flags, d->mode);
   1273  1.1  mrg 
   1274  1.1  mrg       if (called_from_pragma)
   1275  1.1  mrg 	{
   1276  1.1  mrg 	  unsigned int raw_code
   1277  1.1  mrg 		= (fcode << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
   1278  1.1  mrg 	  fndecl = simulate_builtin_function_decl (input_location, namebuf,
   1279  1.1  mrg 						   ftype, raw_code, NULL,
   1280  1.1  mrg 						   attrs);
   1281  1.1  mrg 	}
   1282  1.1  mrg       else
   1283  1.1  mrg 	fndecl = aarch64_general_add_builtin (namebuf, ftype, fcode, attrs);
   1284  1.1  mrg 
   1285  1.1  mrg       aarch64_builtin_decls[fcode] = fndecl;
   1286  1.1  mrg     }
   1287  1.1  mrg }
   1288  1.1  mrg 
   1289  1.1  mrg /* Register the tuple type that contains NUM_VECTORS of the AdvSIMD type
   1290  1.1  mrg    indexed by TYPE_INDEX.  */
   1291  1.1  mrg static void
   1292  1.1  mrg register_tuple_type (unsigned int num_vectors, unsigned int type_index)
   1293  1.1  mrg {
   1294  1.1  mrg   aarch64_simd_type_info *type = &aarch64_simd_types[type_index];
   1295  1.1  mrg 
   1296  1.1  mrg   /* Synthesize the name of the user-visible vector tuple type.  */
   1297  1.1  mrg   const char *vector_type_name = type->name;
   1298  1.1  mrg   char tuple_type_name[sizeof ("bfloat16x4x2_t")];
   1299  1.1  mrg   snprintf (tuple_type_name, sizeof (tuple_type_name), "%.*sx%d_t",
   1300  1.1  mrg 	    (int) strlen (vector_type_name) - 4, vector_type_name + 2,
   1301  1.1  mrg 	    num_vectors);
   1302  1.1  mrg   tuple_type_name[0] = TOLOWER (tuple_type_name[0]);
   1303  1.1  mrg 
   1304  1.1  mrg   tree vector_type = type->itype;
   1305  1.1  mrg   tree array_type = build_array_type_nelts (vector_type, num_vectors);
   1306  1.1  mrg   if (type->mode == DImode)
   1307  1.1  mrg     {
   1308  1.1  mrg       if (num_vectors == 2)
   1309  1.1  mrg 	SET_TYPE_MODE (array_type, V2x1DImode);
   1310  1.1  mrg       else if (num_vectors == 3)
   1311  1.1  mrg 	SET_TYPE_MODE (array_type, V3x1DImode);
   1312  1.1  mrg       else if (num_vectors == 4)
   1313  1.1  mrg 	SET_TYPE_MODE (array_type, V4x1DImode);
   1314  1.1  mrg     }
   1315  1.1  mrg 
   1316  1.1  mrg   unsigned int alignment
   1317  1.1  mrg     = known_eq (GET_MODE_SIZE (type->mode), 16) ? 128 : 64;
   1318  1.1  mrg   machine_mode tuple_mode = TYPE_MODE_RAW (array_type);
   1319  1.1  mrg   gcc_assert (VECTOR_MODE_P (tuple_mode)
   1320  1.1  mrg 	      && TYPE_MODE (array_type) == tuple_mode
   1321  1.1  mrg 	      && TYPE_ALIGN (array_type) == alignment);
   1322  1.1  mrg 
   1323  1.1  mrg   tree field = build_decl (input_location, FIELD_DECL,
   1324  1.1  mrg 			   get_identifier ("val"), array_type);
   1325  1.1  mrg 
   1326  1.1  mrg   tree t = lang_hooks.types.simulate_record_decl (input_location,
   1327  1.1  mrg 						  tuple_type_name,
   1328  1.1  mrg 						  make_array_slice (&field,
   1329  1.1  mrg 								    1));
   1330  1.1  mrg   gcc_assert (TYPE_MODE_RAW (t) == TYPE_MODE (t)
   1331  1.1  mrg 	      && (flag_pack_struct
   1332  1.1  mrg 		  || maximum_field_alignment
   1333  1.1  mrg 		  || (TYPE_MODE_RAW (t) == tuple_mode
   1334  1.1  mrg 		      && TYPE_ALIGN (t) == alignment)));
   1335  1.1  mrg 
   1336  1.1  mrg   aarch64_simd_tuple_modes[type_index][num_vectors - 2] = tuple_mode;
   1337  1.1  mrg   aarch64_simd_tuple_types[type_index][num_vectors - 2] = t;
   1338  1.1  mrg }
   1339  1.1  mrg 
   1340  1.1  mrg static bool
   1341  1.1  mrg aarch64_scalar_builtin_type_p (aarch64_simd_type t)
   1342  1.1  mrg {
   1343  1.1  mrg   return (t == Poly8_t || t == Poly16_t || t == Poly64_t || t == Poly128_t);
   1344  1.1  mrg }
   1345  1.1  mrg 
   1346  1.1  mrg /* Enable AARCH64_FL_* flags EXTRA_FLAGS on top of the base Advanced SIMD
   1347  1.1  mrg    set.  */
   1348  1.1  mrg aarch64_simd_switcher::aarch64_simd_switcher (unsigned int extra_flags)
   1349  1.1  mrg   : m_old_isa_flags (aarch64_isa_flags),
   1350  1.1  mrg     m_old_general_regs_only (TARGET_GENERAL_REGS_ONLY)
   1351  1.1  mrg {
   1352  1.1  mrg   /* Changing the ISA flags should be enough here.  We shouldn't need to
   1353  1.1  mrg      pay the compile-time cost of a full target switch.  */
   1354  1.1  mrg   aarch64_isa_flags = AARCH64_FL_FP | AARCH64_FL_SIMD | extra_flags;
   1355  1.1  mrg   global_options.x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
   1356  1.1  mrg }
   1357  1.1  mrg 
   1358  1.1  mrg aarch64_simd_switcher::~aarch64_simd_switcher ()
   1359  1.1  mrg {
   1360  1.1  mrg   if (m_old_general_regs_only)
   1361  1.1  mrg     global_options.x_target_flags |= MASK_GENERAL_REGS_ONLY;
   1362  1.1  mrg   aarch64_isa_flags = m_old_isa_flags;
   1363  1.1  mrg }
   1364  1.1  mrg 
   1365  1.1  mrg /* Implement #pragma GCC aarch64 "arm_neon.h".  */
   1366  1.1  mrg void
   1367  1.1  mrg handle_arm_neon_h (void)
   1368  1.1  mrg {
   1369  1.1  mrg   aarch64_simd_switcher simd;
   1370  1.1  mrg 
   1371  1.1  mrg   /* Register the AdvSIMD vector tuple types.  */
   1372  1.1  mrg   for (unsigned int i = 0; i < ARM_NEON_H_TYPES_LAST; i++)
   1373  1.1  mrg     for (unsigned int count = 2; count <= 4; ++count)
   1374  1.1  mrg       if (!aarch64_scalar_builtin_type_p (aarch64_simd_types[i].type))
   1375  1.1  mrg 	register_tuple_type (count, i);
   1376  1.1  mrg 
   1377  1.1  mrg   aarch64_init_simd_builtin_functions (true);
   1378  1.1  mrg }
   1379  1.1  mrg 
   1380  1.1  mrg void
   1381  1.1  mrg aarch64_init_simd_builtins (void)
   1382  1.1  mrg {
   1383  1.1  mrg   if (aarch64_simd_builtins_initialized_p)
   1384  1.1  mrg     return;
   1385  1.1  mrg 
   1386  1.1  mrg   aarch64_simd_builtins_initialized_p = true;
   1387  1.1  mrg 
   1388  1.1  mrg   aarch64_init_simd_builtin_types ();
   1389  1.1  mrg 
   1390  1.1  mrg   /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
   1391  1.1  mrg      Therefore we need to preserve the old __builtin scalar types.  It can be
   1392  1.1  mrg      removed once all the intrinsics become strongly typed using the qualifier
   1393  1.1  mrg      system.  */
   1394  1.1  mrg   aarch64_init_simd_builtin_scalar_types ();
   1395  1.1  mrg 
   1396  1.1  mrg   aarch64_init_simd_builtin_functions (false);
   1397  1.1  mrg   if (in_lto_p)
   1398  1.1  mrg     handle_arm_neon_h ();
   1399  1.1  mrg 
   1400  1.1  mrg   /* Initialize the remaining fcmla_laneq intrinsics.  */
   1401  1.1  mrg   aarch64_init_fcmla_laneq_builtins ();
   1402  1.1  mrg }
   1403  1.1  mrg 
   1404  1.1  mrg static void
   1405  1.1  mrg aarch64_init_crc32_builtins ()
   1406  1.1  mrg {
   1407  1.1  mrg   tree usi_type = aarch64_simd_builtin_std_type (SImode, qualifier_unsigned);
   1408  1.1  mrg   unsigned int i = 0;
   1409  1.1  mrg 
   1410  1.1  mrg   for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
   1411  1.1  mrg     {
   1412  1.1  mrg       aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
   1413  1.1  mrg       tree argtype = aarch64_simd_builtin_std_type (d->mode,
   1414  1.1  mrg 						    qualifier_unsigned);
   1415  1.1  mrg       tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
   1416  1.1  mrg       tree attrs = aarch64_get_attributes (FLAG_NONE, d->mode);
   1417  1.1  mrg       tree fndecl
   1418  1.1  mrg 	= aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
   1419  1.1  mrg 
   1420  1.1  mrg       aarch64_builtin_decls[d->fcode] = fndecl;
   1421  1.1  mrg     }
   1422  1.1  mrg }
   1423  1.1  mrg 
   1424  1.1  mrg /* Add builtins for reciprocal square root.  */
   1425  1.1  mrg 
   1426  1.1  mrg void
   1427  1.1  mrg aarch64_init_builtin_rsqrt (void)
   1428  1.1  mrg {
   1429  1.1  mrg   tree fndecl = NULL;
   1430  1.1  mrg   tree ftype = NULL;
   1431  1.1  mrg 
   1432  1.1  mrg   tree V2SF_type_node = build_vector_type (float_type_node, 2);
   1433  1.1  mrg   tree V2DF_type_node = build_vector_type (double_type_node, 2);
   1434  1.1  mrg   tree V4SF_type_node = build_vector_type (float_type_node, 4);
   1435  1.1  mrg 
   1436  1.1  mrg   struct builtin_decls_data
   1437  1.1  mrg   {
   1438  1.1  mrg     tree type_node;
   1439  1.1  mrg     const char *builtin_name;
   1440  1.1  mrg     int function_code;
   1441  1.1  mrg   };
   1442  1.1  mrg 
   1443  1.1  mrg   builtin_decls_data bdda[] =
   1444  1.1  mrg   {
   1445  1.1  mrg     { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
   1446  1.1  mrg     { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
   1447  1.1  mrg     { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
   1448  1.1  mrg     { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
   1449  1.1  mrg     { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
   1450  1.1  mrg   };
   1451  1.1  mrg 
   1452  1.1  mrg   builtin_decls_data *bdd = bdda;
   1453  1.1  mrg   builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data));
   1454  1.1  mrg 
   1455  1.1  mrg   for (; bdd < bdd_end; bdd++)
   1456  1.1  mrg   {
   1457  1.1  mrg     ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
   1458  1.1  mrg     tree attrs = aarch64_get_attributes (FLAG_FP, TYPE_MODE (bdd->type_node));
   1459  1.1  mrg     fndecl = aarch64_general_add_builtin (bdd->builtin_name,
   1460  1.1  mrg 					  ftype, bdd->function_code, attrs);
   1461  1.1  mrg     aarch64_builtin_decls[bdd->function_code] = fndecl;
   1462  1.1  mrg   }
   1463  1.1  mrg }
   1464  1.1  mrg 
   1465  1.1  mrg /* Initialize the backend types that support the user-visible __fp16
   1466  1.1  mrg    type, also initialize a pointer to that type, to be used when
   1467  1.1  mrg    forming HFAs.  */
   1468  1.1  mrg 
   1469  1.1  mrg static void
   1470  1.1  mrg aarch64_init_fp16_types (void)
   1471  1.1  mrg {
   1472  1.1  mrg   aarch64_fp16_type_node = make_node (REAL_TYPE);
   1473  1.1  mrg   TYPE_PRECISION (aarch64_fp16_type_node) = 16;
   1474  1.1  mrg   layout_type (aarch64_fp16_type_node);
   1475  1.1  mrg 
   1476  1.1  mrg   (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node, "__fp16");
   1477  1.1  mrg   aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
   1478  1.1  mrg }
   1479  1.1  mrg 
   1480  1.1  mrg /* Initialize the backend REAL_TYPE type supporting bfloat types.  */
   1481  1.1  mrg static void
   1482  1.1  mrg aarch64_init_bf16_types (void)
   1483  1.1  mrg {
   1484  1.1  mrg   aarch64_bf16_type_node = make_node (REAL_TYPE);
   1485  1.1  mrg   TYPE_PRECISION (aarch64_bf16_type_node) = 16;
   1486  1.1  mrg   SET_TYPE_MODE (aarch64_bf16_type_node, BFmode);
   1487  1.1  mrg   layout_type (aarch64_bf16_type_node);
   1488  1.1  mrg 
   1489  1.1  mrg   lang_hooks.types.register_builtin_type (aarch64_bf16_type_node, "__bf16");
   1490  1.1  mrg   aarch64_bf16_ptr_type_node = build_pointer_type (aarch64_bf16_type_node);
   1491  1.1  mrg }
   1492  1.1  mrg 
   1493  1.1  mrg /* Pointer authentication builtins that will become NOP on legacy platform.
   1494  1.1  mrg    Currently, these builtins are for internal use only (libgcc EH unwinder).  */
   1495  1.1  mrg 
   1496  1.1  mrg void
   1497  1.1  mrg aarch64_init_pauth_hint_builtins (void)
   1498  1.1  mrg {
   1499  1.1  mrg   /* Pointer Authentication builtins.  */
   1500  1.1  mrg   tree ftype_pointer_auth
   1501  1.1  mrg     = build_function_type_list (ptr_type_node, ptr_type_node,
   1502  1.1  mrg 				unsigned_intDI_type_node, NULL_TREE);
   1503  1.1  mrg   tree ftype_pointer_strip
   1504  1.1  mrg     = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
   1505  1.1  mrg 
   1506  1.1  mrg   aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
   1507  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_autia1716",
   1508  1.1  mrg 				   ftype_pointer_auth,
   1509  1.1  mrg 				   AARCH64_PAUTH_BUILTIN_AUTIA1716);
   1510  1.1  mrg   aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
   1511  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_pacia1716",
   1512  1.1  mrg 				   ftype_pointer_auth,
   1513  1.1  mrg 				   AARCH64_PAUTH_BUILTIN_PACIA1716);
   1514  1.1  mrg   aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
   1515  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_autib1716",
   1516  1.1  mrg 				   ftype_pointer_auth,
   1517  1.1  mrg 				   AARCH64_PAUTH_BUILTIN_AUTIB1716);
   1518  1.1  mrg   aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
   1519  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_pacib1716",
   1520  1.1  mrg 				   ftype_pointer_auth,
   1521  1.1  mrg 				   AARCH64_PAUTH_BUILTIN_PACIB1716);
   1522  1.1  mrg   aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
   1523  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_xpaclri",
   1524  1.1  mrg 				   ftype_pointer_strip,
   1525  1.1  mrg 				   AARCH64_PAUTH_BUILTIN_XPACLRI);
   1526  1.1  mrg }
   1527  1.1  mrg 
   1528  1.1  mrg /* Initialize the transactional memory extension (TME) builtins.  */
   1529  1.1  mrg static void
   1530  1.1  mrg aarch64_init_tme_builtins (void)
   1531  1.1  mrg {
   1532  1.1  mrg   tree ftype_uint64_void
   1533  1.1  mrg     = build_function_type_list (uint64_type_node, NULL);
   1534  1.1  mrg   tree ftype_void_void
   1535  1.1  mrg     = build_function_type_list (void_type_node, NULL);
   1536  1.1  mrg   tree ftype_void_uint64
   1537  1.1  mrg     = build_function_type_list (void_type_node, uint64_type_node, NULL);
   1538  1.1  mrg 
   1539  1.1  mrg   aarch64_builtin_decls[AARCH64_TME_BUILTIN_TSTART]
   1540  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_tstart",
   1541  1.1  mrg 				   ftype_uint64_void,
   1542  1.1  mrg 				   AARCH64_TME_BUILTIN_TSTART);
   1543  1.1  mrg   aarch64_builtin_decls[AARCH64_TME_BUILTIN_TTEST]
   1544  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_ttest",
   1545  1.1  mrg 				   ftype_uint64_void,
   1546  1.1  mrg 				   AARCH64_TME_BUILTIN_TTEST);
   1547  1.1  mrg   aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCOMMIT]
   1548  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_tcommit",
   1549  1.1  mrg 				   ftype_void_void,
   1550  1.1  mrg 				   AARCH64_TME_BUILTIN_TCOMMIT);
   1551  1.1  mrg   aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCANCEL]
   1552  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_tcancel",
   1553  1.1  mrg 				   ftype_void_uint64,
   1554  1.1  mrg 				   AARCH64_TME_BUILTIN_TCANCEL);
   1555  1.1  mrg }
   1556  1.1  mrg 
   1557  1.1  mrg /* Add builtins for Random Number instructions.  */
   1558  1.1  mrg 
   1559  1.1  mrg static void
   1560  1.1  mrg aarch64_init_rng_builtins (void)
   1561  1.1  mrg {
   1562  1.1  mrg   tree unsigned_ptr_type = build_pointer_type (unsigned_intDI_type_node);
   1563  1.1  mrg   tree ftype
   1564  1.1  mrg     = build_function_type_list (integer_type_node, unsigned_ptr_type, NULL);
   1565  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDR]
   1566  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype,
   1567  1.1  mrg 				   AARCH64_BUILTIN_RNG_RNDR);
   1568  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
   1569  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype,
   1570  1.1  mrg 				   AARCH64_BUILTIN_RNG_RNDRRS);
   1571  1.1  mrg }
   1572  1.1  mrg 
   1573  1.1  mrg /* Initialize the memory tagging extension (MTE) builtins.  */
   1574  1.1  mrg struct aarch64_mte
   1575  1.1  mrg {
   1576  1.1  mrg   tree ftype;
   1577  1.1  mrg   enum insn_code icode;
   1578  1.1  mrg } aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_END -
   1579  1.1  mrg 			      AARCH64_MEMTAG_BUILTIN_START - 1];
   1580  1.1  mrg 
   1581  1.1  mrg static void
   1582  1.1  mrg aarch64_init_memtag_builtins (void)
   1583  1.1  mrg {
   1584  1.1  mrg   tree fntype = NULL;
   1585  1.1  mrg 
   1586  1.1  mrg #define AARCH64_INIT_MEMTAG_BUILTINS_DECL(F, N, I, T) \
   1587  1.1  mrg   aarch64_builtin_decls[AARCH64_MEMTAG_BUILTIN_##F] \
   1588  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_memtag_"#N, \
   1589  1.1  mrg 				   T, AARCH64_MEMTAG_BUILTIN_##F); \
   1590  1.1  mrg   aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_##F - \
   1591  1.1  mrg 			      AARCH64_MEMTAG_BUILTIN_START - 1] = \
   1592  1.1  mrg 				{T, CODE_FOR_##I};
   1593  1.1  mrg 
   1594  1.1  mrg   fntype = build_function_type_list (ptr_type_node, ptr_type_node,
   1595  1.1  mrg 				     uint64_type_node, NULL);
   1596  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (IRG, irg, irg, fntype);
   1597  1.1  mrg 
   1598  1.1  mrg   fntype = build_function_type_list (uint64_type_node, ptr_type_node,
   1599  1.1  mrg 				     uint64_type_node, NULL);
   1600  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (GMI, gmi, gmi, fntype);
   1601  1.1  mrg 
   1602  1.1  mrg   fntype = build_function_type_list (ptrdiff_type_node, ptr_type_node,
   1603  1.1  mrg 				     ptr_type_node, NULL);
   1604  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (SUBP, subp, subp, fntype);
   1605  1.1  mrg 
   1606  1.1  mrg   fntype = build_function_type_list (ptr_type_node, ptr_type_node,
   1607  1.1  mrg 				     unsigned_type_node, NULL);
   1608  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (INC_TAG, inc_tag, addg, fntype);
   1609  1.1  mrg 
   1610  1.1  mrg   fntype = build_function_type_list (void_type_node, ptr_type_node, NULL);
   1611  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (SET_TAG, set_tag, stg, fntype);
   1612  1.1  mrg 
   1613  1.1  mrg   fntype = build_function_type_list (ptr_type_node, ptr_type_node, NULL);
   1614  1.1  mrg   AARCH64_INIT_MEMTAG_BUILTINS_DECL (GET_TAG, get_tag, ldg, fntype);
   1615  1.1  mrg 
   1616  1.1  mrg #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
   1617  1.1  mrg }
   1618  1.1  mrg 
   1619  1.1  mrg /* Add builtins for Load/store 64 Byte instructions.  */
   1620  1.1  mrg 
   1621  1.1  mrg typedef struct
   1622  1.1  mrg {
   1623  1.1  mrg   const char *name;
   1624  1.1  mrg   unsigned int code;
   1625  1.1  mrg   tree type;
   1626  1.1  mrg } ls64_builtins_data;
   1627  1.1  mrg 
   1628  1.1  mrg static GTY(()) tree ls64_arm_data_t = NULL_TREE;
   1629  1.1  mrg 
   1630  1.1  mrg static void
   1631  1.1  mrg aarch64_init_ls64_builtins_types (void)
   1632  1.1  mrg {
   1633  1.1  mrg   /* Synthesize:
   1634  1.1  mrg 
   1635  1.1  mrg      typedef struct {
   1636  1.1  mrg        uint64_t val[8];
   1637  1.1  mrg      } __arm_data512_t;  */
   1638  1.1  mrg   const char *tuple_type_name = "__arm_data512_t";
   1639  1.1  mrg   tree node_type = get_typenode_from_name (UINT64_TYPE);
   1640  1.1  mrg   tree array_type = build_array_type_nelts (node_type, 8);
   1641  1.1  mrg   SET_TYPE_MODE (array_type, V8DImode);
   1642  1.1  mrg 
   1643  1.1  mrg   gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type));
   1644  1.1  mrg   gcc_assert (TYPE_ALIGN (array_type) == 64);
   1645  1.1  mrg 
   1646  1.1  mrg   tree field = build_decl (input_location, FIELD_DECL,
   1647  1.1  mrg 			   get_identifier ("val"), array_type);
   1648  1.1  mrg 
   1649  1.1  mrg   ls64_arm_data_t = lang_hooks.types.simulate_record_decl (input_location,
   1650  1.1  mrg 			 tuple_type_name,
   1651  1.1  mrg 			 make_array_slice (&field, 1));
   1652  1.1  mrg 
   1653  1.1  mrg   gcc_assert (TYPE_MODE (ls64_arm_data_t) == V8DImode);
   1654  1.1  mrg   gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t));
   1655  1.1  mrg   gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == 64);
   1656  1.1  mrg }
   1657  1.1  mrg 
   1658  1.1  mrg static void
   1659  1.1  mrg aarch64_init_ls64_builtins (void)
   1660  1.1  mrg {
   1661  1.1  mrg   aarch64_init_ls64_builtins_types ();
   1662  1.1  mrg 
   1663  1.1  mrg   ls64_builtins_data data[4] = {
   1664  1.1  mrg     {"__arm_ld64b", AARCH64_LS64_BUILTIN_LD64B,
   1665  1.1  mrg      build_function_type_list (ls64_arm_data_t,
   1666  1.1  mrg 			       const_ptr_type_node, NULL_TREE)},
   1667  1.1  mrg     {"__arm_st64b", AARCH64_LS64_BUILTIN_ST64B,
   1668  1.1  mrg      build_function_type_list (void_type_node, ptr_type_node,
   1669  1.1  mrg 			       ls64_arm_data_t, NULL_TREE)},
   1670  1.1  mrg     {"__arm_st64bv", AARCH64_LS64_BUILTIN_ST64BV,
   1671  1.1  mrg      build_function_type_list (uint64_type_node, ptr_type_node,
   1672  1.1  mrg 			       ls64_arm_data_t, NULL_TREE)},
   1673  1.1  mrg     {"__arm_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0,
   1674  1.1  mrg      build_function_type_list (uint64_type_node, ptr_type_node,
   1675  1.1  mrg 			       ls64_arm_data_t, NULL_TREE)},
   1676  1.1  mrg   };
   1677  1.1  mrg 
   1678  1.1  mrg   for (size_t i = 0; i < ARRAY_SIZE (data); ++i)
   1679  1.1  mrg     aarch64_builtin_decls[data[i].code]
   1680  1.1  mrg       = aarch64_general_simulate_builtin (data[i].name, data[i].type,
   1681  1.1  mrg 					  data[i].code);
   1682  1.1  mrg }
   1683  1.1  mrg 
   1684  1.1  mrg static void
   1685  1.1  mrg aarch64_init_data_intrinsics (void)
   1686  1.1  mrg {
   1687  1.1  mrg   tree uint32_fntype = build_function_type_list (uint32_type_node,
   1688  1.1  mrg 						 uint32_type_node, NULL_TREE);
   1689  1.1  mrg   tree ulong_fntype = build_function_type_list (long_unsigned_type_node,
   1690  1.1  mrg 						long_unsigned_type_node,
   1691  1.1  mrg 						NULL_TREE);
   1692  1.1  mrg   tree uint64_fntype = build_function_type_list (uint64_type_node,
   1693  1.1  mrg 						 uint64_type_node, NULL_TREE);
   1694  1.1  mrg   aarch64_builtin_decls[AARCH64_REV16]
   1695  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rev16", uint32_fntype,
   1696  1.1  mrg 				   AARCH64_REV16);
   1697  1.1  mrg   aarch64_builtin_decls[AARCH64_REV16L]
   1698  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rev16l", ulong_fntype,
   1699  1.1  mrg 				   AARCH64_REV16L);
   1700  1.1  mrg   aarch64_builtin_decls[AARCH64_REV16LL]
   1701  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rev16ll", uint64_fntype,
   1702  1.1  mrg 				   AARCH64_REV16LL);
   1703  1.1  mrg   aarch64_builtin_decls[AARCH64_RBIT]
   1704  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rbit", uint32_fntype,
   1705  1.1  mrg 				   AARCH64_RBIT);
   1706  1.1  mrg   aarch64_builtin_decls[AARCH64_RBITL]
   1707  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rbitl", ulong_fntype,
   1708  1.1  mrg 				   AARCH64_RBITL);
   1709  1.1  mrg   aarch64_builtin_decls[AARCH64_RBITLL]
   1710  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_rbitll", uint64_fntype,
   1711  1.1  mrg 				   AARCH64_RBITLL);
   1712  1.1  mrg }
   1713  1.1  mrg 
   1714  1.1  mrg /* Implement #pragma GCC aarch64 "arm_acle.h".  */
   1715  1.1  mrg void
   1716  1.1  mrg handle_arm_acle_h (void)
   1717  1.1  mrg {
   1718  1.1  mrg   if (TARGET_LS64)
   1719  1.1  mrg     aarch64_init_ls64_builtins ();
   1720  1.1  mrg }
   1721  1.1  mrg 
   1722  1.1  mrg /* Initialize fpsr fpcr getters and setters.  */
   1723  1.1  mrg 
   1724  1.1  mrg static void
   1725  1.1  mrg aarch64_init_fpsr_fpcr_builtins (void)
   1726  1.1  mrg {
   1727  1.1  mrg   tree ftype_set
   1728  1.1  mrg     = build_function_type_list (void_type_node, unsigned_type_node, NULL);
   1729  1.1  mrg   tree ftype_get
   1730  1.1  mrg     = build_function_type_list (unsigned_type_node, NULL);
   1731  1.1  mrg 
   1732  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
   1733  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
   1734  1.1  mrg 				   ftype_get,
   1735  1.1  mrg 				   AARCH64_BUILTIN_GET_FPCR);
   1736  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
   1737  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
   1738  1.1  mrg 				   ftype_set,
   1739  1.1  mrg 				   AARCH64_BUILTIN_SET_FPCR);
   1740  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
   1741  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
   1742  1.1  mrg 				   ftype_get,
   1743  1.1  mrg 				   AARCH64_BUILTIN_GET_FPSR);
   1744  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
   1745  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
   1746  1.1  mrg 				   ftype_set,
   1747  1.1  mrg 				   AARCH64_BUILTIN_SET_FPSR);
   1748  1.1  mrg 
   1749  1.1  mrg   ftype_set
   1750  1.1  mrg     = build_function_type_list (void_type_node, long_long_unsigned_type_node,
   1751  1.1  mrg 				NULL);
   1752  1.1  mrg   ftype_get
   1753  1.1  mrg     = build_function_type_list (long_long_unsigned_type_node, NULL);
   1754  1.1  mrg 
   1755  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR64]
   1756  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
   1757  1.1  mrg 				   ftype_get,
   1758  1.1  mrg 				   AARCH64_BUILTIN_GET_FPCR64);
   1759  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR64]
   1760  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
   1761  1.1  mrg 				   ftype_set,
   1762  1.1  mrg 				   AARCH64_BUILTIN_SET_FPCR64);
   1763  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR64]
   1764  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
   1765  1.1  mrg 				   ftype_get,
   1766  1.1  mrg 				   AARCH64_BUILTIN_GET_FPSR64);
   1767  1.1  mrg   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR64]
   1768  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
   1769  1.1  mrg 				   ftype_set,
   1770  1.1  mrg 				   AARCH64_BUILTIN_SET_FPSR64);
   1771  1.1  mrg }
   1772  1.1  mrg 
   1773  1.1  mrg /* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */
   1774  1.1  mrg 
   1775  1.1  mrg void
   1776  1.1  mrg aarch64_general_init_builtins (void)
   1777  1.1  mrg {
   1778  1.1  mrg   aarch64_init_fpsr_fpcr_builtins ();
   1779  1.1  mrg 
   1780  1.1  mrg   aarch64_init_fp16_types ();
   1781  1.1  mrg 
   1782  1.1  mrg   aarch64_init_bf16_types ();
   1783  1.1  mrg 
   1784  1.1  mrg   {
   1785  1.1  mrg     aarch64_simd_switcher simd;
   1786  1.1  mrg     aarch64_init_simd_builtins ();
   1787  1.1  mrg   }
   1788  1.1  mrg 
   1789  1.1  mrg   aarch64_init_crc32_builtins ();
   1790  1.1  mrg   aarch64_init_builtin_rsqrt ();
   1791  1.1  mrg   aarch64_init_rng_builtins ();
   1792  1.1  mrg   aarch64_init_data_intrinsics ();
   1793  1.1  mrg 
   1794  1.1  mrg   tree ftype_jcvt
   1795  1.1  mrg     = build_function_type_list (intSI_type_node, double_type_node, NULL);
   1796  1.1  mrg   aarch64_builtin_decls[AARCH64_JSCVT]
   1797  1.1  mrg     = aarch64_general_add_builtin ("__builtin_aarch64_jcvtzs", ftype_jcvt,
   1798  1.1  mrg 				   AARCH64_JSCVT);
   1799  1.1  mrg 
   1800  1.1  mrg   /* Initialize pointer authentication builtins which are backed by instructions
   1801  1.1  mrg      in NOP encoding space.
   1802  1.1  mrg 
   1803  1.1  mrg      NOTE: these builtins are supposed to be used by libgcc unwinder only, as
   1804  1.1  mrg      there is no support on return address signing under ILP32, we don't
   1805  1.1  mrg      register them.  */
   1806  1.1  mrg   if (!TARGET_ILP32)
   1807  1.1  mrg     aarch64_init_pauth_hint_builtins ();
   1808  1.1  mrg 
   1809  1.1  mrg   if (TARGET_TME)
   1810  1.1  mrg     aarch64_init_tme_builtins ();
   1811  1.1  mrg 
   1812  1.1  mrg   if (TARGET_MEMTAG)
   1813  1.1  mrg     aarch64_init_memtag_builtins ();
   1814  1.1  mrg 
   1815  1.1  mrg   if (in_lto_p)
   1816  1.1  mrg     handle_arm_acle_h ();
   1817  1.1  mrg }
   1818  1.1  mrg 
   1819  1.1  mrg /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group.  */
   1820  1.1  mrg tree
   1821  1.1  mrg aarch64_general_builtin_decl (unsigned code, bool)
   1822  1.1  mrg {
   1823  1.1  mrg   if (code >= AARCH64_BUILTIN_MAX)
   1824  1.1  mrg     return error_mark_node;
   1825  1.1  mrg 
   1826  1.1  mrg   return aarch64_builtin_decls[code];
   1827  1.1  mrg }
   1828  1.1  mrg 
   1829  1.1  mrg typedef enum
   1830  1.1  mrg {
   1831  1.1  mrg   SIMD_ARG_COPY_TO_REG,
   1832  1.1  mrg   SIMD_ARG_CONSTANT,
   1833  1.1  mrg   SIMD_ARG_LANE_INDEX,
   1834  1.1  mrg   SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
   1835  1.1  mrg   SIMD_ARG_LANE_PAIR_INDEX,
   1836  1.1  mrg   SIMD_ARG_LANE_QUADTUP_INDEX,
   1837  1.1  mrg   SIMD_ARG_STOP
   1838  1.1  mrg } builtin_simd_arg;
   1839  1.1  mrg 
   1840  1.1  mrg 
   1841  1.1  mrg static rtx
   1842  1.1  mrg aarch64_simd_expand_args (rtx target, int icode, int have_retval,
   1843  1.1  mrg 			  tree exp, builtin_simd_arg *args,
   1844  1.1  mrg 			  machine_mode builtin_mode)
   1845  1.1  mrg {
   1846  1.1  mrg   rtx pat;
   1847  1.1  mrg   rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand.  */
   1848  1.1  mrg   int opc = 0;
   1849  1.1  mrg 
   1850  1.1  mrg   if (have_retval)
   1851  1.1  mrg     {
   1852  1.1  mrg       machine_mode tmode = insn_data[icode].operand[0].mode;
   1853  1.1  mrg       if (!target
   1854  1.1  mrg 	  || GET_MODE (target) != tmode
   1855  1.1  mrg 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
   1856  1.1  mrg 	target = gen_reg_rtx (tmode);
   1857  1.1  mrg       op[opc++] = target;
   1858  1.1  mrg     }
   1859  1.1  mrg 
   1860  1.1  mrg   for (;;)
   1861  1.1  mrg     {
   1862  1.1  mrg       builtin_simd_arg thisarg = args[opc - have_retval];
   1863  1.1  mrg 
   1864  1.1  mrg       if (thisarg == SIMD_ARG_STOP)
   1865  1.1  mrg 	break;
   1866  1.1  mrg       else
   1867  1.1  mrg 	{
   1868  1.1  mrg 	  tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
   1869  1.1  mrg 	  machine_mode mode = insn_data[icode].operand[opc].mode;
   1870  1.1  mrg 	  op[opc] = expand_normal (arg);
   1871  1.1  mrg 
   1872  1.1  mrg 	  switch (thisarg)
   1873  1.1  mrg 	    {
   1874  1.1  mrg 	    case SIMD_ARG_COPY_TO_REG:
   1875  1.1  mrg 	      if (POINTER_TYPE_P (TREE_TYPE (arg)))
   1876  1.1  mrg 		op[opc] = convert_memory_address (Pmode, op[opc]);
   1877  1.1  mrg 	      /*gcc_assert (GET_MODE (op[opc]) == mode); */
   1878  1.1  mrg 	      if (!(*insn_data[icode].operand[opc].predicate)
   1879  1.1  mrg 		  (op[opc], mode))
   1880  1.1  mrg 		op[opc] = copy_to_mode_reg (mode, op[opc]);
   1881  1.1  mrg 	      break;
   1882  1.1  mrg 
   1883  1.1  mrg 	    case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
   1884  1.1  mrg 	      gcc_assert (opc > 1);
   1885  1.1  mrg 	      if (CONST_INT_P (op[opc]))
   1886  1.1  mrg 		{
   1887  1.1  mrg 		  unsigned int nunits
   1888  1.1  mrg 		    = GET_MODE_NUNITS (builtin_mode).to_constant ();
   1889  1.1  mrg 		  aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
   1890  1.1  mrg 		  /* Keep to GCC-vector-extension lane indices in the RTL.  */
   1891  1.1  mrg 		  op[opc] = aarch64_endian_lane_rtx (builtin_mode,
   1892  1.1  mrg 						     INTVAL (op[opc]));
   1893  1.1  mrg 		}
   1894  1.1  mrg 	      goto constant_arg;
   1895  1.1  mrg 
   1896  1.1  mrg 	    case SIMD_ARG_LANE_INDEX:
   1897  1.1  mrg 	      /* Must be a previous operand into which this is an index.  */
   1898  1.1  mrg 	      gcc_assert (opc > 0);
   1899  1.1  mrg 	      if (CONST_INT_P (op[opc]))
   1900  1.1  mrg 		{
   1901  1.1  mrg 		  machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
   1902  1.1  mrg 		  unsigned int nunits
   1903  1.1  mrg 		    = GET_MODE_NUNITS (vmode).to_constant ();
   1904  1.1  mrg 		  aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
   1905  1.1  mrg 		  /* Keep to GCC-vector-extension lane indices in the RTL.  */
   1906  1.1  mrg 		  op[opc] = aarch64_endian_lane_rtx (vmode, INTVAL (op[opc]));
   1907  1.1  mrg 		}
   1908  1.1  mrg 	      /* If the lane index isn't a constant then error out.  */
   1909  1.1  mrg 	      goto constant_arg;
   1910  1.1  mrg 
   1911  1.1  mrg 	    case SIMD_ARG_LANE_PAIR_INDEX:
   1912  1.1  mrg 	      /* Must be a previous operand into which this is an index and
   1913  1.1  mrg 		 index is restricted to nunits / 2.  */
   1914  1.1  mrg 	      gcc_assert (opc > 0);
   1915  1.1  mrg 	      if (CONST_INT_P (op[opc]))
   1916  1.1  mrg 		{
   1917  1.1  mrg 		  machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
   1918  1.1  mrg 		  unsigned int nunits
   1919  1.1  mrg 		    = GET_MODE_NUNITS (vmode).to_constant ();
   1920  1.1  mrg 		  aarch64_simd_lane_bounds (op[opc], 0, nunits / 2, exp);
   1921  1.1  mrg 		  /* Keep to GCC-vector-extension lane indices in the RTL.  */
   1922  1.1  mrg 		  int lane = INTVAL (op[opc]);
   1923  1.1  mrg 		  op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 2, lane),
   1924  1.1  mrg 					  SImode);
   1925  1.1  mrg 		}
   1926  1.1  mrg 	      /* If the lane index isn't a constant then error out.  */
   1927  1.1  mrg 	      goto constant_arg;
   1928  1.1  mrg 	    case SIMD_ARG_LANE_QUADTUP_INDEX:
   1929  1.1  mrg 	      /* Must be a previous operand into which this is an index and
   1930  1.1  mrg 		 index is restricted to nunits / 4.  */
   1931  1.1  mrg 	      gcc_assert (opc > 0);
   1932  1.1  mrg 	      if (CONST_INT_P (op[opc]))
   1933  1.1  mrg 		{
   1934  1.1  mrg 		  machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
   1935  1.1  mrg 		  unsigned int nunits
   1936  1.1  mrg 		    = GET_MODE_NUNITS (vmode).to_constant ();
   1937  1.1  mrg 		  aarch64_simd_lane_bounds (op[opc], 0, nunits / 4, exp);
   1938  1.1  mrg 		  /* Keep to GCC-vector-extension lane indices in the RTL.  */
   1939  1.1  mrg 		  int lane = INTVAL (op[opc]);
   1940  1.1  mrg 		  op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 4, lane),
   1941  1.1  mrg 					  SImode);
   1942  1.1  mrg 		}
   1943  1.1  mrg 	      /* If the lane index isn't a constant then error out.  */
   1944  1.1  mrg 	      goto constant_arg;
   1945  1.1  mrg 	    case SIMD_ARG_CONSTANT:
   1946  1.1  mrg constant_arg:
   1947  1.1  mrg 	      if (!(*insn_data[icode].operand[opc].predicate)
   1948  1.1  mrg 		  (op[opc], mode))
   1949  1.1  mrg 	      {
   1950  1.1  mrg 		error_at (EXPR_LOCATION (exp),
   1951  1.1  mrg 			  "argument %d must be a constant immediate",
   1952  1.1  mrg 			  opc + 1 - have_retval);
   1953  1.1  mrg 		return const0_rtx;
   1954  1.1  mrg 	      }
   1955  1.1  mrg 	      break;
   1956  1.1  mrg 
   1957  1.1  mrg 	    case SIMD_ARG_STOP:
   1958  1.1  mrg 	      gcc_unreachable ();
   1959  1.1  mrg 	    }
   1960  1.1  mrg 
   1961  1.1  mrg 	  opc++;
   1962  1.1  mrg 	}
   1963  1.1  mrg     }
   1964  1.1  mrg 
   1965  1.1  mrg   switch (opc)
   1966  1.1  mrg     {
   1967  1.1  mrg     case 1:
   1968  1.1  mrg       pat = GEN_FCN (icode) (op[0]);
   1969  1.1  mrg       break;
   1970  1.1  mrg 
   1971  1.1  mrg     case 2:
   1972  1.1  mrg       pat = GEN_FCN (icode) (op[0], op[1]);
   1973  1.1  mrg       break;
   1974  1.1  mrg 
   1975  1.1  mrg     case 3:
   1976  1.1  mrg       pat = GEN_FCN (icode) (op[0], op[1], op[2]);
   1977  1.1  mrg       break;
   1978  1.1  mrg 
   1979  1.1  mrg     case 4:
   1980  1.1  mrg       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
   1981  1.1  mrg       break;
   1982  1.1  mrg 
   1983  1.1  mrg     case 5:
   1984  1.1  mrg       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
   1985  1.1  mrg       break;
   1986  1.1  mrg 
   1987  1.1  mrg     case 6:
   1988  1.1  mrg       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
   1989  1.1  mrg       break;
   1990  1.1  mrg 
   1991  1.1  mrg     default:
   1992  1.1  mrg       gcc_unreachable ();
   1993  1.1  mrg     }
   1994  1.1  mrg 
   1995  1.1  mrg   if (!pat)
   1996  1.1  mrg     return NULL_RTX;
   1997  1.1  mrg 
   1998  1.1  mrg   emit_insn (pat);
   1999  1.1  mrg 
   2000  1.1  mrg   return target;
   2001  1.1  mrg }
   2002  1.1  mrg 
   2003  1.1  mrg /* Expand an AArch64 AdvSIMD builtin(intrinsic).  */
   2004  1.1  mrg rtx
   2005  1.1  mrg aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
   2006  1.1  mrg {
   2007  1.1  mrg   if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
   2008  1.1  mrg     {
   2009  1.1  mrg       rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
   2010  1.1  mrg       rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
   2011  1.1  mrg       if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
   2012  1.1  mrg 	  && UINTVAL (elementsize) != 0
   2013  1.1  mrg 	  && UINTVAL (totalsize) != 0)
   2014  1.1  mrg 	{
   2015  1.1  mrg 	  rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
   2016  1.1  mrg           if (CONST_INT_P (lane_idx))
   2017  1.1  mrg 	    aarch64_simd_lane_bounds (lane_idx, 0,
   2018  1.1  mrg 				      UINTVAL (totalsize)
   2019  1.1  mrg 				       / UINTVAL (elementsize),
   2020  1.1  mrg 				      exp);
   2021  1.1  mrg           else
   2022  1.1  mrg 	    error_at (EXPR_LOCATION (exp),
   2023  1.1  mrg 		      "lane index must be a constant immediate");
   2024  1.1  mrg 	}
   2025  1.1  mrg       else
   2026  1.1  mrg 	error_at (EXPR_LOCATION (exp),
   2027  1.1  mrg 		  "total size and element size must be a nonzero "
   2028  1.1  mrg 		  "constant immediate");
   2029  1.1  mrg       /* Don't generate any RTL.  */
   2030  1.1  mrg       return const0_rtx;
   2031  1.1  mrg     }
   2032  1.1  mrg   aarch64_simd_builtin_datum *d =
   2033  1.1  mrg 		&aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
   2034  1.1  mrg   enum insn_code icode = d->code;
   2035  1.1  mrg   builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
   2036  1.1  mrg   int num_args = insn_data[d->code].n_operands;
   2037  1.1  mrg   int is_void = 0;
   2038  1.1  mrg   int k;
   2039  1.1  mrg 
   2040  1.1  mrg   is_void = !!(d->qualifiers[0] & qualifier_void);
   2041  1.1  mrg 
   2042  1.1  mrg   num_args += is_void;
   2043  1.1  mrg 
   2044  1.1  mrg   for (k = 1; k < num_args; k++)
   2045  1.1  mrg     {
   2046  1.1  mrg       /* We have four arrays of data, each indexed in a different fashion.
   2047  1.1  mrg 	 qualifiers - element 0 always describes the function return type.
   2048  1.1  mrg 	 operands - element 0 is either the operand for return value (if
   2049  1.1  mrg 	   the function has a non-void return type) or the operand for the
   2050  1.1  mrg 	   first argument.
   2051  1.1  mrg 	 expr_args - element 0 always holds the first argument.
   2052  1.1  mrg 	 args - element 0 is always used for the return type.  */
   2053  1.1  mrg       int qualifiers_k = k;
   2054  1.1  mrg       int operands_k = k - is_void;
   2055  1.1  mrg       int expr_args_k = k - 1;
   2056  1.1  mrg 
   2057  1.1  mrg       if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
   2058  1.1  mrg 	args[k] = SIMD_ARG_LANE_INDEX;
   2059  1.1  mrg       else if (d->qualifiers[qualifiers_k] & qualifier_lane_pair_index)
   2060  1.1  mrg 	args[k] = SIMD_ARG_LANE_PAIR_INDEX;
   2061  1.1  mrg       else if (d->qualifiers[qualifiers_k] & qualifier_lane_quadtup_index)
   2062  1.1  mrg 	args[k] = SIMD_ARG_LANE_QUADTUP_INDEX;
   2063  1.1  mrg       else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
   2064  1.1  mrg 	args[k] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
   2065  1.1  mrg       else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
   2066  1.1  mrg 	args[k] = SIMD_ARG_CONSTANT;
   2067  1.1  mrg       else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
   2068  1.1  mrg 	{
   2069  1.1  mrg 	  rtx arg
   2070  1.1  mrg 	    = expand_normal (CALL_EXPR_ARG (exp,
   2071  1.1  mrg 					    (expr_args_k)));
   2072  1.1  mrg 	  /* Handle constants only if the predicate allows it.  */
   2073  1.1  mrg 	  bool op_const_int_p =
   2074  1.1  mrg 	    (CONST_INT_P (arg)
   2075  1.1  mrg 	     && (*insn_data[icode].operand[operands_k].predicate)
   2076  1.1  mrg 		(arg, insn_data[icode].operand[operands_k].mode));
   2077  1.1  mrg 	  args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
   2078  1.1  mrg 	}
   2079  1.1  mrg       else
   2080  1.1  mrg 	args[k] = SIMD_ARG_COPY_TO_REG;
   2081  1.1  mrg 
   2082  1.1  mrg     }
   2083  1.1  mrg   args[k] = SIMD_ARG_STOP;
   2084  1.1  mrg 
   2085  1.1  mrg   /* The interface to aarch64_simd_expand_args expects a 0 if
   2086  1.1  mrg      the function is void, and a 1 if it is not.  */
   2087  1.1  mrg   return aarch64_simd_expand_args
   2088  1.1  mrg 	  (target, icode, !is_void, exp, &args[1], d->mode);
   2089  1.1  mrg }
   2090  1.1  mrg 
   2091  1.1  mrg rtx
   2092  1.1  mrg aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
   2093  1.1  mrg {
   2094  1.1  mrg   rtx pat;
   2095  1.1  mrg   aarch64_crc_builtin_datum *d
   2096  1.1  mrg     = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
   2097  1.1  mrg   enum insn_code icode = d->icode;
   2098  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   2099  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 1);
   2100  1.1  mrg   rtx op0 = expand_normal (arg0);
   2101  1.1  mrg   rtx op1 = expand_normal (arg1);
   2102  1.1  mrg   machine_mode tmode = insn_data[icode].operand[0].mode;
   2103  1.1  mrg   machine_mode mode0 = insn_data[icode].operand[1].mode;
   2104  1.1  mrg   machine_mode mode1 = insn_data[icode].operand[2].mode;
   2105  1.1  mrg 
   2106  1.1  mrg   if (! target
   2107  1.1  mrg       || GET_MODE (target) != tmode
   2108  1.1  mrg       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
   2109  1.1  mrg     target = gen_reg_rtx (tmode);
   2110  1.1  mrg 
   2111  1.1  mrg   gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
   2112  1.1  mrg 	      && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
   2113  1.1  mrg 
   2114  1.1  mrg   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
   2115  1.1  mrg     op0 = copy_to_mode_reg (mode0, op0);
   2116  1.1  mrg   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
   2117  1.1  mrg     op1 = copy_to_mode_reg (mode1, op1);
   2118  1.1  mrg 
   2119  1.1  mrg   pat = GEN_FCN (icode) (target, op0, op1);
   2120  1.1  mrg   if (!pat)
   2121  1.1  mrg     return NULL_RTX;
   2122  1.1  mrg 
   2123  1.1  mrg   emit_insn (pat);
   2124  1.1  mrg   return target;
   2125  1.1  mrg }
   2126  1.1  mrg 
   2127  1.1  mrg /* Function to expand reciprocal square root builtins.  */
   2128  1.1  mrg 
   2129  1.1  mrg static rtx
   2130  1.1  mrg aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
   2131  1.1  mrg {
   2132  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   2133  1.1  mrg   rtx op0 = expand_normal (arg0);
   2134  1.1  mrg 
   2135  1.1  mrg   rtx (*gen) (rtx, rtx);
   2136  1.1  mrg 
   2137  1.1  mrg   switch (fcode)
   2138  1.1  mrg     {
   2139  1.1  mrg       case AARCH64_BUILTIN_RSQRT_DF:
   2140  1.1  mrg 	gen = gen_rsqrtdf2;
   2141  1.1  mrg 	break;
   2142  1.1  mrg       case AARCH64_BUILTIN_RSQRT_SF:
   2143  1.1  mrg 	gen = gen_rsqrtsf2;
   2144  1.1  mrg 	break;
   2145  1.1  mrg       case AARCH64_BUILTIN_RSQRT_V2DF:
   2146  1.1  mrg 	gen = gen_rsqrtv2df2;
   2147  1.1  mrg 	break;
   2148  1.1  mrg       case AARCH64_BUILTIN_RSQRT_V2SF:
   2149  1.1  mrg 	gen = gen_rsqrtv2sf2;
   2150  1.1  mrg 	break;
   2151  1.1  mrg       case AARCH64_BUILTIN_RSQRT_V4SF:
   2152  1.1  mrg 	gen = gen_rsqrtv4sf2;
   2153  1.1  mrg 	break;
   2154  1.1  mrg       default: gcc_unreachable ();
   2155  1.1  mrg     }
   2156  1.1  mrg 
   2157  1.1  mrg   if (!target)
   2158  1.1  mrg     target = gen_reg_rtx (GET_MODE (op0));
   2159  1.1  mrg 
   2160  1.1  mrg   emit_insn (gen (target, op0));
   2161  1.1  mrg 
   2162  1.1  mrg   return target;
   2163  1.1  mrg }
   2164  1.1  mrg 
   2165  1.1  mrg /* Expand a FCMLA lane expression EXP with code FCODE and
   2166  1.1  mrg    result going to TARGET if that is convenient.  */
   2167  1.1  mrg 
   2168  1.1  mrg rtx
   2169  1.1  mrg aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
   2170  1.1  mrg {
   2171  1.1  mrg   int bcode = fcode - AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE - 1;
   2172  1.1  mrg   aarch64_fcmla_laneq_builtin_datum* d
   2173  1.1  mrg     = &aarch64_fcmla_lane_builtin_data[bcode];
   2174  1.1  mrg   machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
   2175  1.1  mrg   rtx op0 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 0)));
   2176  1.1  mrg   rtx op1 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
   2177  1.1  mrg   rtx op2 = force_reg (quadmode, expand_normal (CALL_EXPR_ARG (exp, 2)));
   2178  1.1  mrg   tree tmp = CALL_EXPR_ARG (exp, 3);
   2179  1.1  mrg   rtx lane_idx = expand_expr (tmp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
   2180  1.1  mrg 
   2181  1.1  mrg   /* Validate that the lane index is a constant.  */
   2182  1.1  mrg   if (!CONST_INT_P (lane_idx))
   2183  1.1  mrg     {
   2184  1.1  mrg       error_at (EXPR_LOCATION (exp),
   2185  1.1  mrg 		"argument %d must be a constant immediate", 4);
   2186  1.1  mrg       return const0_rtx;
   2187  1.1  mrg     }
   2188  1.1  mrg 
   2189  1.1  mrg   /* Validate that the index is within the expected range.  */
   2190  1.1  mrg   int nunits = GET_MODE_NUNITS (quadmode).to_constant ();
   2191  1.1  mrg   aarch64_simd_lane_bounds (lane_idx, 0, nunits / 2, exp);
   2192  1.1  mrg 
   2193  1.1  mrg   /* Generate the correct register and mode.  */
   2194  1.1  mrg   int lane = INTVAL (lane_idx);
   2195  1.1  mrg 
   2196  1.1  mrg   if (lane < nunits / 4)
   2197  1.1  mrg     op2 = simplify_gen_subreg (d->mode, op2, quadmode,
   2198  1.1  mrg 			       subreg_lowpart_offset (d->mode, quadmode));
   2199  1.1  mrg   else
   2200  1.1  mrg     {
   2201  1.1  mrg       /* Select the upper 64 bits, either a V2SF or V4HF, this however
   2202  1.1  mrg 	 is quite messy, as the operation required even though simple
   2203  1.1  mrg 	 doesn't have a simple RTL pattern, and seems it's quite hard to
   2204  1.1  mrg 	 define using a single RTL pattern.  The target generic version
   2205  1.1  mrg 	 gen_highpart_mode generates code that isn't optimal.  */
   2206  1.1  mrg       rtx temp1 = gen_reg_rtx (d->mode);
   2207  1.1  mrg       rtx temp2 = gen_reg_rtx (DImode);
   2208  1.1  mrg       temp1 = simplify_gen_subreg (d->mode, op2, quadmode,
   2209  1.1  mrg 				   subreg_lowpart_offset (d->mode, quadmode));
   2210  1.1  mrg       temp1 = simplify_gen_subreg (V2DImode, temp1, d->mode, 0);
   2211  1.1  mrg       if (BYTES_BIG_ENDIAN)
   2212  1.1  mrg 	emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const0_rtx));
   2213  1.1  mrg       else
   2214  1.1  mrg 	emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const1_rtx));
   2215  1.1  mrg       op2 = simplify_gen_subreg (d->mode, temp2, GET_MODE (temp2), 0);
   2216  1.1  mrg 
   2217  1.1  mrg       /* And recalculate the index.  */
   2218  1.1  mrg       lane -= nunits / 4;
   2219  1.1  mrg     }
   2220  1.1  mrg 
   2221  1.1  mrg   /* Keep to GCC-vector-extension lane indices in the RTL, only nunits / 4
   2222  1.1  mrg      (max nunits in range check) are valid.  Which means only 0-1, so we
   2223  1.1  mrg      only need to know the order in a V2mode.  */
   2224  1.1  mrg   lane_idx = aarch64_endian_lane_rtx (V2DImode, lane);
   2225  1.1  mrg 
   2226  1.1  mrg   if (!target
   2227  1.1  mrg       || !REG_P (target)
   2228  1.1  mrg       || GET_MODE (target) != d->mode)
   2229  1.1  mrg     target = gen_reg_rtx (d->mode);
   2230  1.1  mrg 
   2231  1.1  mrg   rtx pat = NULL_RTX;
   2232  1.1  mrg 
   2233  1.1  mrg   if (d->lane)
   2234  1.1  mrg     pat = GEN_FCN (d->icode) (target, op0, op1, op2, lane_idx);
   2235  1.1  mrg   else
   2236  1.1  mrg     pat = GEN_FCN (d->icode) (target, op0, op1, op2);
   2237  1.1  mrg 
   2238  1.1  mrg   if (!pat)
   2239  1.1  mrg     return NULL_RTX;
   2240  1.1  mrg 
   2241  1.1  mrg   emit_insn (pat);
   2242  1.1  mrg   return target;
   2243  1.1  mrg }
   2244  1.1  mrg 
   2245  1.1  mrg /* Function to expand an expression EXP which calls one of the Transactional
   2246  1.1  mrg    Memory Extension (TME) builtins FCODE with the result going to TARGET.  */
   2247  1.1  mrg static rtx
   2248  1.1  mrg aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
   2249  1.1  mrg {
   2250  1.1  mrg   switch (fcode)
   2251  1.1  mrg     {
   2252  1.1  mrg     case AARCH64_TME_BUILTIN_TSTART:
   2253  1.1  mrg       target = gen_reg_rtx (DImode);
   2254  1.1  mrg       emit_insn (GEN_FCN (CODE_FOR_tstart) (target));
   2255  1.1  mrg       break;
   2256  1.1  mrg 
   2257  1.1  mrg     case AARCH64_TME_BUILTIN_TTEST:
   2258  1.1  mrg       target = gen_reg_rtx (DImode);
   2259  1.1  mrg       emit_insn (GEN_FCN (CODE_FOR_ttest) (target));
   2260  1.1  mrg       break;
   2261  1.1  mrg 
   2262  1.1  mrg     case AARCH64_TME_BUILTIN_TCOMMIT:
   2263  1.1  mrg       emit_insn (GEN_FCN (CODE_FOR_tcommit) ());
   2264  1.1  mrg       break;
   2265  1.1  mrg 
   2266  1.1  mrg     case AARCH64_TME_BUILTIN_TCANCEL:
   2267  1.1  mrg       {
   2268  1.1  mrg 	tree arg0 = CALL_EXPR_ARG (exp, 0);
   2269  1.1  mrg 	rtx op0 = expand_normal (arg0);
   2270  1.1  mrg 	if (CONST_INT_P (op0) && UINTVAL (op0) <= 65536)
   2271  1.1  mrg 	  emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
   2272  1.1  mrg 	else
   2273  1.1  mrg 	  {
   2274  1.1  mrg 	    error_at (EXPR_LOCATION (exp),
   2275  1.1  mrg 		      "argument must be a 16-bit constant immediate");
   2276  1.1  mrg 	    return const0_rtx;
   2277  1.1  mrg 	  }
   2278  1.1  mrg       }
   2279  1.1  mrg       break;
   2280  1.1  mrg 
   2281  1.1  mrg     default :
   2282  1.1  mrg       gcc_unreachable ();
   2283  1.1  mrg     }
   2284  1.1  mrg     return target;
   2285  1.1  mrg }
   2286  1.1  mrg 
   2287  1.1  mrg /* Function to expand an expression EXP which calls one of the Load/Store
   2288  1.1  mrg    64 Byte extension (LS64) builtins FCODE with the result going to TARGET.  */
   2289  1.1  mrg static rtx
   2290  1.1  mrg aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target)
   2291  1.1  mrg {
   2292  1.1  mrg   expand_operand ops[3];
   2293  1.1  mrg 
   2294  1.1  mrg   switch (fcode)
   2295  1.1  mrg     {
   2296  1.1  mrg     case AARCH64_LS64_BUILTIN_LD64B:
   2297  1.1  mrg       {
   2298  1.1  mrg 	rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2299  1.1  mrg 	create_output_operand (&ops[0], target, V8DImode);
   2300  1.1  mrg 	create_input_operand (&ops[1], op0, DImode);
   2301  1.1  mrg 	expand_insn (CODE_FOR_ld64b, 2, ops);
   2302  1.1  mrg 	return ops[0].value;
   2303  1.1  mrg       }
   2304  1.1  mrg     case AARCH64_LS64_BUILTIN_ST64B:
   2305  1.1  mrg       {
   2306  1.1  mrg 	rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2307  1.1  mrg 	rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
   2308  1.1  mrg 	create_input_operand (&ops[0], op0, DImode);
   2309  1.1  mrg 	create_input_operand (&ops[1], op1, V8DImode);
   2310  1.1  mrg 	expand_insn (CODE_FOR_st64b, 2, ops);
   2311  1.1  mrg 	return const0_rtx;
   2312  1.1  mrg       }
   2313  1.1  mrg     case AARCH64_LS64_BUILTIN_ST64BV:
   2314  1.1  mrg       {
   2315  1.1  mrg 	rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2316  1.1  mrg 	rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
   2317  1.1  mrg 	create_output_operand (&ops[0], target, DImode);
   2318  1.1  mrg 	create_input_operand (&ops[1], op0, DImode);
   2319  1.1  mrg 	create_input_operand (&ops[2], op1, V8DImode);
   2320  1.1  mrg 	expand_insn (CODE_FOR_st64bv, 3, ops);
   2321  1.1  mrg 	return ops[0].value;
   2322  1.1  mrg       }
   2323  1.1  mrg     case AARCH64_LS64_BUILTIN_ST64BV0:
   2324  1.1  mrg       {
   2325  1.1  mrg 	rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2326  1.1  mrg 	rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
   2327  1.1  mrg 	create_output_operand (&ops[0], target, DImode);
   2328  1.1  mrg 	create_input_operand (&ops[1], op0, DImode);
   2329  1.1  mrg 	create_input_operand (&ops[2], op1, V8DImode);
   2330  1.1  mrg 	expand_insn (CODE_FOR_st64bv0, 3, ops);
   2331  1.1  mrg 	return ops[0].value;
   2332  1.1  mrg       }
   2333  1.1  mrg     }
   2334  1.1  mrg 
   2335  1.1  mrg   gcc_unreachable ();
   2336  1.1  mrg }
   2337  1.1  mrg 
   2338  1.1  mrg /* Expand a random number builtin EXP with code FCODE, putting the result
   2339  1.1  mrg    int TARGET.  If IGNORE is true the return value is ignored.  */
   2340  1.1  mrg 
   2341  1.1  mrg rtx
   2342  1.1  mrg aarch64_expand_rng_builtin (tree exp, rtx target, int fcode, int ignore)
   2343  1.1  mrg {
   2344  1.1  mrg   rtx pat;
   2345  1.1  mrg   enum insn_code icode;
   2346  1.1  mrg   if (fcode == AARCH64_BUILTIN_RNG_RNDR)
   2347  1.1  mrg     icode = CODE_FOR_aarch64_rndr;
   2348  1.1  mrg   else if (fcode == AARCH64_BUILTIN_RNG_RNDRRS)
   2349  1.1  mrg     icode = CODE_FOR_aarch64_rndrrs;
   2350  1.1  mrg   else
   2351  1.1  mrg     gcc_unreachable ();
   2352  1.1  mrg 
   2353  1.1  mrg   rtx rand = gen_reg_rtx (DImode);
   2354  1.1  mrg   pat = GEN_FCN (icode) (rand);
   2355  1.1  mrg   if (!pat)
   2356  1.1  mrg     return NULL_RTX;
   2357  1.1  mrg 
   2358  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   2359  1.1  mrg   rtx res_addr = expand_normal (arg0);
   2360  1.1  mrg   res_addr = convert_memory_address (Pmode, res_addr);
   2361  1.1  mrg   rtx res_mem = gen_rtx_MEM (DImode, res_addr);
   2362  1.1  mrg   emit_insn (pat);
   2363  1.1  mrg   emit_move_insn (res_mem, rand);
   2364  1.1  mrg   /* If the status result is unused don't generate the CSET code.  */
   2365  1.1  mrg   if (ignore)
   2366  1.1  mrg     return target;
   2367  1.1  mrg 
   2368  1.1  mrg   rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
   2369  1.1  mrg   rtx cmp_rtx = gen_rtx_fmt_ee (EQ, SImode, cc_reg, const0_rtx);
   2370  1.1  mrg   emit_insn (gen_aarch64_cstoresi (target, cmp_rtx, cc_reg));
   2371  1.1  mrg   return target;
   2372  1.1  mrg }
   2373  1.1  mrg 
   2374  1.1  mrg /* Expand an expression EXP that calls a MEMTAG built-in FCODE
   2375  1.1  mrg    with result going to TARGET.  */
   2376  1.1  mrg static rtx
   2377  1.1  mrg aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
   2378  1.1  mrg {
   2379  1.1  mrg   if (TARGET_ILP32)
   2380  1.1  mrg     {
   2381  1.1  mrg       error ("Memory Tagging Extension does not support %<-mabi=ilp32%>");
   2382  1.1  mrg       return const0_rtx;
   2383  1.1  mrg     }
   2384  1.1  mrg 
   2385  1.1  mrg   rtx pat = NULL;
   2386  1.1  mrg   enum insn_code icode = aarch64_memtag_builtin_data[fcode -
   2387  1.1  mrg 			   AARCH64_MEMTAG_BUILTIN_START - 1].icode;
   2388  1.1  mrg 
   2389  1.1  mrg   rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2390  1.1  mrg   machine_mode mode0 = GET_MODE (op0);
   2391  1.1  mrg   op0 = force_reg (mode0 == VOIDmode ? DImode : mode0, op0);
   2392  1.1  mrg   op0 = convert_to_mode (DImode, op0, true);
   2393  1.1  mrg 
   2394  1.1  mrg   switch (fcode)
   2395  1.1  mrg     {
   2396  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_IRG:
   2397  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_GMI:
   2398  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_SUBP:
   2399  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_INC_TAG:
   2400  1.1  mrg 	{
   2401  1.1  mrg 	  if (! target
   2402  1.1  mrg 	      || GET_MODE (target) != DImode
   2403  1.1  mrg 	      || ! (*insn_data[icode].operand[0].predicate) (target, DImode))
   2404  1.1  mrg 	    target = gen_reg_rtx (DImode);
   2405  1.1  mrg 
   2406  1.1  mrg 	  if (fcode == AARCH64_MEMTAG_BUILTIN_INC_TAG)
   2407  1.1  mrg 	    {
   2408  1.1  mrg 	      rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
   2409  1.1  mrg 
   2410  1.1  mrg 	      if ((*insn_data[icode].operand[3].predicate) (op1, QImode))
   2411  1.1  mrg 		{
   2412  1.1  mrg 		  pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
   2413  1.1  mrg 		  break;
   2414  1.1  mrg 		}
   2415  1.1  mrg 	      error_at (EXPR_LOCATION (exp),
   2416  1.1  mrg 			"argument %d must be a constant immediate "
   2417  1.1  mrg 			"in range [0,15]", 2);
   2418  1.1  mrg 	      return const0_rtx;
   2419  1.1  mrg 	    }
   2420  1.1  mrg 	  else
   2421  1.1  mrg 	    {
   2422  1.1  mrg 	      rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
   2423  1.1  mrg 	      machine_mode mode1 = GET_MODE (op1);
   2424  1.1  mrg 	      op1 = force_reg (mode1 == VOIDmode ? DImode : mode1, op1);
   2425  1.1  mrg 	      op1 = convert_to_mode (DImode, op1, true);
   2426  1.1  mrg 	      pat = GEN_FCN (icode) (target, op0, op1);
   2427  1.1  mrg 	    }
   2428  1.1  mrg 	  break;
   2429  1.1  mrg 	}
   2430  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_GET_TAG:
   2431  1.1  mrg 	target = op0;
   2432  1.1  mrg 	pat = GEN_FCN (icode) (target, op0, const0_rtx);
   2433  1.1  mrg 	break;
   2434  1.1  mrg       case AARCH64_MEMTAG_BUILTIN_SET_TAG:
   2435  1.1  mrg 	pat = GEN_FCN (icode) (op0, op0, const0_rtx);
   2436  1.1  mrg 	break;
   2437  1.1  mrg       default:
   2438  1.1  mrg 	gcc_unreachable();
   2439  1.1  mrg     }
   2440  1.1  mrg 
   2441  1.1  mrg   if (!pat)
   2442  1.1  mrg     return NULL_RTX;
   2443  1.1  mrg 
   2444  1.1  mrg   emit_insn (pat);
   2445  1.1  mrg   return target;
   2446  1.1  mrg }
   2447  1.1  mrg 
   2448  1.1  mrg /* Function to expand an expression EXP which calls one of the ACLE Data
   2449  1.1  mrg    Intrinsic builtins FCODE with the result going to TARGET.  */
   2450  1.1  mrg static rtx
   2451  1.1  mrg aarch64_expand_builtin_data_intrinsic (unsigned int fcode, tree exp, rtx target)
   2452  1.1  mrg {
   2453  1.1  mrg   expand_operand ops[2];
   2454  1.1  mrg   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   2455  1.1  mrg   create_output_operand (&ops[0], target, mode);
   2456  1.1  mrg   create_input_operand (&ops[1], expand_normal (CALL_EXPR_ARG (exp, 0)), mode);
   2457  1.1  mrg   enum insn_code icode;
   2458  1.1  mrg 
   2459  1.1  mrg   switch (fcode)
   2460  1.1  mrg     {
   2461  1.1  mrg     case AARCH64_REV16:
   2462  1.1  mrg     case AARCH64_REV16L:
   2463  1.1  mrg     case AARCH64_REV16LL:
   2464  1.1  mrg       icode = code_for_aarch64_rev16 (mode);
   2465  1.1  mrg       break;
   2466  1.1  mrg     case AARCH64_RBIT:
   2467  1.1  mrg     case AARCH64_RBITL:
   2468  1.1  mrg     case AARCH64_RBITLL:
   2469  1.1  mrg       icode = code_for_aarch64_rbit (mode);
   2470  1.1  mrg       break;
   2471  1.1  mrg     default:
   2472  1.1  mrg       gcc_unreachable ();
   2473  1.1  mrg     }
   2474  1.1  mrg 
   2475  1.1  mrg   expand_insn (icode, 2, ops);
   2476  1.1  mrg   return ops[0].value;
   2477  1.1  mrg }
   2478  1.1  mrg 
   2479  1.1  mrg /* Expand an expression EXP as fpsr or fpcr setter (depending on
   2480  1.1  mrg    UNSPEC) using MODE.  */
   2481  1.1  mrg static void
   2482  1.1  mrg aarch64_expand_fpsr_fpcr_setter (int unspec, machine_mode mode, tree exp)
   2483  1.1  mrg {
   2484  1.1  mrg   tree arg = CALL_EXPR_ARG (exp, 0);
   2485  1.1  mrg   rtx op = force_reg (mode, expand_normal (arg));
   2486  1.1  mrg   emit_insn (gen_aarch64_set (unspec, mode, op));
   2487  1.1  mrg }
   2488  1.1  mrg 
   2489  1.1  mrg /* Expand a fpsr or fpcr getter (depending on UNSPEC) using MODE.
   2490  1.1  mrg    Return the target.  */
   2491  1.1  mrg static rtx
   2492  1.1  mrg aarch64_expand_fpsr_fpcr_getter (enum insn_code icode, machine_mode mode,
   2493  1.1  mrg 				 rtx target)
   2494  1.1  mrg {
   2495  1.1  mrg   expand_operand op;
   2496  1.1  mrg   create_output_operand (&op, target, mode);
   2497  1.1  mrg   expand_insn (icode, 1, &op);
   2498  1.1  mrg   return op.value;
   2499  1.1  mrg }
   2500  1.1  mrg 
   2501  1.1  mrg /* Expand an expression EXP that calls built-in function FCODE,
   2502  1.1  mrg    with result going to TARGET if that's convenient.  IGNORE is true
   2503  1.1  mrg    if the result of the builtin is ignored.  */
   2504  1.1  mrg rtx
   2505  1.1  mrg aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
   2506  1.1  mrg 				int ignore)
   2507  1.1  mrg {
   2508  1.1  mrg   int icode;
   2509  1.1  mrg   rtx op0;
   2510  1.1  mrg   tree arg0;
   2511  1.1  mrg 
   2512  1.1  mrg   switch (fcode)
   2513  1.1  mrg     {
   2514  1.1  mrg     case AARCH64_BUILTIN_GET_FPCR:
   2515  1.1  mrg       return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrsi,
   2516  1.1  mrg 					      SImode, target);
   2517  1.1  mrg     case AARCH64_BUILTIN_SET_FPCR:
   2518  1.1  mrg       aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, SImode, exp);
   2519  1.1  mrg       return target;
   2520  1.1  mrg     case AARCH64_BUILTIN_GET_FPSR:
   2521  1.1  mrg       return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrsi,
   2522  1.1  mrg 					      SImode, target);
   2523  1.1  mrg     case AARCH64_BUILTIN_SET_FPSR:
   2524  1.1  mrg       aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, SImode, exp);
   2525  1.1  mrg       return target;
   2526  1.1  mrg     case AARCH64_BUILTIN_GET_FPCR64:
   2527  1.1  mrg       return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrdi,
   2528  1.1  mrg 					      DImode, target);
   2529  1.1  mrg     case AARCH64_BUILTIN_SET_FPCR64:
   2530  1.1  mrg       aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, DImode, exp);
   2531  1.1  mrg       return target;
   2532  1.1  mrg     case AARCH64_BUILTIN_GET_FPSR64:
   2533  1.1  mrg       return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrdi,
   2534  1.1  mrg 					      DImode, target);
   2535  1.1  mrg     case AARCH64_BUILTIN_SET_FPSR64:
   2536  1.1  mrg       aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, DImode, exp);
   2537  1.1  mrg       return target;
   2538  1.1  mrg     case AARCH64_PAUTH_BUILTIN_AUTIA1716:
   2539  1.1  mrg     case AARCH64_PAUTH_BUILTIN_PACIA1716:
   2540  1.1  mrg     case AARCH64_PAUTH_BUILTIN_AUTIB1716:
   2541  1.1  mrg     case AARCH64_PAUTH_BUILTIN_PACIB1716:
   2542  1.1  mrg     case AARCH64_PAUTH_BUILTIN_XPACLRI:
   2543  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   2544  1.1  mrg       op0 = force_reg (Pmode, expand_normal (arg0));
   2545  1.1  mrg 
   2546  1.1  mrg       if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
   2547  1.1  mrg 	{
   2548  1.1  mrg 	  rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
   2549  1.1  mrg 	  icode = CODE_FOR_xpaclri;
   2550  1.1  mrg 	  emit_move_insn (lr, op0);
   2551  1.1  mrg 	  emit_insn (GEN_FCN (icode) ());
   2552  1.1  mrg 	  return lr;
   2553  1.1  mrg 	}
   2554  1.1  mrg       else
   2555  1.1  mrg 	{
   2556  1.1  mrg 	  tree arg1 = CALL_EXPR_ARG (exp, 1);
   2557  1.1  mrg 	  rtx op1 = force_reg (Pmode, expand_normal (arg1));
   2558  1.1  mrg 	  switch (fcode)
   2559  1.1  mrg 	    {
   2560  1.1  mrg 	    case AARCH64_PAUTH_BUILTIN_AUTIA1716:
   2561  1.1  mrg 	      icode = CODE_FOR_autia1716;
   2562  1.1  mrg 	      break;
   2563  1.1  mrg 	    case AARCH64_PAUTH_BUILTIN_AUTIB1716:
   2564  1.1  mrg 	      icode = CODE_FOR_autib1716;
   2565  1.1  mrg 	      break;
   2566  1.1  mrg 	    case AARCH64_PAUTH_BUILTIN_PACIA1716:
   2567  1.1  mrg 	      icode = CODE_FOR_pacia1716;
   2568  1.1  mrg 	      break;
   2569  1.1  mrg 	    case AARCH64_PAUTH_BUILTIN_PACIB1716:
   2570  1.1  mrg 	      icode = CODE_FOR_pacib1716;
   2571  1.1  mrg 	      break;
   2572  1.1  mrg 	    default:
   2573  1.1  mrg 	      icode = 0;
   2574  1.1  mrg 	      gcc_unreachable ();
   2575  1.1  mrg 	    }
   2576  1.1  mrg 
   2577  1.1  mrg 	  rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
   2578  1.1  mrg 	  rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
   2579  1.1  mrg 	  emit_move_insn (x17_reg, op0);
   2580  1.1  mrg 	  emit_move_insn (x16_reg, op1);
   2581  1.1  mrg 	  emit_insn (GEN_FCN (icode) ());
   2582  1.1  mrg 	  return x17_reg;
   2583  1.1  mrg 	}
   2584  1.1  mrg 
   2585  1.1  mrg     case AARCH64_JSCVT:
   2586  1.1  mrg       {
   2587  1.1  mrg 	expand_operand ops[2];
   2588  1.1  mrg 	create_output_operand (&ops[0], target, SImode);
   2589  1.1  mrg 	op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2590  1.1  mrg 	create_input_operand (&ops[1], op0, DFmode);
   2591  1.1  mrg 	expand_insn (CODE_FOR_aarch64_fjcvtzs, 2, ops);
   2592  1.1  mrg 	return ops[0].value;
   2593  1.1  mrg       }
   2594  1.1  mrg 
   2595  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF:
   2596  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF:
   2597  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF:
   2598  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V2SF:
   2599  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V4HF:
   2600  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V4HF:
   2601  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF:
   2602  1.1  mrg     case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF:
   2603  1.1  mrg       return aarch64_expand_fcmla_builtin (exp, target, fcode);
   2604  1.1  mrg     case AARCH64_BUILTIN_RNG_RNDR:
   2605  1.1  mrg     case AARCH64_BUILTIN_RNG_RNDRRS:
   2606  1.1  mrg       return aarch64_expand_rng_builtin (exp, target, fcode, ignore);
   2607  1.1  mrg     }
   2608  1.1  mrg 
   2609  1.1  mrg   if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
   2610  1.1  mrg     return aarch64_simd_expand_builtin (fcode, exp, target);
   2611  1.1  mrg   else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
   2612  1.1  mrg     return aarch64_crc32_expand_builtin (fcode, exp, target);
   2613  1.1  mrg 
   2614  1.1  mrg   if (fcode == AARCH64_BUILTIN_RSQRT_DF
   2615  1.1  mrg       || fcode == AARCH64_BUILTIN_RSQRT_SF
   2616  1.1  mrg       || fcode == AARCH64_BUILTIN_RSQRT_V2DF
   2617  1.1  mrg       || fcode == AARCH64_BUILTIN_RSQRT_V2SF
   2618  1.1  mrg       || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
   2619  1.1  mrg     return aarch64_expand_builtin_rsqrt (fcode, exp, target);
   2620  1.1  mrg 
   2621  1.1  mrg   if (fcode == AARCH64_TME_BUILTIN_TSTART
   2622  1.1  mrg       || fcode == AARCH64_TME_BUILTIN_TCOMMIT
   2623  1.1  mrg       || fcode == AARCH64_TME_BUILTIN_TTEST
   2624  1.1  mrg       || fcode == AARCH64_TME_BUILTIN_TCANCEL)
   2625  1.1  mrg     return aarch64_expand_builtin_tme (fcode, exp, target);
   2626  1.1  mrg 
   2627  1.1  mrg   if (fcode == AARCH64_LS64_BUILTIN_LD64B
   2628  1.1  mrg       || fcode == AARCH64_LS64_BUILTIN_ST64B
   2629  1.1  mrg       || fcode == AARCH64_LS64_BUILTIN_ST64BV
   2630  1.1  mrg       || fcode == AARCH64_LS64_BUILTIN_ST64BV0)
   2631  1.1  mrg     return aarch64_expand_builtin_ls64 (fcode, exp, target);
   2632  1.1  mrg 
   2633  1.1  mrg   if (fcode >= AARCH64_MEMTAG_BUILTIN_START
   2634  1.1  mrg       && fcode <= AARCH64_MEMTAG_BUILTIN_END)
   2635  1.1  mrg     return aarch64_expand_builtin_memtag (fcode, exp, target);
   2636  1.1  mrg   if (fcode >= AARCH64_REV16
   2637  1.1  mrg       && fcode <= AARCH64_RBITLL)
   2638  1.1  mrg     return aarch64_expand_builtin_data_intrinsic (fcode, exp, target);
   2639  1.1  mrg 
   2640  1.1  mrg   gcc_unreachable ();
   2641  1.1  mrg }
   2642  1.1  mrg 
   2643  1.1  mrg tree
   2644  1.1  mrg aarch64_builtin_vectorized_function (unsigned int fn, tree type_out,
   2645  1.1  mrg 				     tree type_in)
   2646  1.1  mrg {
   2647  1.1  mrg   machine_mode in_mode, out_mode;
   2648  1.1  mrg 
   2649  1.1  mrg   if (TREE_CODE (type_out) != VECTOR_TYPE
   2650  1.1  mrg       || TREE_CODE (type_in) != VECTOR_TYPE)
   2651  1.1  mrg     return NULL_TREE;
   2652  1.1  mrg 
   2653  1.1  mrg   out_mode = TYPE_MODE (type_out);
   2654  1.1  mrg   in_mode = TYPE_MODE (type_in);
   2655  1.1  mrg 
   2656  1.1  mrg #undef AARCH64_CHECK_BUILTIN_MODE
   2657  1.1  mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
   2658  1.1  mrg #define AARCH64_FIND_FRINT_VARIANT(N) \
   2659  1.1  mrg   (AARCH64_CHECK_BUILTIN_MODE (2, D) \
   2660  1.1  mrg     ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
   2661  1.1  mrg     : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
   2662  1.1  mrg 	? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
   2663  1.1  mrg 	: (AARCH64_CHECK_BUILTIN_MODE (2, S) \
   2664  1.1  mrg 	   ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
   2665  1.1  mrg 	   : NULL_TREE)))
   2666  1.1  mrg   switch (fn)
   2667  1.1  mrg     {
   2668  1.1  mrg #undef AARCH64_CHECK_BUILTIN_MODE
   2669  1.1  mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
   2670  1.1  mrg   (out_mode == V##C##N##Fmode && in_mode == V##C##N##Fmode)
   2671  1.1  mrg     CASE_CFN_FLOOR:
   2672  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (floor);
   2673  1.1  mrg     CASE_CFN_CEIL:
   2674  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (ceil);
   2675  1.1  mrg     CASE_CFN_TRUNC:
   2676  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (btrunc);
   2677  1.1  mrg     CASE_CFN_ROUND:
   2678  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (round);
   2679  1.1  mrg     CASE_CFN_NEARBYINT:
   2680  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (nearbyint);
   2681  1.1  mrg     CASE_CFN_SQRT:
   2682  1.1  mrg       return AARCH64_FIND_FRINT_VARIANT (sqrt);
   2683  1.1  mrg #undef AARCH64_CHECK_BUILTIN_MODE
   2684  1.1  mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
   2685  1.1  mrg   (out_mode == V##C##SImode && in_mode == V##C##N##Imode)
   2686  1.1  mrg     CASE_CFN_CLZ:
   2687  1.1  mrg       {
   2688  1.1  mrg 	if (AARCH64_CHECK_BUILTIN_MODE (4, S))
   2689  1.1  mrg 	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
   2690  1.1  mrg 	return NULL_TREE;
   2691  1.1  mrg       }
   2692  1.1  mrg     CASE_CFN_CTZ:
   2693  1.1  mrg       {
   2694  1.1  mrg 	if (AARCH64_CHECK_BUILTIN_MODE (2, S))
   2695  1.1  mrg 	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
   2696  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
   2697  1.1  mrg 	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
   2698  1.1  mrg 	return NULL_TREE;
   2699  1.1  mrg       }
   2700  1.1  mrg #undef AARCH64_CHECK_BUILTIN_MODE
   2701  1.1  mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
   2702  1.1  mrg   (out_mode == V##C##N##Imode && in_mode == V##C##N##Fmode)
   2703  1.1  mrg     CASE_CFN_IFLOOR:
   2704  1.1  mrg     CASE_CFN_LFLOOR:
   2705  1.1  mrg     CASE_CFN_LLFLOOR:
   2706  1.1  mrg       {
   2707  1.1  mrg 	enum aarch64_builtins builtin;
   2708  1.1  mrg 	if (AARCH64_CHECK_BUILTIN_MODE (2, D))
   2709  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
   2710  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
   2711  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
   2712  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
   2713  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
   2714  1.1  mrg 	else
   2715  1.1  mrg 	  return NULL_TREE;
   2716  1.1  mrg 
   2717  1.1  mrg 	return aarch64_builtin_decls[builtin];
   2718  1.1  mrg       }
   2719  1.1  mrg     CASE_CFN_ICEIL:
   2720  1.1  mrg     CASE_CFN_LCEIL:
   2721  1.1  mrg     CASE_CFN_LLCEIL:
   2722  1.1  mrg       {
   2723  1.1  mrg 	enum aarch64_builtins builtin;
   2724  1.1  mrg 	if (AARCH64_CHECK_BUILTIN_MODE (2, D))
   2725  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
   2726  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
   2727  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
   2728  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
   2729  1.1  mrg 	  builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
   2730  1.1  mrg 	else
   2731  1.1  mrg 	  return NULL_TREE;
   2732  1.1  mrg 
   2733  1.1  mrg 	return aarch64_builtin_decls[builtin];
   2734  1.1  mrg       }
   2735  1.1  mrg     CASE_CFN_IROUND:
   2736  1.1  mrg     CASE_CFN_LROUND:
   2737  1.1  mrg     CASE_CFN_LLROUND:
   2738  1.1  mrg       {
   2739  1.1  mrg 	enum aarch64_builtins builtin;
   2740  1.1  mrg 	if (AARCH64_CHECK_BUILTIN_MODE (2, D))
   2741  1.1  mrg 	  builtin =	AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
   2742  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
   2743  1.1  mrg 	  builtin =	AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
   2744  1.1  mrg 	else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
   2745  1.1  mrg 	  builtin =	AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
   2746  1.1  mrg 	else
   2747  1.1  mrg 	  return NULL_TREE;
   2748  1.1  mrg 
   2749  1.1  mrg 	return aarch64_builtin_decls[builtin];
   2750  1.1  mrg       }
   2751  1.1  mrg     default:
   2752  1.1  mrg       return NULL_TREE;
   2753  1.1  mrg     }
   2754  1.1  mrg 
   2755  1.1  mrg   return NULL_TREE;
   2756  1.1  mrg }
   2757  1.1  mrg 
   2758  1.1  mrg /* Return builtin for reciprocal square root.  */
   2759  1.1  mrg 
   2760  1.1  mrg tree
   2761  1.1  mrg aarch64_general_builtin_rsqrt (unsigned int fn)
   2762  1.1  mrg {
   2763  1.1  mrg   if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
   2764  1.1  mrg     return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
   2765  1.1  mrg   if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
   2766  1.1  mrg     return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
   2767  1.1  mrg   if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
   2768  1.1  mrg     return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
   2769  1.1  mrg   return NULL_TREE;
   2770  1.1  mrg }
   2771  1.1  mrg 
   2772  1.1  mrg /* Return true if the lane check can be removed as there is no
   2773  1.1  mrg    error going to be emitted.  */
   2774  1.1  mrg static bool
   2775  1.1  mrg aarch64_fold_builtin_lane_check (tree arg0, tree arg1, tree arg2)
   2776  1.1  mrg {
   2777  1.1  mrg   if (TREE_CODE (arg0) != INTEGER_CST)
   2778  1.1  mrg     return false;
   2779  1.1  mrg   if (TREE_CODE (arg1) != INTEGER_CST)
   2780  1.1  mrg     return false;
   2781  1.1  mrg   if (TREE_CODE (arg2) != INTEGER_CST)
   2782  1.1  mrg     return false;
   2783  1.1  mrg 
   2784  1.1  mrg   auto totalsize = wi::to_widest (arg0);
   2785  1.1  mrg   auto elementsize = wi::to_widest (arg1);
   2786  1.1  mrg   if (totalsize == 0 || elementsize == 0)
   2787  1.1  mrg     return false;
   2788  1.1  mrg   auto lane = wi::to_widest (arg2);
   2789  1.1  mrg   auto high = wi::udiv_trunc (totalsize, elementsize);
   2790  1.1  mrg   return wi::ltu_p (lane, high);
   2791  1.1  mrg }
   2792  1.1  mrg 
   2793  1.1  mrg #undef VAR1
   2794  1.1  mrg #define VAR1(T, N, MAP, FLAG, A) \
   2795  1.1  mrg   case AARCH64_SIMD_BUILTIN_##T##_##N##A:
   2796  1.1  mrg 
   2797  1.1  mrg /* Try to fold a call to the built-in function with subcode FCODE.  The
   2798  1.1  mrg    function is passed the N_ARGS arguments in ARGS and it returns a value
   2799  1.1  mrg    of type TYPE.  Return the new expression on success and NULL_TREE on
   2800  1.1  mrg    failure.  */
   2801  1.1  mrg tree
   2802  1.1  mrg aarch64_general_fold_builtin (unsigned int fcode, tree type,
   2803  1.1  mrg 			      unsigned int n_args ATTRIBUTE_UNUSED, tree *args)
   2804  1.1  mrg {
   2805  1.1  mrg   switch (fcode)
   2806  1.1  mrg     {
   2807  1.1  mrg       BUILTIN_VDQF (UNOP, abs, 2, ALL)
   2808  1.1  mrg 	return fold_build1 (ABS_EXPR, type, args[0]);
   2809  1.1  mrg       VAR1 (UNOP, floatv2si, 2, ALL, v2sf)
   2810  1.1  mrg       VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
   2811  1.1  mrg       VAR1 (UNOP, floatv2di, 2, ALL, v2df)
   2812  1.1  mrg 	return fold_build1 (FLOAT_EXPR, type, args[0]);
   2813  1.1  mrg       case AARCH64_SIMD_BUILTIN_LANE_CHECK:
   2814  1.1  mrg 	gcc_assert (n_args == 3);
   2815  1.1  mrg 	if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
   2816  1.1  mrg 	  return void_node;
   2817  1.1  mrg 	break;
   2818  1.1  mrg       default:
   2819  1.1  mrg 	break;
   2820  1.1  mrg     }
   2821  1.1  mrg 
   2822  1.1  mrg   return NULL_TREE;
   2823  1.1  mrg }
   2824  1.1  mrg 
   2825  1.1  mrg enum aarch64_simd_type
   2826  1.1  mrg get_mem_type_for_load_store (unsigned int fcode)
   2827  1.1  mrg {
   2828  1.1  mrg   switch (fcode)
   2829  1.1  mrg   {
   2830  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v8qi)
   2831  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v8qi)
   2832  1.1  mrg       return Int8x8_t;
   2833  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v16qi)
   2834  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v16qi)
   2835  1.1  mrg       return Int8x16_t;
   2836  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v4hi)
   2837  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v4hi)
   2838  1.1  mrg       return Int16x4_t;
   2839  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v8hi)
   2840  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v8hi)
   2841  1.1  mrg       return Int16x8_t;
   2842  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v2si)
   2843  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v2si)
   2844  1.1  mrg       return Int32x2_t;
   2845  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v4si)
   2846  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v4si)
   2847  1.1  mrg       return Int32x4_t;
   2848  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v2di)
   2849  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v2di)
   2850  1.1  mrg       return Int64x2_t;
   2851  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v8qi)
   2852  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v8qi)
   2853  1.1  mrg       return Uint8x8_t;
   2854  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v16qi)
   2855  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v16qi)
   2856  1.1  mrg       return Uint8x16_t;
   2857  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v4hi)
   2858  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v4hi)
   2859  1.1  mrg       return Uint16x4_t;
   2860  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v8hi)
   2861  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v8hi)
   2862  1.1  mrg       return Uint16x8_t;
   2863  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v2si)
   2864  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v2si)
   2865  1.1  mrg       return Uint32x2_t;
   2866  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v4si)
   2867  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v4si)
   2868  1.1  mrg       return Uint32x4_t;
   2869  1.1  mrg     VAR1 (LOAD1_U, ld1, 0, LOAD, v2di)
   2870  1.1  mrg     VAR1 (STORE1_U, st1, 0, STORE, v2di)
   2871  1.1  mrg       return Uint64x2_t;
   2872  1.1  mrg     VAR1 (LOAD1_P, ld1, 0, LOAD, v8qi)
   2873  1.1  mrg     VAR1 (STORE1_P, st1, 0, STORE, v8qi)
   2874  1.1  mrg       return Poly8x8_t;
   2875  1.1  mrg     VAR1 (LOAD1_P, ld1, 0, LOAD, v16qi)
   2876  1.1  mrg     VAR1 (STORE1_P, st1, 0, STORE, v16qi)
   2877  1.1  mrg       return Poly8x16_t;
   2878  1.1  mrg     VAR1 (LOAD1_P, ld1, 0, LOAD, v4hi)
   2879  1.1  mrg     VAR1 (STORE1_P, st1, 0, STORE, v4hi)
   2880  1.1  mrg       return Poly16x4_t;
   2881  1.1  mrg     VAR1 (LOAD1_P, ld1, 0, LOAD, v8hi)
   2882  1.1  mrg     VAR1 (STORE1_P, st1, 0, STORE, v8hi)
   2883  1.1  mrg       return Poly16x8_t;
   2884  1.1  mrg     VAR1 (LOAD1_P, ld1, 0, LOAD, v2di)
   2885  1.1  mrg     VAR1 (STORE1_P, st1, 0, STORE, v2di)
   2886  1.1  mrg       return Poly64x2_t;
   2887  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v4hf)
   2888  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v4hf)
   2889  1.1  mrg       return Float16x4_t;
   2890  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v8hf)
   2891  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v8hf)
   2892  1.1  mrg       return Float16x8_t;
   2893  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v4bf)
   2894  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v4bf)
   2895  1.1  mrg       return Bfloat16x4_t;
   2896  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v8bf)
   2897  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v8bf)
   2898  1.1  mrg       return Bfloat16x8_t;
   2899  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v2sf)
   2900  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v2sf)
   2901  1.1  mrg       return Float32x2_t;
   2902  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v4sf)
   2903  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v4sf)
   2904  1.1  mrg       return Float32x4_t;
   2905  1.1  mrg     VAR1 (LOAD1, ld1, 0, LOAD, v2df)
   2906  1.1  mrg     VAR1 (STORE1, st1, 0, STORE, v2df)
   2907  1.1  mrg       return Float64x2_t;
   2908  1.1  mrg     default:
   2909  1.1  mrg       gcc_unreachable ();
   2910  1.1  mrg       break;
   2911  1.1  mrg   }
   2912  1.1  mrg }
   2913  1.1  mrg 
   2914  1.1  mrg /* We've seen a vector load from address ADDR.  Record it in
   2915  1.1  mrg    vector_load_decls, if appropriate.  */
   2916  1.1  mrg static void
   2917  1.1  mrg aarch64_record_vector_load_arg (tree addr)
   2918  1.1  mrg {
   2919  1.1  mrg   tree decl = aarch64_vector_load_decl (addr);
   2920  1.1  mrg   if (!decl)
   2921  1.1  mrg     return;
   2922  1.1  mrg   if (!cfun->machine->vector_load_decls)
   2923  1.1  mrg     cfun->machine->vector_load_decls = hash_set<tree>::create_ggc (31);
   2924  1.1  mrg   cfun->machine->vector_load_decls->add (decl);
   2925  1.1  mrg }
   2926  1.1  mrg 
   2927  1.1  mrg /* Try to fold STMT, given that it's a call to the built-in function with
   2928  1.1  mrg    subcode FCODE.  Return the new statement on success and null on
   2929  1.1  mrg    failure.  */
   2930  1.1  mrg gimple *
   2931  1.1  mrg aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt,
   2932  1.1  mrg 				     gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
   2933  1.1  mrg {
   2934  1.1  mrg   gimple *new_stmt = NULL;
   2935  1.1  mrg   unsigned nargs = gimple_call_num_args (stmt);
   2936  1.1  mrg   tree *args = (nargs > 0
   2937  1.1  mrg 		? gimple_call_arg_ptr (stmt, 0)
   2938  1.1  mrg 		: &error_mark_node);
   2939  1.1  mrg 
   2940  1.1  mrg   /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
   2941  1.1  mrg      and unsigned int; it will distinguish according to the types of
   2942  1.1  mrg      the arguments to the __builtin.  */
   2943  1.1  mrg   switch (fcode)
   2944  1.1  mrg     {
   2945  1.1  mrg       BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, ALL)
   2946  1.1  mrg 	new_stmt = gimple_build_call_internal (IFN_REDUC_PLUS,
   2947  1.1  mrg 					       1, args[0]);
   2948  1.1  mrg 	gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
   2949  1.1  mrg 	break;
   2950  1.1  mrg 
   2951  1.1  mrg       /* Lower sqrt builtins to gimple/internal function sqrt. */
   2952  1.1  mrg       BUILTIN_VHSDF_DF (UNOP, sqrt, 2, FP)
   2953  1.1  mrg 	new_stmt = gimple_build_call_internal (IFN_SQRT,
   2954  1.1  mrg 					       1, args[0]);
   2955  1.1  mrg 	gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
   2956  1.1  mrg 	break;
   2957  1.1  mrg 
   2958  1.1  mrg      /*lower store and load neon builtins to gimple.  */
   2959  1.1  mrg      BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD)
   2960  1.1  mrg      BUILTIN_VDQ_I (LOAD1_U, ld1, 0, LOAD)
   2961  1.1  mrg      BUILTIN_VALLP_NO_DI (LOAD1_P, ld1, 0, LOAD)
   2962  1.1  mrg 	/* Punt until after inlining, so that we stand more chance of
   2963  1.1  mrg 	   recording something meaningful in vector_load_decls.  */
   2964  1.1  mrg 	if (!cfun->after_inlining)
   2965  1.1  mrg 	  break;
   2966  1.1  mrg 	aarch64_record_vector_load_arg (args[0]);
   2967  1.1  mrg 	if (!BYTES_BIG_ENDIAN)
   2968  1.1  mrg 	  {
   2969  1.1  mrg 	    enum aarch64_simd_type mem_type
   2970  1.1  mrg 	      = get_mem_type_for_load_store(fcode);
   2971  1.1  mrg 	    aarch64_simd_type_info simd_type
   2972  1.1  mrg 	      = aarch64_simd_types[mem_type];
   2973  1.1  mrg 	    tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
   2974  1.1  mrg 							     VOIDmode, true);
   2975  1.1  mrg 	    tree zero = build_zero_cst (elt_ptr_type);
   2976  1.1  mrg 	    /* Use element type alignment.  */
   2977  1.1  mrg 	    tree access_type
   2978  1.1  mrg 	      = build_aligned_type (simd_type.itype,
   2979  1.1  mrg 				    TYPE_ALIGN (simd_type.eltype));
   2980  1.1  mrg 	    new_stmt
   2981  1.1  mrg 	      = gimple_build_assign (gimple_get_lhs (stmt),
   2982  1.1  mrg 				     fold_build2 (MEM_REF,
   2983  1.1  mrg 						  access_type,
   2984  1.1  mrg 						  args[0], zero));
   2985  1.1  mrg 	    gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   2986  1.1  mrg 	    gimple_set_vdef (new_stmt, gimple_vdef (stmt));
   2987  1.1  mrg 	  }
   2988  1.1  mrg 	break;
   2989  1.1  mrg 
   2990  1.1  mrg       BUILTIN_VALL_F16 (STORE1, st1, 0, STORE)
   2991  1.1  mrg       BUILTIN_VDQ_I (STORE1_U, st1, 0, STORE)
   2992  1.1  mrg       BUILTIN_VALLP_NO_DI (STORE1_P, st1, 0, STORE)
   2993  1.1  mrg 	if (!BYTES_BIG_ENDIAN)
   2994  1.1  mrg 	  {
   2995  1.1  mrg 	    enum aarch64_simd_type mem_type
   2996  1.1  mrg 	      = get_mem_type_for_load_store(fcode);
   2997  1.1  mrg 	    aarch64_simd_type_info simd_type
   2998  1.1  mrg 	      = aarch64_simd_types[mem_type];
   2999  1.1  mrg 	    tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
   3000  1.1  mrg 							     VOIDmode, true);
   3001  1.1  mrg 	    tree zero = build_zero_cst (elt_ptr_type);
   3002  1.1  mrg 	    /* Use element type alignment.  */
   3003  1.1  mrg 	    tree access_type
   3004  1.1  mrg 	      = build_aligned_type (simd_type.itype,
   3005  1.1  mrg 				    TYPE_ALIGN (simd_type.eltype));
   3006  1.1  mrg 	    new_stmt
   3007  1.1  mrg 	      = gimple_build_assign (fold_build2 (MEM_REF, access_type,
   3008  1.1  mrg 						  args[0], zero),
   3009  1.1  mrg 				     args[1]);
   3010  1.1  mrg 	    gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   3011  1.1  mrg 	    gimple_set_vdef (new_stmt, gimple_vdef (stmt));
   3012  1.1  mrg 	  }
   3013  1.1  mrg 	break;
   3014  1.1  mrg 
   3015  1.1  mrg       BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL)
   3016  1.1  mrg       BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL)
   3017  1.1  mrg 	new_stmt = gimple_build_call_internal (IFN_REDUC_MAX,
   3018  1.1  mrg 					       1, args[0]);
   3019  1.1  mrg 	gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
   3020  1.1  mrg 	break;
   3021  1.1  mrg       BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10, ALL)
   3022  1.1  mrg       BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10, ALL)
   3023  1.1  mrg 	new_stmt = gimple_build_call_internal (IFN_REDUC_MIN,
   3024  1.1  mrg 					       1, args[0]);
   3025  1.1  mrg 	gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
   3026  1.1  mrg 	break;
   3027  1.1  mrg       BUILTIN_VSDQ_I_DI (BINOP, ashl, 3, NONE)
   3028  1.1  mrg 	if (TREE_CODE (args[1]) == INTEGER_CST
   3029  1.1  mrg 	    && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
   3030  1.1  mrg 	  new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3031  1.1  mrg 					  LSHIFT_EXPR, args[0], args[1]);
   3032  1.1  mrg 	break;
   3033  1.1  mrg       BUILTIN_VSDQ_I_DI (BINOP, sshl, 0, NONE)
   3034  1.1  mrg       BUILTIN_VSDQ_I_DI (BINOP_UUS, ushl, 0, NONE)
   3035  1.1  mrg 	{
   3036  1.1  mrg 	  tree cst = args[1];
   3037  1.1  mrg 	  tree ctype = TREE_TYPE (cst);
   3038  1.1  mrg 	  /* Left shifts can be both scalar or vector, e.g. uint64x1_t is
   3039  1.1  mrg 	     treated as a scalar type not a vector one.  */
   3040  1.1  mrg 	  if ((cst = uniform_integer_cst_p (cst)) != NULL_TREE)
   3041  1.1  mrg 	    {
   3042  1.1  mrg 	      wide_int wcst = wi::to_wide (cst);
   3043  1.1  mrg 	      tree unit_ty = TREE_TYPE (cst);
   3044  1.1  mrg 
   3045  1.1  mrg 	      wide_int abs_cst = wi::abs (wcst);
   3046  1.1  mrg 	      if (wi::geu_p (abs_cst, element_precision (args[0])))
   3047  1.1  mrg 		break;
   3048  1.1  mrg 
   3049  1.1  mrg 	      if (wi::neg_p (wcst, TYPE_SIGN (ctype)))
   3050  1.1  mrg 		{
   3051  1.1  mrg 		  tree final_cst;
   3052  1.1  mrg 		  final_cst = wide_int_to_tree (unit_ty, abs_cst);
   3053  1.1  mrg 		  if (TREE_CODE (cst) != INTEGER_CST)
   3054  1.1  mrg 		    final_cst = build_uniform_cst (ctype, final_cst);
   3055  1.1  mrg 
   3056  1.1  mrg 		  new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3057  1.1  mrg 						  RSHIFT_EXPR, args[0],
   3058  1.1  mrg 						  final_cst);
   3059  1.1  mrg 		}
   3060  1.1  mrg 	      else
   3061  1.1  mrg 		new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3062  1.1  mrg 						LSHIFT_EXPR, args[0], args[1]);
   3063  1.1  mrg 	    }
   3064  1.1  mrg 	}
   3065  1.1  mrg 	break;
   3066  1.1  mrg       BUILTIN_VDQ_I (SHIFTIMM, ashr, 3, NONE)
   3067  1.1  mrg       VAR1 (SHIFTIMM, ashr_simd, 0, NONE, di)
   3068  1.1  mrg       BUILTIN_VDQ_I (USHIFTIMM, lshr, 3, NONE)
   3069  1.1  mrg       VAR1 (USHIFTIMM, lshr_simd, 0, NONE, di)
   3070  1.1  mrg 	if (TREE_CODE (args[1]) == INTEGER_CST
   3071  1.1  mrg 	    && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
   3072  1.1  mrg 	  new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3073  1.1  mrg 					  RSHIFT_EXPR, args[0], args[1]);
   3074  1.1  mrg 	break;
   3075  1.1  mrg       BUILTIN_GPF (BINOP, fmulx, 0, ALL)
   3076  1.1  mrg 	{
   3077  1.1  mrg 	  gcc_assert (nargs == 2);
   3078  1.1  mrg 	  bool a0_cst_p = TREE_CODE (args[0]) == REAL_CST;
   3079  1.1  mrg 	  bool a1_cst_p = TREE_CODE (args[1]) == REAL_CST;
   3080  1.1  mrg 	  if (a0_cst_p || a1_cst_p)
   3081  1.1  mrg 	    {
   3082  1.1  mrg 	      if (a0_cst_p && a1_cst_p)
   3083  1.1  mrg 		{
   3084  1.1  mrg 		  tree t0 = TREE_TYPE (args[0]);
   3085  1.1  mrg 		  real_value a0 = (TREE_REAL_CST (args[0]));
   3086  1.1  mrg 		  real_value a1 = (TREE_REAL_CST (args[1]));
   3087  1.1  mrg 		  if (real_equal (&a1, &dconst0))
   3088  1.1  mrg 		    std::swap (a0, a1);
   3089  1.1  mrg 		  /* According to real_equal (), +0 equals -0.  */
   3090  1.1  mrg 		  if (real_equal (&a0, &dconst0) && real_isinf (&a1))
   3091  1.1  mrg 		    {
   3092  1.1  mrg 		      real_value res = dconst2;
   3093  1.1  mrg 		      res.sign = a0.sign ^ a1.sign;
   3094  1.1  mrg 		      new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3095  1.1  mrg 						      REAL_CST,
   3096  1.1  mrg 						      build_real (t0, res));
   3097  1.1  mrg 		    }
   3098  1.1  mrg 		  else
   3099  1.1  mrg 		    new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3100  1.1  mrg 						    MULT_EXPR,
   3101  1.1  mrg 						    args[0], args[1]);
   3102  1.1  mrg 		}
   3103  1.1  mrg 	      else /* a0_cst_p ^ a1_cst_p.  */
   3104  1.1  mrg 		{
   3105  1.1  mrg 		  real_value const_part = a0_cst_p
   3106  1.1  mrg 		    ? TREE_REAL_CST (args[0]) : TREE_REAL_CST (args[1]);
   3107  1.1  mrg 		  if (!real_equal (&const_part, &dconst0)
   3108  1.1  mrg 		      && !real_isinf (&const_part))
   3109  1.1  mrg 		    new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
   3110  1.1  mrg 						    MULT_EXPR, args[0],
   3111  1.1  mrg 						    args[1]);
   3112  1.1  mrg 		}
   3113  1.1  mrg 	    }
   3114  1.1  mrg 	  if (new_stmt)
   3115  1.1  mrg 	    {
   3116  1.1  mrg 	      gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   3117  1.1  mrg 	      gimple_set_vdef (new_stmt, gimple_vdef (stmt));
   3118  1.1  mrg 	    }
   3119  1.1  mrg 	  break;
   3120  1.1  mrg 	}
   3121  1.1  mrg     case AARCH64_SIMD_BUILTIN_LANE_CHECK:
   3122  1.1  mrg       if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
   3123  1.1  mrg 	{
   3124  1.1  mrg 	  unlink_stmt_vdef (stmt);
   3125  1.1  mrg 	  release_defs (stmt);
   3126  1.1  mrg 	  new_stmt = gimple_build_nop ();
   3127  1.1  mrg 	}
   3128  1.1  mrg       break;
   3129  1.1  mrg     default:
   3130  1.1  mrg       break;
   3131  1.1  mrg     }
   3132  1.1  mrg   return new_stmt;
   3133  1.1  mrg }
   3134  1.1  mrg 
   3135  1.1  mrg void
   3136  1.1  mrg aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
   3137  1.1  mrg {
   3138  1.1  mrg   const unsigned AARCH64_FE_INVALID = 1;
   3139  1.1  mrg   const unsigned AARCH64_FE_DIVBYZERO = 2;
   3140  1.1  mrg   const unsigned AARCH64_FE_OVERFLOW = 4;
   3141  1.1  mrg   const unsigned AARCH64_FE_UNDERFLOW = 8;
   3142  1.1  mrg   const unsigned AARCH64_FE_INEXACT = 16;
   3143  1.1  mrg   const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
   3144  1.1  mrg 							| AARCH64_FE_DIVBYZERO
   3145  1.1  mrg 							| AARCH64_FE_OVERFLOW
   3146  1.1  mrg 							| AARCH64_FE_UNDERFLOW
   3147  1.1  mrg 							| AARCH64_FE_INEXACT);
   3148  1.1  mrg   const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
   3149  1.1  mrg   tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
   3150  1.1  mrg   tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
   3151  1.1  mrg   tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
   3152  1.1  mrg   tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
   3153  1.1  mrg 
   3154  1.1  mrg   /* Generate the equivalence of :
   3155  1.1  mrg        unsigned int fenv_cr;
   3156  1.1  mrg        fenv_cr = __builtin_aarch64_get_fpcr ();
   3157  1.1  mrg 
   3158  1.1  mrg        unsigned int fenv_sr;
   3159  1.1  mrg        fenv_sr = __builtin_aarch64_get_fpsr ();
   3160  1.1  mrg 
   3161  1.1  mrg        Now set all exceptions to non-stop
   3162  1.1  mrg        unsigned int mask_cr
   3163  1.1  mrg 		= ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
   3164  1.1  mrg        unsigned int masked_cr;
   3165  1.1  mrg        masked_cr = fenv_cr & mask_cr;
   3166  1.1  mrg 
   3167  1.1  mrg        And clear all exception flags
   3168  1.1  mrg        unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
   3169  1.1  mrg        unsigned int masked_cr;
   3170  1.1  mrg        masked_sr = fenv_sr & mask_sr;
   3171  1.1  mrg 
   3172  1.1  mrg        __builtin_aarch64_set_cr (masked_cr);
   3173  1.1  mrg        __builtin_aarch64_set_sr (masked_sr);  */
   3174  1.1  mrg 
   3175  1.1  mrg   fenv_cr = create_tmp_var_raw (unsigned_type_node);
   3176  1.1  mrg   fenv_sr = create_tmp_var_raw (unsigned_type_node);
   3177  1.1  mrg 
   3178  1.1  mrg   get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
   3179  1.1  mrg   set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
   3180  1.1  mrg   get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
   3181  1.1  mrg   set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
   3182  1.1  mrg 
   3183  1.1  mrg   mask_cr = build_int_cst (unsigned_type_node,
   3184  1.1  mrg 			   ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
   3185  1.1  mrg   mask_sr = build_int_cst (unsigned_type_node,
   3186  1.1  mrg 			   ~(AARCH64_FE_ALL_EXCEPT));
   3187  1.1  mrg 
   3188  1.1  mrg   ld_fenv_cr = build4 (TARGET_EXPR, unsigned_type_node,
   3189  1.1  mrg 		       fenv_cr, build_call_expr (get_fpcr, 0),
   3190  1.1  mrg 		       NULL_TREE, NULL_TREE);
   3191  1.1  mrg   ld_fenv_sr = build4 (TARGET_EXPR, unsigned_type_node,
   3192  1.1  mrg 		       fenv_sr, build_call_expr (get_fpsr, 0),
   3193  1.1  mrg 		       NULL_TREE, NULL_TREE);
   3194  1.1  mrg 
   3195  1.1  mrg   masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
   3196  1.1  mrg   masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
   3197  1.1  mrg 
   3198  1.1  mrg   hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
   3199  1.1  mrg   hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
   3200  1.1  mrg 
   3201  1.1  mrg   hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
   3202  1.1  mrg 			hold_fnclex_sr);
   3203  1.1  mrg   masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
   3204  1.1  mrg 			masked_fenv_sr);
   3205  1.1  mrg   ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
   3206  1.1  mrg 
   3207  1.1  mrg   *hold = build2 (COMPOUND_EXPR, void_type_node,
   3208  1.1  mrg 		  build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
   3209  1.1  mrg 		  hold_fnclex);
   3210  1.1  mrg 
   3211  1.1  mrg   /* Store the value of masked_fenv to clear the exceptions:
   3212  1.1  mrg      __builtin_aarch64_set_fpsr (masked_fenv_sr);  */
   3213  1.1  mrg 
   3214  1.1  mrg   *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
   3215  1.1  mrg 
   3216  1.1  mrg   /* Generate the equivalent of :
   3217  1.1  mrg        unsigned int new_fenv_var;
   3218  1.1  mrg        new_fenv_var = __builtin_aarch64_get_fpsr ();
   3219  1.1  mrg 
   3220  1.1  mrg        __builtin_aarch64_set_fpsr (fenv_sr);
   3221  1.1  mrg 
   3222  1.1  mrg        __atomic_feraiseexcept (new_fenv_var);  */
   3223  1.1  mrg 
   3224  1.1  mrg   new_fenv_var = create_tmp_var_raw (unsigned_type_node);
   3225  1.1  mrg   reload_fenv = build4 (TARGET_EXPR, unsigned_type_node,
   3226  1.1  mrg 			new_fenv_var, build_call_expr (get_fpsr, 0),
   3227  1.1  mrg 			NULL_TREE, NULL_TREE);
   3228  1.1  mrg   restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
   3229  1.1  mrg   atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
   3230  1.1  mrg   update_call = build_call_expr (atomic_feraiseexcept, 1,
   3231  1.1  mrg 				 fold_convert (integer_type_node, new_fenv_var));
   3232  1.1  mrg   *update = build2 (COMPOUND_EXPR, void_type_node,
   3233  1.1  mrg 		    build2 (COMPOUND_EXPR, void_type_node,
   3234  1.1  mrg 			    reload_fenv, restore_fnenv), update_call);
   3235  1.1  mrg }
   3236  1.1  mrg 
   3237  1.1  mrg /* Resolve overloaded MEMTAG build-in functions.  */
   3238  1.1  mrg #define AARCH64_BUILTIN_SUBCODE(F) \
   3239  1.1  mrg   (DECL_MD_FUNCTION_CODE (F) >> AARCH64_BUILTIN_SHIFT)
   3240  1.1  mrg 
   3241  1.1  mrg static tree
   3242  1.1  mrg aarch64_resolve_overloaded_memtag (location_t loc,
   3243  1.1  mrg 				   tree fndecl, void *pass_params)
   3244  1.1  mrg {
   3245  1.1  mrg   vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (pass_params);
   3246  1.1  mrg   unsigned param_num = params ? params->length() : 0;
   3247  1.1  mrg   unsigned int fcode = AARCH64_BUILTIN_SUBCODE (fndecl);
   3248  1.1  mrg   tree inittype = aarch64_memtag_builtin_data[
   3249  1.1  mrg 		    fcode - AARCH64_MEMTAG_BUILTIN_START - 1].ftype;
   3250  1.1  mrg   unsigned arg_num = list_length (TYPE_ARG_TYPES (inittype)) - 1;
   3251  1.1  mrg 
   3252  1.1  mrg   if (param_num != arg_num)
   3253  1.1  mrg     {
   3254  1.1  mrg       TREE_TYPE (fndecl) = inittype;
   3255  1.1  mrg       return NULL_TREE;
   3256  1.1  mrg     }
   3257  1.1  mrg   tree retype = NULL;
   3258  1.1  mrg 
   3259  1.1  mrg   if (fcode == AARCH64_MEMTAG_BUILTIN_SUBP)
   3260  1.1  mrg     {
   3261  1.1  mrg       tree t0 = TREE_TYPE ((*params)[0]);
   3262  1.1  mrg       tree t1 = TREE_TYPE ((*params)[1]);
   3263  1.1  mrg 
   3264  1.1  mrg       if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
   3265  1.1  mrg 	t0 = ptr_type_node;
   3266  1.1  mrg       if (t1 == error_mark_node || TREE_CODE (t1) != POINTER_TYPE)
   3267  1.1  mrg 	t1 = ptr_type_node;
   3268  1.1  mrg 
   3269  1.1  mrg       if (TYPE_MODE (t0) != DImode)
   3270  1.1  mrg 	warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
   3271  1.1  mrg 	    (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
   3272  1.1  mrg 
   3273  1.1  mrg       if (TYPE_MODE (t1) != DImode)
   3274  1.1  mrg 	warning_at (loc, 1, "expected 64-bit address but argument 2 is %d-bit",
   3275  1.1  mrg 	    (int)tree_to_shwi (DECL_SIZE ((*params)[1])));
   3276  1.1  mrg 
   3277  1.1  mrg       retype = build_function_type_list (ptrdiff_type_node, t0, t1, NULL);
   3278  1.1  mrg     }
   3279  1.1  mrg   else
   3280  1.1  mrg     {
   3281  1.1  mrg       tree t0 = TREE_TYPE ((*params)[0]);
   3282  1.1  mrg 
   3283  1.1  mrg       if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
   3284  1.1  mrg 	{
   3285  1.1  mrg 	  TREE_TYPE (fndecl) = inittype;
   3286  1.1  mrg 	  return NULL_TREE;
   3287  1.1  mrg 	}
   3288  1.1  mrg 
   3289  1.1  mrg       if (TYPE_MODE (t0) != DImode)
   3290  1.1  mrg 	warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
   3291  1.1  mrg 	    (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
   3292  1.1  mrg 
   3293  1.1  mrg       switch (fcode)
   3294  1.1  mrg 	{
   3295  1.1  mrg 	case AARCH64_MEMTAG_BUILTIN_IRG:
   3296  1.1  mrg 	  retype = build_function_type_list (t0, t0, uint64_type_node, NULL);
   3297  1.1  mrg 	  break;
   3298  1.1  mrg 	case AARCH64_MEMTAG_BUILTIN_GMI:
   3299  1.1  mrg 	  retype = build_function_type_list (uint64_type_node, t0,
   3300  1.1  mrg 	      uint64_type_node, NULL);
   3301  1.1  mrg 	  break;
   3302  1.1  mrg 	case AARCH64_MEMTAG_BUILTIN_INC_TAG:
   3303  1.1  mrg 	  retype = build_function_type_list (t0, t0, unsigned_type_node, NULL);
   3304  1.1  mrg 	  break;
   3305  1.1  mrg 	case AARCH64_MEMTAG_BUILTIN_SET_TAG:
   3306  1.1  mrg 	  retype = build_function_type_list (void_type_node, t0, NULL);
   3307  1.1  mrg 	  break;
   3308  1.1  mrg 	case AARCH64_MEMTAG_BUILTIN_GET_TAG:
   3309  1.1  mrg 	  retype = build_function_type_list (t0, t0, NULL);
   3310  1.1  mrg 	  break;
   3311  1.1  mrg 	default:
   3312  1.1  mrg 	  return NULL_TREE;
   3313  1.1  mrg 	}
   3314  1.1  mrg     }
   3315  1.1  mrg 
   3316  1.1  mrg   if (!retype || retype == error_mark_node)
   3317  1.1  mrg     TREE_TYPE (fndecl) = inittype;
   3318  1.1  mrg   else
   3319  1.1  mrg     TREE_TYPE (fndecl) = retype;
   3320  1.1  mrg 
   3321  1.1  mrg   return NULL_TREE;
   3322  1.1  mrg }
   3323  1.1  mrg 
   3324  1.1  mrg /* Called at aarch64_resolve_overloaded_builtin in aarch64-c.cc.  */
   3325  1.1  mrg tree
   3326  1.1  mrg aarch64_resolve_overloaded_builtin_general (location_t loc, tree function,
   3327  1.1  mrg 					    void *pass_params)
   3328  1.1  mrg {
   3329  1.1  mrg   unsigned int fcode = AARCH64_BUILTIN_SUBCODE (function);
   3330  1.1  mrg 
   3331  1.1  mrg   if (fcode >= AARCH64_MEMTAG_BUILTIN_START
   3332  1.1  mrg       && fcode <= AARCH64_MEMTAG_BUILTIN_END)
   3333  1.1  mrg     return aarch64_resolve_overloaded_memtag(loc, function, pass_params);
   3334  1.1  mrg 
   3335  1.1  mrg   return NULL_TREE;
   3336  1.1  mrg }
   3337  1.1  mrg 
   3338  1.1  mrg #undef AARCH64_CHECK_BUILTIN_MODE
   3339  1.1  mrg #undef AARCH64_FIND_FRINT_VARIANT
   3340  1.1  mrg #undef CF0
   3341  1.1  mrg #undef CF1
   3342  1.1  mrg #undef CF2
   3343  1.1  mrg #undef CF3
   3344  1.1  mrg #undef CF4
   3345  1.1  mrg #undef CF10
   3346  1.1  mrg #undef VAR1
   3347  1.1  mrg #undef VAR2
   3348  1.1  mrg #undef VAR3
   3349  1.1  mrg #undef VAR4
   3350  1.1  mrg #undef VAR5
   3351  1.1  mrg #undef VAR6
   3352  1.1  mrg #undef VAR7
   3353  1.1  mrg #undef VAR8
   3354  1.1  mrg #undef VAR9
   3355  1.1  mrg #undef VAR10
   3356  1.1  mrg #undef VAR11
   3357  1.1  mrg 
   3358  1.1  mrg #include "gt-aarch64-builtins.h"
   3359