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