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