1 1.1 mrg /* ACLE support for AArch64 SVE (function shapes) 2 1.1.1.2 mrg Copyright (C) 2018-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it 7 1.1 mrg under the terms of the GNU General Public License as published by 8 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg any later version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but 12 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 1.1 mrg General Public License for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg #include "config.h" 21 1.1 mrg #include "system.h" 22 1.1 mrg #include "coretypes.h" 23 1.1 mrg #include "tm.h" 24 1.1 mrg #include "tree.h" 25 1.1 mrg #include "rtl.h" 26 1.1 mrg #include "tm_p.h" 27 1.1 mrg #include "memmodel.h" 28 1.1 mrg #include "insn-codes.h" 29 1.1 mrg #include "optabs.h" 30 1.1 mrg #include "aarch64-sve-builtins.h" 31 1.1 mrg #include "aarch64-sve-builtins-shapes.h" 32 1.1 mrg 33 1.1 mrg /* In the comments below, _t0 represents the first type suffix and _t1 34 1.1 mrg represents the second. Square brackets enclose characters that are 35 1.1 mrg present in only the full name, not the overloaded name. Governing 36 1.1 mrg predicate arguments and predicate suffixes are not shown, since they 37 1.1 mrg depend on the predication type, which is a separate piece of 38 1.1 mrg information from the shape. 39 1.1 mrg 40 1.1 mrg Non-overloaded functions may have additional suffixes beyond the 41 1.1 mrg ones shown, if those suffixes don't affect the types in the type 42 1.1 mrg signature. E.g. the predicate form of svtrn1 has a _b<bits> suffix, 43 1.1 mrg but this does not affect the prototype, which is always 44 1.1 mrg "svbool_t(svbool_t, svbool_t)". */ 45 1.1 mrg 46 1.1 mrg namespace aarch64_sve { 47 1.1 mrg 48 1.1 mrg /* Return a representation of "const T *". */ 49 1.1 mrg static tree 50 1.1 mrg build_const_pointer (tree t) 51 1.1 mrg { 52 1.1 mrg return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST)); 53 1.1 mrg } 54 1.1 mrg 55 1.1 mrg /* If INSTANCE has a governing predicate, add it to the list of argument 56 1.1 mrg types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the 57 1.1 mrg function. */ 58 1.1 mrg static void 59 1.1 mrg apply_predication (const function_instance &instance, tree return_type, 60 1.1 mrg vec<tree> &argument_types) 61 1.1 mrg { 62 1.1 mrg if (instance.pred != PRED_none) 63 1.1 mrg { 64 1.1 mrg argument_types.quick_insert (0, get_svbool_t ()); 65 1.1 mrg /* For unary merge operations, the first argument is a vector with 66 1.1 mrg the same type as the result. For unary_convert_narrowt it also 67 1.1 mrg provides the "bottom" half of active elements, and is present 68 1.1 mrg for all types of predication. */ 69 1.1 mrg if ((argument_types.length () == 2 && instance.pred == PRED_m) 70 1.1 mrg || instance.shape == shapes::unary_convert_narrowt) 71 1.1 mrg argument_types.quick_insert (0, return_type); 72 1.1 mrg } 73 1.1 mrg } 74 1.1 mrg 75 1.1 mrg /* Parse and move past an element type in FORMAT and return it as a type 76 1.1 mrg suffix. The format is: 77 1.1 mrg 78 1.1 mrg [01] - the element type in type suffix 0 or 1 of INSTANCE 79 1.1 mrg f<bits> - a floating-point type with the given number of bits 80 1.1 mrg f[01] - a floating-point type with the same width as type suffix 0 or 1 81 1.1 mrg B - bfloat16_t 82 1.1 mrg h<elt> - a half-sized version of <elt> 83 1.1 mrg p - a predicate (represented as TYPE_SUFFIX_b) 84 1.1 mrg q<elt> - a quarter-sized version of <elt> 85 1.1 mrg s<bits> - a signed type with the given number of bits 86 1.1 mrg s[01] - a signed type with the same width as type suffix 0 or 1 87 1.1 mrg u<bits> - an unsigned type with the given number of bits 88 1.1 mrg u[01] - an unsigned type with the same width as type suffix 0 or 1 89 1.1 mrg w<elt> - a 64-bit version of <elt> if <elt> is integral, otherwise <elt> 90 1.1 mrg 91 1.1 mrg where <elt> is another element type. */ 92 1.1 mrg static type_suffix_index 93 1.1 mrg parse_element_type (const function_instance &instance, const char *&format) 94 1.1 mrg { 95 1.1 mrg int ch = *format++; 96 1.1 mrg 97 1.1 mrg if (ch == 'f' || ch == 's' || ch == 'u') 98 1.1 mrg { 99 1.1 mrg type_class_index tclass = (ch == 'f' ? TYPE_float 100 1.1 mrg : ch == 's' ? TYPE_signed 101 1.1 mrg : TYPE_unsigned); 102 1.1 mrg char *end; 103 1.1 mrg unsigned int bits = strtol (format, &end, 10); 104 1.1 mrg format = end; 105 1.1 mrg if (bits == 0 || bits == 1) 106 1.1 mrg bits = instance.type_suffix (bits).element_bits; 107 1.1 mrg return find_type_suffix (tclass, bits); 108 1.1 mrg } 109 1.1 mrg 110 1.1 mrg if (ch == 'w') 111 1.1 mrg { 112 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 113 1.1 mrg if (type_suffixes[suffix].integer_p) 114 1.1 mrg return find_type_suffix (type_suffixes[suffix].tclass, 64); 115 1.1 mrg return suffix; 116 1.1 mrg } 117 1.1 mrg 118 1.1 mrg if (ch == 'p') 119 1.1 mrg return TYPE_SUFFIX_b; 120 1.1 mrg 121 1.1 mrg if (ch == 'B') 122 1.1 mrg return TYPE_SUFFIX_bf16; 123 1.1 mrg 124 1.1 mrg if (ch == 'q') 125 1.1 mrg { 126 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 127 1.1 mrg return find_type_suffix (type_suffixes[suffix].tclass, 128 1.1 mrg type_suffixes[suffix].element_bits / 4); 129 1.1 mrg } 130 1.1 mrg 131 1.1 mrg if (ch == 'h') 132 1.1 mrg { 133 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 134 1.1 mrg /* Widening and narrowing doesn't change the type for predicates; 135 1.1 mrg everything's still an svbool_t. */ 136 1.1 mrg if (suffix == TYPE_SUFFIX_b) 137 1.1 mrg return suffix; 138 1.1 mrg return find_type_suffix (type_suffixes[suffix].tclass, 139 1.1 mrg type_suffixes[suffix].element_bits / 2); 140 1.1 mrg } 141 1.1 mrg 142 1.1 mrg if (ch == '0' || ch == '1') 143 1.1 mrg return instance.type_suffix_ids[ch - '0']; 144 1.1 mrg 145 1.1 mrg gcc_unreachable (); 146 1.1 mrg } 147 1.1 mrg 148 1.1 mrg /* Read and return a type from FORMAT for function INSTANCE. Advance 149 1.1 mrg FORMAT beyond the type string. The format is: 150 1.1 mrg 151 1.1 mrg _ - void 152 1.1 mrg al - array pointer for loads 153 1.1 mrg ap - array pointer for prefetches 154 1.1 mrg as - array pointer for stores 155 1.1 mrg b - base vector type (from a _<m0>base suffix) 156 1.1 mrg d - displacement vector type (from a _<m1>index or _<m1>offset suffix) 157 1.1 mrg e<name> - an enum with the given name 158 1.1 mrg s<elt> - a scalar type with the given element suffix 159 1.1 mrg t<elt> - a vector or tuple type with given element suffix [*1] 160 1.1 mrg v<elt> - a vector with the given element suffix 161 1.1 mrg 162 1.1 mrg where <elt> has the format described above parse_element_type 163 1.1 mrg 164 1.1 mrg [*1] the vectors_per_tuple function indicates whether the type should 165 1.1 mrg be a tuple, and if so, how many vectors it should contain. */ 166 1.1 mrg static tree 167 1.1 mrg parse_type (const function_instance &instance, const char *&format) 168 1.1 mrg { 169 1.1 mrg int ch = *format++; 170 1.1 mrg 171 1.1 mrg if (ch == '_') 172 1.1 mrg return void_type_node; 173 1.1 mrg 174 1.1 mrg if (ch == 'a') 175 1.1 mrg { 176 1.1 mrg ch = *format++; 177 1.1 mrg if (ch == 'l') 178 1.1 mrg return build_const_pointer (instance.memory_scalar_type ()); 179 1.1 mrg if (ch == 'p') 180 1.1 mrg return const_ptr_type_node; 181 1.1 mrg if (ch == 's') 182 1.1 mrg return build_pointer_type (instance.memory_scalar_type ()); 183 1.1 mrg gcc_unreachable (); 184 1.1 mrg } 185 1.1 mrg 186 1.1 mrg if (ch == 'b') 187 1.1 mrg return instance.base_vector_type (); 188 1.1 mrg 189 1.1 mrg if (ch == 'd') 190 1.1 mrg return instance.displacement_vector_type (); 191 1.1 mrg 192 1.1 mrg if (ch == 'e') 193 1.1 mrg { 194 1.1.1.2 mrg if (startswith (format, "pattern")) 195 1.1 mrg { 196 1.1 mrg format += 7; 197 1.1 mrg return acle_svpattern; 198 1.1 mrg } 199 1.1.1.2 mrg if (startswith (format, "prfop")) 200 1.1 mrg { 201 1.1 mrg format += 5; 202 1.1 mrg return acle_svprfop; 203 1.1 mrg } 204 1.1 mrg gcc_unreachable (); 205 1.1 mrg } 206 1.1 mrg 207 1.1 mrg if (ch == 's') 208 1.1 mrg { 209 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 210 1.1 mrg return scalar_types[type_suffixes[suffix].vector_type]; 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg if (ch == 't') 214 1.1 mrg { 215 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 216 1.1 mrg vector_type_index vector_type = type_suffixes[suffix].vector_type; 217 1.1 mrg unsigned int num_vectors = instance.vectors_per_tuple (); 218 1.1 mrg return acle_vector_types[num_vectors - 1][vector_type]; 219 1.1 mrg } 220 1.1 mrg 221 1.1 mrg if (ch == 'v') 222 1.1 mrg { 223 1.1 mrg type_suffix_index suffix = parse_element_type (instance, format); 224 1.1 mrg return acle_vector_types[0][type_suffixes[suffix].vector_type]; 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg gcc_unreachable (); 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg /* Read and move past any argument count at FORMAT for the function 231 1.1 mrg signature of INSTANCE. The counts are: 232 1.1 mrg 233 1.1 mrg *q: one argument per element in a 128-bit quadword (as for svdupq) 234 1.1 mrg *t: one argument per vector in a tuple (as for svcreate) 235 1.1 mrg 236 1.1 mrg Otherwise the count is 1. */ 237 1.1 mrg static unsigned int 238 1.1 mrg parse_count (const function_instance &instance, const char *&format) 239 1.1 mrg { 240 1.1 mrg if (format[0] == '*' && format[1] == 'q') 241 1.1 mrg { 242 1.1 mrg format += 2; 243 1.1 mrg return instance.elements_per_vq (0); 244 1.1 mrg } 245 1.1 mrg if (format[0] == '*' && format[1] == 't') 246 1.1 mrg { 247 1.1 mrg format += 2; 248 1.1 mrg return instance.vectors_per_tuple (); 249 1.1 mrg } 250 1.1 mrg return 1; 251 1.1 mrg } 252 1.1 mrg 253 1.1 mrg /* Read a type signature for INSTANCE from FORMAT. Add the argument types 254 1.1 mrg to ARGUMENT_TYPES and return the return type. 255 1.1 mrg 256 1.1 mrg The format is a comma-separated list of types (as for parse_type), 257 1.1 mrg with the first type being the return type and the rest being the 258 1.1 mrg argument types. Each argument type can be followed by an optional 259 1.1 mrg count (as for parse_count). */ 260 1.1 mrg static tree 261 1.1 mrg parse_signature (const function_instance &instance, const char *format, 262 1.1 mrg vec<tree> &argument_types) 263 1.1 mrg { 264 1.1 mrg tree return_type = parse_type (instance, format); 265 1.1 mrg while (format[0] == ',') 266 1.1 mrg { 267 1.1 mrg format += 1; 268 1.1 mrg tree argument_type = parse_type (instance, format); 269 1.1 mrg unsigned int count = parse_count (instance, format); 270 1.1 mrg for (unsigned int i = 0; i < count; ++i) 271 1.1 mrg argument_types.quick_push (argument_type); 272 1.1 mrg } 273 1.1 mrg gcc_assert (format[0] == 0); 274 1.1 mrg return return_type; 275 1.1 mrg } 276 1.1 mrg 277 1.1 mrg /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID, 278 1.1 mrg the type suffixes at index TI and the predication suffix at index PI. 279 1.1 mrg The other arguments are as for build_all. */ 280 1.1 mrg static void 281 1.1 mrg build_one (function_builder &b, const char *signature, 282 1.1 mrg const function_group_info &group, mode_suffix_index mode_suffix_id, 283 1.1 mrg unsigned int ti, unsigned int pi, bool force_direct_overloads) 284 1.1 mrg { 285 1.1 mrg /* Byte forms of svdupq take 16 arguments. */ 286 1.1 mrg auto_vec<tree, 16> argument_types; 287 1.1 mrg function_instance instance (group.base_name, *group.base, *group.shape, 288 1.1 mrg mode_suffix_id, group.types[ti], 289 1.1 mrg group.preds[pi]); 290 1.1 mrg tree return_type = parse_signature (instance, signature, argument_types); 291 1.1 mrg apply_predication (instance, return_type, argument_types); 292 1.1 mrg b.add_unique_function (instance, return_type, argument_types, 293 1.1 mrg group.required_extensions, force_direct_overloads); 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg /* GROUP describes some sort of gather or scatter operation. There are 297 1.1 mrg two cases: 298 1.1 mrg 299 1.1 mrg - If the function has any type suffixes (as for loads and stores), the 300 1.1 mrg first function type suffix specifies either a 32-bit or a 64-bit type, 301 1.1 mrg which in turn selects either MODE32 or MODE64 as the addressing mode. 302 1.1 mrg Add a function instance for every type and predicate combination 303 1.1 mrg in GROUP for which the associated addressing mode is not MODE_none. 304 1.1 mrg 305 1.1 mrg - If the function has no type suffixes (as for prefetches), add one 306 1.1 mrg MODE32 form and one MODE64 form for each predication type. 307 1.1 mrg 308 1.1 mrg The other arguments are as for build_all. */ 309 1.1 mrg static void 310 1.1 mrg build_32_64 (function_builder &b, const char *signature, 311 1.1 mrg const function_group_info &group, mode_suffix_index mode32, 312 1.1 mrg mode_suffix_index mode64, bool force_direct_overloads = false) 313 1.1 mrg { 314 1.1 mrg for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi) 315 1.1 mrg if (group.types[0][0] == NUM_TYPE_SUFFIXES) 316 1.1 mrg { 317 1.1 mrg gcc_assert (mode32 != MODE_none && mode64 != MODE_none); 318 1.1 mrg build_one (b, signature, group, mode32, 0, pi, 319 1.1 mrg force_direct_overloads); 320 1.1 mrg build_one (b, signature, group, mode64, 0, pi, 321 1.1 mrg force_direct_overloads); 322 1.1 mrg } 323 1.1 mrg else 324 1.1 mrg for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti) 325 1.1 mrg { 326 1.1 mrg unsigned int bits = type_suffixes[group.types[ti][0]].element_bits; 327 1.1 mrg gcc_assert (bits == 32 || bits == 64); 328 1.1 mrg mode_suffix_index mode = bits == 32 ? mode32 : mode64; 329 1.1 mrg if (mode != MODE_none) 330 1.1 mrg build_one (b, signature, group, mode, ti, pi, 331 1.1 mrg force_direct_overloads); 332 1.1 mrg } 333 1.1 mrg } 334 1.1 mrg 335 1.1 mrg /* For every type and predicate combination in GROUP, add one function 336 1.1 mrg that takes a scalar (pointer) base and a signed vector array index, 337 1.1 mrg and another that instead takes an unsigned vector array index. 338 1.1 mrg The vector array index has the same element size as the first 339 1.1 mrg function type suffix. SIGNATURE is as for build_all. */ 340 1.1 mrg static void 341 1.1 mrg build_sv_index (function_builder &b, const char *signature, 342 1.1 mrg const function_group_info &group) 343 1.1 mrg { 344 1.1 mrg build_32_64 (b, signature, group, MODE_s32index, MODE_s64index); 345 1.1 mrg build_32_64 (b, signature, group, MODE_u32index, MODE_u64index); 346 1.1 mrg } 347 1.1 mrg 348 1.1 mrg /* Like build_sv_index, but only handle 64-bit types. */ 349 1.1 mrg static void 350 1.1 mrg build_sv_index64 (function_builder &b, const char *signature, 351 1.1 mrg const function_group_info &group) 352 1.1 mrg { 353 1.1 mrg build_32_64 (b, signature, group, MODE_none, MODE_s64index); 354 1.1 mrg build_32_64 (b, signature, group, MODE_none, MODE_u64index); 355 1.1 mrg } 356 1.1 mrg 357 1.1 mrg /* Like build_sv_index, but taking vector byte offsets instead of vector 358 1.1 mrg array indices. */ 359 1.1 mrg static void 360 1.1 mrg build_sv_offset (function_builder &b, const char *signature, 361 1.1 mrg const function_group_info &group) 362 1.1 mrg { 363 1.1 mrg build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset); 364 1.1 mrg build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset); 365 1.1 mrg } 366 1.1 mrg 367 1.1 mrg /* Like build_sv_offset, but exclude offsets that must be interpreted 368 1.1 mrg as signed (i.e. s32offset). */ 369 1.1 mrg static void 370 1.1 mrg build_sv_uint_offset (function_builder &b, const char *signature, 371 1.1 mrg const function_group_info &group) 372 1.1 mrg { 373 1.1 mrg build_32_64 (b, signature, group, MODE_none, MODE_s64offset); 374 1.1 mrg build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset); 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg /* For every type and predicate combination in GROUP, add a function 378 1.1 mrg that takes a vector base address and no displacement. The vector 379 1.1 mrg base has the same element size as the first type suffix. 380 1.1 mrg 381 1.1 mrg The other arguments are as for build_all. */ 382 1.1 mrg static void 383 1.1 mrg build_v_base (function_builder &b, const char *signature, 384 1.1 mrg const function_group_info &group, 385 1.1 mrg bool force_direct_overloads = false) 386 1.1 mrg { 387 1.1 mrg build_32_64 (b, signature, group, MODE_u32base, MODE_u64base, 388 1.1 mrg force_direct_overloads); 389 1.1 mrg } 390 1.1 mrg 391 1.1 mrg /* Like build_v_base, but for functions that also take a scalar array 392 1.1 mrg index. */ 393 1.1 mrg static void 394 1.1 mrg build_vs_index (function_builder &b, const char *signature, 395 1.1 mrg const function_group_info &group, 396 1.1 mrg bool force_direct_overloads = false) 397 1.1 mrg { 398 1.1 mrg build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index, 399 1.1 mrg force_direct_overloads); 400 1.1 mrg } 401 1.1 mrg 402 1.1 mrg /* Like build_v_base, but for functions that also take a scalar byte 403 1.1 mrg offset. */ 404 1.1 mrg static void 405 1.1 mrg build_vs_offset (function_builder &b, const char *signature, 406 1.1 mrg const function_group_info &group, 407 1.1 mrg bool force_direct_overloads = false) 408 1.1 mrg { 409 1.1 mrg build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset, 410 1.1 mrg force_direct_overloads); 411 1.1 mrg } 412 1.1 mrg 413 1.1 mrg /* Add a function instance for every type and predicate combination 414 1.1 mrg in GROUP. Take the function base name from GROUP and the mode suffix 415 1.1 mrg from MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature 416 1.1 mrg without a governing predicate, then use apply_predication to add in the 417 1.1 mrg predicate. FORCE_DIRECT_OVERLOADS is true if there is a one-to-one 418 1.1 mrg mapping between "short" and "full" names, and if standard overload 419 1.1 mrg resolution therefore isn't necessary. */ 420 1.1 mrg static void 421 1.1 mrg build_all (function_builder &b, const char *signature, 422 1.1 mrg const function_group_info &group, mode_suffix_index mode_suffix_id, 423 1.1 mrg bool force_direct_overloads = false) 424 1.1 mrg { 425 1.1 mrg for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi) 426 1.1 mrg for (unsigned int ti = 0; 427 1.1 mrg ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti) 428 1.1 mrg build_one (b, signature, group, mode_suffix_id, ti, pi, 429 1.1 mrg force_direct_overloads); 430 1.1 mrg } 431 1.1 mrg 432 1.1 mrg /* TYPE is the largest type suffix associated with the arguments of R, 433 1.1 mrg but the result is twice as wide. Return the associated type suffix 434 1.1 mrg if it exists, otherwise report an appropriate error and return 435 1.1 mrg NUM_TYPE_SUFFIXES. */ 436 1.1 mrg static type_suffix_index 437 1.1 mrg long_type_suffix (function_resolver &r, type_suffix_index type) 438 1.1 mrg { 439 1.1 mrg unsigned int element_bits = type_suffixes[type].element_bits; 440 1.1 mrg if (type_suffixes[type].integer_p && element_bits < 64) 441 1.1 mrg return find_type_suffix (type_suffixes[type].tclass, element_bits * 2); 442 1.1 mrg 443 1.1 mrg r.report_no_such_form (type); 444 1.1 mrg return NUM_TYPE_SUFFIXES; 445 1.1 mrg } 446 1.1 mrg 447 1.1 mrg /* Declare the function shape NAME, pointing it to an instance 448 1.1 mrg of class <NAME>_def. */ 449 1.1 mrg #define SHAPE(NAME) \ 450 1.1 mrg static CONSTEXPR const NAME##_def NAME##_obj; \ 451 1.1 mrg namespace shapes { const function_shape *const NAME = &NAME##_obj; } 452 1.1 mrg 453 1.1 mrg /* Base class for functions that are not overloaded. */ 454 1.1 mrg struct nonoverloaded_base : public function_shape 455 1.1 mrg { 456 1.1 mrg bool 457 1.1 mrg explicit_type_suffix_p (unsigned int) const OVERRIDE 458 1.1 mrg { 459 1.1 mrg return true; 460 1.1 mrg } 461 1.1 mrg 462 1.1 mrg tree 463 1.1 mrg resolve (function_resolver &) const OVERRIDE 464 1.1 mrg { 465 1.1 mrg gcc_unreachable (); 466 1.1 mrg } 467 1.1 mrg }; 468 1.1 mrg 469 1.1 mrg /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true 470 1.1 mrg if type suffix N appears in the overloaded name. */ 471 1.1 mrg template<unsigned int EXPLICIT_MASK> 472 1.1 mrg struct overloaded_base : public function_shape 473 1.1 mrg { 474 1.1 mrg bool 475 1.1 mrg explicit_type_suffix_p (unsigned int i) const OVERRIDE 476 1.1 mrg { 477 1.1 mrg return (EXPLICIT_MASK >> i) & 1; 478 1.1 mrg } 479 1.1 mrg }; 480 1.1 mrg 481 1.1 mrg /* Base class for adr_index and adr_offset. */ 482 1.1 mrg struct adr_base : public overloaded_base<0> 483 1.1 mrg { 484 1.1 mrg /* The function takes two arguments: a vector base and a vector displacement 485 1.1 mrg (either an index or an offset). Resolve based on them both. */ 486 1.1 mrg tree 487 1.1 mrg resolve (function_resolver &r) const OVERRIDE 488 1.1 mrg { 489 1.1 mrg unsigned int i, nargs; 490 1.1 mrg mode_suffix_index mode; 491 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 492 1.1 mrg || (mode = r.resolve_adr_address (0)) == MODE_none) 493 1.1 mrg return error_mark_node; 494 1.1 mrg 495 1.1 mrg return r.resolve_to (mode); 496 1.1 mrg }; 497 1.1 mrg }; 498 1.1 mrg 499 1.1 mrg /* Base class for narrowing bottom binary functions that take an 500 1.1 mrg immediate second operand. The result is half the size of input 501 1.1 mrg and has class CLASS. */ 502 1.1 mrg template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS> 503 1.1 mrg struct binary_imm_narrowb_base : public overloaded_base<0> 504 1.1 mrg { 505 1.1 mrg void 506 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 507 1.1 mrg { 508 1.1 mrg b.add_overloaded_functions (group, MODE_n); 509 1.1 mrg STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS 510 1.1 mrg || CLASS == TYPE_unsigned); 511 1.1 mrg if (CLASS == TYPE_unsigned) 512 1.1 mrg build_all (b, "vhu0,v0,su64", group, MODE_n); 513 1.1 mrg else 514 1.1 mrg build_all (b, "vh0,v0,su64", group, MODE_n); 515 1.1 mrg } 516 1.1 mrg 517 1.1 mrg tree 518 1.1 mrg resolve (function_resolver &r) const OVERRIDE 519 1.1 mrg { 520 1.1 mrg return r.resolve_uniform (1, 1); 521 1.1 mrg } 522 1.1 mrg }; 523 1.1 mrg 524 1.1 mrg /* The top equivalent of binary_imm_narrowb_base. It takes three arguments, 525 1.1 mrg with the first being the values of the even elements, which are typically 526 1.1 mrg the result of the narrowb operation. */ 527 1.1 mrg template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS> 528 1.1 mrg struct binary_imm_narrowt_base : public overloaded_base<0> 529 1.1 mrg { 530 1.1 mrg void 531 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 532 1.1 mrg { 533 1.1 mrg b.add_overloaded_functions (group, MODE_n); 534 1.1 mrg STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS 535 1.1 mrg || CLASS == TYPE_unsigned); 536 1.1 mrg if (CLASS == TYPE_unsigned) 537 1.1 mrg build_all (b, "vhu0,vhu0,v0,su64", group, MODE_n); 538 1.1 mrg else 539 1.1 mrg build_all (b, "vh0,vh0,v0,su64", group, MODE_n); 540 1.1 mrg } 541 1.1 mrg 542 1.1 mrg tree 543 1.1 mrg resolve (function_resolver &r) const OVERRIDE 544 1.1 mrg { 545 1.1 mrg unsigned int i, nargs; 546 1.1 mrg type_suffix_index type; 547 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 548 1.1 mrg || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES 549 1.1 mrg || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE) 550 1.1 mrg || !r.require_integer_immediate (i + 2)) 551 1.1 mrg return error_mark_node; 552 1.1 mrg 553 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 554 1.1 mrg } 555 1.1 mrg }; 556 1.1 mrg 557 1.1 mrg /* Base class for long (i.e. narrow op narrow -> wide) binary functions 558 1.1 mrg that take an immediate second operand. The type suffix specifies 559 1.1 mrg the wider type. */ 560 1.1 mrg struct binary_imm_long_base : public overloaded_base<0> 561 1.1 mrg { 562 1.1 mrg void 563 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 564 1.1 mrg { 565 1.1 mrg b.add_overloaded_functions (group, MODE_n); 566 1.1 mrg build_all (b, "v0,vh0,su64", group, MODE_n); 567 1.1 mrg } 568 1.1 mrg 569 1.1 mrg tree 570 1.1 mrg resolve (function_resolver &r) const OVERRIDE 571 1.1 mrg { 572 1.1 mrg unsigned int i, nargs; 573 1.1 mrg type_suffix_index type, result_type; 574 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 575 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 576 1.1 mrg || !r.require_integer_immediate (i + 1) 577 1.1 mrg || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES) 578 1.1 mrg return error_mark_node; 579 1.1 mrg 580 1.1 mrg if (tree res = r.lookup_form (r.mode_suffix_id, result_type)) 581 1.1 mrg return res; 582 1.1 mrg 583 1.1 mrg return r.report_no_such_form (type); 584 1.1 mrg } 585 1.1 mrg }; 586 1.1 mrg 587 1.1 mrg /* Base class for inc_dec and inc_dec_pat. */ 588 1.1 mrg struct inc_dec_base : public overloaded_base<0> 589 1.1 mrg { 590 1.1 mrg CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {} 591 1.1 mrg 592 1.1 mrg /* Resolve based on the first argument only, which must be either a 593 1.1 mrg scalar or a vector. If it's a scalar, it must be a 32-bit or 594 1.1 mrg 64-bit integer. */ 595 1.1 mrg tree 596 1.1 mrg resolve (function_resolver &r) const 597 1.1 mrg { 598 1.1 mrg unsigned int i, nargs; 599 1.1 mrg if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs) 600 1.1 mrg || !r.require_vector_or_scalar_type (i)) 601 1.1 mrg return error_mark_node; 602 1.1 mrg 603 1.1 mrg mode_suffix_index mode; 604 1.1 mrg type_suffix_index type; 605 1.1 mrg if (r.scalar_argument_p (i)) 606 1.1 mrg { 607 1.1 mrg mode = MODE_n; 608 1.1 mrg type = r.infer_integer_scalar_type (i); 609 1.1 mrg } 610 1.1 mrg else 611 1.1 mrg { 612 1.1 mrg mode = MODE_none; 613 1.1 mrg type = r.infer_vector_type (i); 614 1.1 mrg } 615 1.1 mrg if (type == NUM_TYPE_SUFFIXES) 616 1.1 mrg return error_mark_node; 617 1.1 mrg 618 1.1 mrg for (++i; i < nargs; ++i) 619 1.1 mrg if (!r.require_integer_immediate (i)) 620 1.1 mrg return error_mark_node; 621 1.1 mrg 622 1.1 mrg return r.resolve_to (mode, type); 623 1.1 mrg } 624 1.1 mrg 625 1.1 mrg bool 626 1.1 mrg check (function_checker &c) const OVERRIDE 627 1.1 mrg { 628 1.1 mrg return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16); 629 1.1 mrg } 630 1.1 mrg 631 1.1 mrg bool m_pat_p; 632 1.1 mrg }; 633 1.1 mrg 634 1.1 mrg /* Base class for load and load_replicate. */ 635 1.1 mrg struct load_contiguous_base : public overloaded_base<0> 636 1.1 mrg { 637 1.1 mrg /* Resolve a call based purely on a pointer argument. The other arguments 638 1.1 mrg are a governing predicate and (for MODE_vnum) a vnum offset. */ 639 1.1 mrg tree 640 1.1 mrg resolve (function_resolver &r) const OVERRIDE 641 1.1 mrg { 642 1.1 mrg bool vnum_p = r.mode_suffix_id == MODE_vnum; 643 1.1 mrg gcc_assert (r.mode_suffix_id == MODE_none || vnum_p); 644 1.1 mrg 645 1.1 mrg unsigned int i, nargs; 646 1.1 mrg type_suffix_index type; 647 1.1 mrg if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs) 648 1.1 mrg || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES 649 1.1 mrg || (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))) 650 1.1 mrg return error_mark_node; 651 1.1 mrg 652 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 653 1.1 mrg } 654 1.1 mrg }; 655 1.1 mrg 656 1.1 mrg /* Base class for gather loads that take a scalar base and a vector 657 1.1 mrg displacement (either an offset or an index). */ 658 1.1 mrg struct load_gather_sv_base : public overloaded_base<0> 659 1.1 mrg { 660 1.1 mrg tree 661 1.1 mrg resolve (function_resolver &r) const OVERRIDE 662 1.1 mrg { 663 1.1 mrg unsigned int i, nargs; 664 1.1 mrg mode_suffix_index mode; 665 1.1 mrg type_suffix_index type; 666 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 667 1.1 mrg || (type = r.infer_pointer_type (i, true)) == NUM_TYPE_SUFFIXES 668 1.1 mrg || (mode = r.resolve_sv_displacement (i + 1, type, true), 669 1.1 mrg mode == MODE_none)) 670 1.1 mrg return error_mark_node; 671 1.1 mrg 672 1.1 mrg return r.resolve_to (mode, type); 673 1.1 mrg } 674 1.1 mrg }; 675 1.1 mrg 676 1.1 mrg /* Base class for load_ext_gather_index and load_ext_gather_offset, 677 1.1 mrg which differ only in the units of the displacement. */ 678 1.1 mrg struct load_ext_gather_base : public overloaded_base<1> 679 1.1 mrg { 680 1.1 mrg /* Resolve a gather load that takes one of: 681 1.1 mrg 682 1.1 mrg - a scalar pointer base and a vector displacement 683 1.1 mrg - a vector base with no displacement or 684 1.1 mrg - a vector base and a scalar displacement 685 1.1 mrg 686 1.1 mrg The function has an explicit type suffix that determines the type 687 1.1 mrg of the loaded data. */ 688 1.1 mrg tree 689 1.1 mrg resolve (function_resolver &r) const OVERRIDE 690 1.1 mrg { 691 1.1 mrg /* No resolution is needed for a vector base with no displacement; 692 1.1 mrg there's a one-to-one mapping between short and long names. */ 693 1.1 mrg gcc_assert (r.displacement_units () != UNITS_none); 694 1.1 mrg 695 1.1 mrg type_suffix_index type = r.type_suffix_ids[0]; 696 1.1 mrg 697 1.1 mrg unsigned int i, nargs; 698 1.1 mrg mode_suffix_index mode; 699 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 700 1.1 mrg || (mode = r.resolve_gather_address (i, type, true)) == MODE_none) 701 1.1 mrg return error_mark_node; 702 1.1 mrg 703 1.1 mrg return r.resolve_to (mode, type); 704 1.1 mrg } 705 1.1 mrg }; 706 1.1 mrg 707 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, 708 1.1 mrg sv<t0:quarter>_t) (for integer t0) 709 1.1 mrg sv<t0>_t svmmla[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t) (for floating-point t0) 710 1.1 mrg 711 1.1 mrg The functions act like the equivalent of "ternary_qq" for integer elements 712 1.1 mrg and normal vector-only ternary functions for floating-point elements. */ 713 1.1 mrg struct mmla_def : public overloaded_base<0> 714 1.1 mrg { 715 1.1 mrg void 716 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 717 1.1 mrg { 718 1.1 mrg b.add_overloaded_functions (group, MODE_none); 719 1.1 mrg /* svmmla is distributed over several extensions. Allow the common 720 1.1 mrg denominator to define the overloaded svmmla function without 721 1.1 mrg defining any specific versions. */ 722 1.1 mrg if (group.types[0][0] != NUM_TYPE_SUFFIXES) 723 1.1 mrg { 724 1.1 mrg if (type_suffixes[group.types[0][0]].float_p) 725 1.1 mrg build_all (b, "v0,v0,v0,v0", group, MODE_none); 726 1.1 mrg else 727 1.1 mrg build_all (b, "v0,v0,vq0,vq0", group, MODE_none); 728 1.1 mrg } 729 1.1 mrg } 730 1.1 mrg 731 1.1 mrg tree 732 1.1 mrg resolve (function_resolver &r) const OVERRIDE 733 1.1 mrg { 734 1.1 mrg unsigned int i, nargs; 735 1.1 mrg type_suffix_index type; 736 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 737 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 738 1.1 mrg return error_mark_node; 739 1.1 mrg 740 1.1 mrg /* Make sure that the function exists now, since not all forms 741 1.1 mrg follow a set pattern after this point. */ 742 1.1 mrg tree res = r.resolve_to (r.mode_suffix_id, type); 743 1.1 mrg if (res == error_mark_node) 744 1.1 mrg return res; 745 1.1 mrg 746 1.1 mrg bool float_p = type_suffixes[type].float_p; 747 1.1 mrg unsigned int modifier = float_p ? r.SAME_SIZE : r.QUARTER_SIZE; 748 1.1 mrg if (!r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS, 749 1.1 mrg modifier) 750 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS, 751 1.1 mrg modifier)) 752 1.1 mrg return error_mark_node; 753 1.1 mrg 754 1.1 mrg return res; 755 1.1 mrg } 756 1.1 mrg }; 757 1.1 mrg SHAPE (mmla) 758 1.1 mrg 759 1.1 mrg /* Base class for prefetch_gather_index and prefetch_gather_offset, 760 1.1 mrg which differ only in the units of the displacement. */ 761 1.1 mrg struct prefetch_gather_base : public overloaded_base<0> 762 1.1 mrg { 763 1.1 mrg /* Resolve a gather prefetch that takes one of: 764 1.1 mrg 765 1.1 mrg - a scalar pointer base (const void *) and a vector displacement 766 1.1 mrg - a vector base with no displacement or 767 1.1 mrg - a vector base and a scalar displacement 768 1.1 mrg 769 1.1 mrg The prefetch operation is the final argument. This is purely a 770 1.1 mrg mode-based resolution; there are no type suffixes. */ 771 1.1 mrg tree 772 1.1 mrg resolve (function_resolver &r) const OVERRIDE 773 1.1 mrg { 774 1.1 mrg bool has_displacement_p = r.displacement_units () != UNITS_none; 775 1.1 mrg 776 1.1 mrg unsigned int i, nargs; 777 1.1 mrg mode_suffix_index mode; 778 1.1 mrg if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs) 779 1.1 mrg || (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES, 780 1.1 mrg false)) == MODE_none 781 1.1 mrg || !r.require_integer_immediate (nargs - 1)) 782 1.1 mrg return error_mark_node; 783 1.1 mrg 784 1.1 mrg return r.resolve_to (mode); 785 1.1 mrg } 786 1.1 mrg }; 787 1.1 mrg 788 1.1 mrg /* Wraps BASE to provide a narrowing shift right function. Argument N 789 1.1 mrg is an immediate shift amount in the range [1, sizeof(<t0>_t) * 4]. */ 790 1.1 mrg template<typename BASE, unsigned int N> 791 1.1 mrg struct shift_right_imm_narrow_wrapper : public BASE 792 1.1 mrg { 793 1.1 mrg bool 794 1.1 mrg check (function_checker &c) const OVERRIDE 795 1.1 mrg { 796 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits / 2; 797 1.1 mrg return c.require_immediate_range (N, 1, bits); 798 1.1 mrg } 799 1.1 mrg }; 800 1.1 mrg 801 1.1 mrg /* Base class for store_scatter_index and store_scatter_offset, 802 1.1 mrg which differ only in the units of the displacement. */ 803 1.1 mrg struct store_scatter_base : public overloaded_base<0> 804 1.1 mrg { 805 1.1 mrg /* Resolve a scatter store that takes one of: 806 1.1 mrg 807 1.1 mrg - a scalar pointer base and a vector displacement 808 1.1 mrg - a vector base with no displacement or 809 1.1 mrg - a vector base and a scalar displacement 810 1.1 mrg 811 1.1 mrg The stored data is the final argument, and it determines the 812 1.1 mrg type suffix. */ 813 1.1 mrg tree 814 1.1 mrg resolve (function_resolver &r) const OVERRIDE 815 1.1 mrg { 816 1.1 mrg bool has_displacement_p = r.displacement_units () != UNITS_none; 817 1.1 mrg 818 1.1 mrg unsigned int i, nargs; 819 1.1 mrg mode_suffix_index mode; 820 1.1 mrg type_suffix_index type; 821 1.1 mrg if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs) 822 1.1 mrg || (type = r.infer_sd_vector_type (nargs - 1)) == NUM_TYPE_SUFFIXES 823 1.1 mrg || (mode = r.resolve_gather_address (i, type, false)) == MODE_none) 824 1.1 mrg return error_mark_node; 825 1.1 mrg 826 1.1 mrg return r.resolve_to (mode, type); 827 1.1 mrg } 828 1.1 mrg }; 829 1.1 mrg 830 1.1 mrg /* Base class for ternary operations in which the final argument is an 831 1.1 mrg immediate shift amount. The derived class should check the range. */ 832 1.1 mrg struct ternary_shift_imm_base : public overloaded_base<0> 833 1.1 mrg { 834 1.1 mrg void 835 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 836 1.1 mrg { 837 1.1 mrg b.add_overloaded_functions (group, MODE_n); 838 1.1 mrg build_all (b, "v0,v0,v0,su64", group, MODE_n); 839 1.1 mrg } 840 1.1 mrg 841 1.1 mrg tree 842 1.1 mrg resolve (function_resolver &r) const OVERRIDE 843 1.1 mrg { 844 1.1 mrg return r.resolve_uniform (2, 1); 845 1.1 mrg } 846 1.1 mrg }; 847 1.1 mrg 848 1.1 mrg /* Base class for ternary operations in which the first argument has the 849 1.1 mrg same element type as the result, and in which the second and third 850 1.1 mrg arguments have an element type that is derived the first. 851 1.1 mrg 852 1.1 mrg MODIFIER is the number of element bits in the second and third 853 1.1 mrg arguments, or a function_resolver modifier that says how this 854 1.1 mrg precision is derived from the first argument's elements. 855 1.1 mrg 856 1.1 mrg TYPE_CLASS2 and TYPE_CLASS3 are the type classes of the second and 857 1.1 mrg third arguments, or function_resolver::SAME_TYPE_CLASS if the type 858 1.1 mrg class is the same as the first argument. */ 859 1.1 mrg template<unsigned int MODIFIER, 860 1.1 mrg type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS, 861 1.1 mrg type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS> 862 1.1 mrg struct ternary_resize2_opt_n_base : public overloaded_base<0> 863 1.1 mrg { 864 1.1 mrg tree 865 1.1 mrg resolve (function_resolver &r) const OVERRIDE 866 1.1 mrg { 867 1.1 mrg unsigned int i, nargs; 868 1.1 mrg type_suffix_index type; 869 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 870 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 871 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2, 872 1.1 mrg MODIFIER)) 873 1.1 mrg return error_mark_node; 874 1.1 mrg 875 1.1 mrg return r.finish_opt_n_resolution (i + 2, i, type, TYPE_CLASS3, MODIFIER); 876 1.1 mrg } 877 1.1 mrg }; 878 1.1 mrg 879 1.1 mrg /* Like ternary_resize2_opt_n_base, but for functions that don't take 880 1.1 mrg a final scalar argument. */ 881 1.1 mrg template<unsigned int MODIFIER, 882 1.1 mrg type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS, 883 1.1 mrg type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS> 884 1.1 mrg struct ternary_resize2_base : public overloaded_base<0> 885 1.1 mrg { 886 1.1 mrg tree 887 1.1 mrg resolve (function_resolver &r) const OVERRIDE 888 1.1 mrg { 889 1.1 mrg unsigned int i, nargs; 890 1.1 mrg type_suffix_index type; 891 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 892 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 893 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2, 894 1.1 mrg MODIFIER) 895 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3, 896 1.1 mrg MODIFIER)) 897 1.1 mrg return error_mark_node; 898 1.1 mrg 899 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 900 1.1 mrg } 901 1.1 mrg }; 902 1.1 mrg 903 1.1 mrg /* Like ternary_resize2_opt_n_base, but for functions that take a final 904 1.1 mrg lane argument. */ 905 1.1 mrg template<unsigned int MODIFIER, 906 1.1 mrg type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS, 907 1.1 mrg type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS> 908 1.1 mrg struct ternary_resize2_lane_base : public overloaded_base<0> 909 1.1 mrg { 910 1.1 mrg tree 911 1.1 mrg resolve (function_resolver &r) const OVERRIDE 912 1.1 mrg { 913 1.1 mrg unsigned int i, nargs; 914 1.1 mrg type_suffix_index type; 915 1.1 mrg if (!r.check_gp_argument (4, i, nargs) 916 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 917 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2, 918 1.1 mrg MODIFIER) 919 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3, 920 1.1 mrg MODIFIER) 921 1.1 mrg || !r.require_integer_immediate (i + 3)) 922 1.1 mrg return error_mark_node; 923 1.1 mrg 924 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 925 1.1 mrg } 926 1.1 mrg }; 927 1.1 mrg 928 1.1 mrg /* A specialization of ternary_resize2_lane_base for bfloat16 elements, 929 1.1 mrg indexed in groups of N elements. */ 930 1.1 mrg template<unsigned int N> 931 1.1 mrg struct ternary_bfloat_lane_base 932 1.1 mrg : public ternary_resize2_lane_base<16, TYPE_bfloat, TYPE_bfloat> 933 1.1 mrg { 934 1.1 mrg void 935 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 936 1.1 mrg { 937 1.1 mrg b.add_overloaded_functions (group, MODE_none); 938 1.1 mrg build_all (b, "v0,v0,vB,vB,su64", group, MODE_none); 939 1.1 mrg } 940 1.1 mrg 941 1.1 mrg bool 942 1.1 mrg check (function_checker &c) const OVERRIDE 943 1.1 mrg { 944 1.1 mrg return c.require_immediate_lane_index (3, N); 945 1.1 mrg } 946 1.1 mrg }; 947 1.1 mrg 948 1.1 mrg /* A specialization of ternary_resize2_lane_base for quarter-sized 949 1.1 mrg elements. */ 950 1.1 mrg template<type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS, 951 1.1 mrg type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS> 952 1.1 mrg struct ternary_qq_lane_base 953 1.1 mrg : public ternary_resize2_lane_base<function_resolver::QUARTER_SIZE, 954 1.1 mrg TYPE_CLASS2, TYPE_CLASS3> 955 1.1 mrg { 956 1.1 mrg bool 957 1.1 mrg check (function_checker &c) const OVERRIDE 958 1.1 mrg { 959 1.1 mrg return c.require_immediate_lane_index (3, 4); 960 1.1 mrg } 961 1.1 mrg }; 962 1.1 mrg 963 1.1 mrg /* Base class for narrowing bottom unary functions. The result is half 964 1.1 mrg the size of input and has class CLASS. */ 965 1.1 mrg template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS> 966 1.1 mrg struct unary_narrowb_base : public overloaded_base<0> 967 1.1 mrg { 968 1.1 mrg void 969 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 970 1.1 mrg { 971 1.1 mrg b.add_overloaded_functions (group, MODE_none); 972 1.1 mrg STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS 973 1.1 mrg || CLASS == TYPE_unsigned); 974 1.1 mrg if (CLASS == TYPE_unsigned) 975 1.1 mrg build_all (b, "vhu0,v0", group, MODE_none); 976 1.1 mrg else 977 1.1 mrg build_all (b, "vh0,v0", group, MODE_none); 978 1.1 mrg } 979 1.1 mrg 980 1.1 mrg tree 981 1.1 mrg resolve (function_resolver &r) const OVERRIDE 982 1.1 mrg { 983 1.1 mrg return r.resolve_unary (CLASS, r.HALF_SIZE); 984 1.1 mrg } 985 1.1 mrg }; 986 1.1 mrg 987 1.1 mrg /* The top equivalent of unary_imm_narrowb_base. All forms take the values 988 1.1 mrg of the even elements as an extra argument, before any governing predicate. 989 1.1 mrg These even elements are typically the result of the narrowb operation. */ 990 1.1 mrg template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS> 991 1.1 mrg struct unary_narrowt_base : public overloaded_base<0> 992 1.1 mrg { 993 1.1 mrg void 994 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 995 1.1 mrg { 996 1.1 mrg b.add_overloaded_functions (group, MODE_none); 997 1.1 mrg STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS 998 1.1 mrg || CLASS == TYPE_unsigned); 999 1.1 mrg if (CLASS == TYPE_unsigned) 1000 1.1 mrg build_all (b, "vhu0,vhu0,v0", group, MODE_none); 1001 1.1 mrg else 1002 1.1 mrg build_all (b, "vh0,vh0,v0", group, MODE_none); 1003 1.1 mrg } 1004 1.1 mrg 1005 1.1 mrg tree 1006 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1007 1.1 mrg { 1008 1.1 mrg unsigned int i, nargs; 1009 1.1 mrg type_suffix_index type; 1010 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1011 1.1 mrg || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES 1012 1.1 mrg || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE)) 1013 1.1 mrg return error_mark_node; 1014 1.1 mrg 1015 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1016 1.1 mrg } 1017 1.1 mrg }; 1018 1.1 mrg 1019 1.1 mrg /* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t) 1020 1.1 mrg 1021 1.1 mrg for all valid combinations of vector base type <m0> and vector 1022 1.1 mrg displacement type <m1>. */ 1023 1.1 mrg struct adr_index_def : public adr_base 1024 1.1 mrg { 1025 1.1 mrg void 1026 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1027 1.1 mrg { 1028 1.1 mrg b.add_overloaded_functions (group, MODE_index); 1029 1.1 mrg build_all (b, "b,b,d", group, MODE_u32base_s32index); 1030 1.1 mrg build_all (b, "b,b,d", group, MODE_u32base_u32index); 1031 1.1 mrg build_all (b, "b,b,d", group, MODE_u64base_s64index); 1032 1.1 mrg build_all (b, "b,b,d", group, MODE_u64base_u64index); 1033 1.1 mrg } 1034 1.1 mrg }; 1035 1.1 mrg SHAPE (adr_index) 1036 1.1 mrg 1037 1.1 mrg /* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t). 1038 1.1 mrg 1039 1.1 mrg for all valid combinations of vector base type <m0> and vector 1040 1.1 mrg displacement type <m1>. */ 1041 1.1 mrg struct adr_offset_def : public adr_base 1042 1.1 mrg { 1043 1.1 mrg void 1044 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1045 1.1 mrg { 1046 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 1047 1.1 mrg build_all (b, "b,b,d", group, MODE_u32base_s32offset); 1048 1.1 mrg build_all (b, "b,b,d", group, MODE_u32base_u32offset); 1049 1.1 mrg build_all (b, "b,b,d", group, MODE_u64base_s64offset); 1050 1.1 mrg build_all (b, "b,b,d", group, MODE_u64base_u64offset); 1051 1.1 mrg } 1052 1.1 mrg }; 1053 1.1 mrg SHAPE (adr_offset) 1054 1.1 mrg 1055 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t) 1056 1.1 mrg 1057 1.1 mrg i.e. a binary operation with uniform types, but with no scalar form. */ 1058 1.1 mrg struct binary_def : public overloaded_base<0> 1059 1.1 mrg { 1060 1.1 mrg void 1061 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1062 1.1 mrg { 1063 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1064 1.1 mrg build_all (b, "v0,v0,v0", group, MODE_none); 1065 1.1 mrg } 1066 1.1 mrg 1067 1.1 mrg tree 1068 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1069 1.1 mrg { 1070 1.1 mrg return r.resolve_uniform (2); 1071 1.1 mrg } 1072 1.1 mrg }; 1073 1.1 mrg SHAPE (binary) 1074 1.1 mrg 1075 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t) 1076 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t). 1077 1.1 mrg 1078 1.1 mrg i.e. a version of the standard binary shape binary_opt_n in which 1079 1.1 mrg the final argument is always a signed integer. */ 1080 1.1 mrg struct binary_int_opt_n_def : public overloaded_base<0> 1081 1.1 mrg { 1082 1.1 mrg void 1083 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1084 1.1 mrg { 1085 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1086 1.1 mrg build_all (b, "v0,v0,vs0", group, MODE_none); 1087 1.1 mrg build_all (b, "v0,v0,ss0", group, MODE_n); 1088 1.1 mrg } 1089 1.1 mrg 1090 1.1 mrg tree 1091 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1092 1.1 mrg { 1093 1.1 mrg unsigned int i, nargs; 1094 1.1 mrg type_suffix_index type; 1095 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1096 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 1097 1.1 mrg return error_mark_node; 1098 1.1 mrg 1099 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed); 1100 1.1 mrg } 1101 1.1 mrg }; 1102 1.1 mrg SHAPE (binary_int_opt_n) 1103 1.1 mrg 1104 1.1 mrg /* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t) 1105 1.1 mrg 1106 1.1 mrg where the final argument is an integer constant expression in the 1107 1.1 mrg range [0, 16 / sizeof (<t0>_t) - 1]. */ 1108 1.1 mrg struct binary_lane_def : public overloaded_base<0> 1109 1.1 mrg { 1110 1.1 mrg void 1111 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1112 1.1 mrg { 1113 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1114 1.1 mrg build_all (b, "v0,v0,v0,su64", group, MODE_none); 1115 1.1 mrg } 1116 1.1 mrg 1117 1.1 mrg tree 1118 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1119 1.1 mrg { 1120 1.1 mrg return r.resolve_uniform (2, 1); 1121 1.1 mrg } 1122 1.1 mrg 1123 1.1 mrg bool 1124 1.1 mrg check (function_checker &c) const OVERRIDE 1125 1.1 mrg { 1126 1.1 mrg return c.require_immediate_lane_index (2); 1127 1.1 mrg } 1128 1.1 mrg }; 1129 1.1 mrg SHAPE (binary_lane) 1130 1.1 mrg 1131 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t, uint64_t). 1132 1.1 mrg 1133 1.1 mrg where the final argument is an integer constant expression in the 1134 1.1 mrg range [0, 32 / sizeof (<t0>_t) - 1]. */ 1135 1.1 mrg struct binary_long_lane_def : public overloaded_base<0> 1136 1.1 mrg { 1137 1.1 mrg void 1138 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1139 1.1 mrg { 1140 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1141 1.1 mrg build_all (b, "v0,vh0,vh0,su64", group, MODE_none); 1142 1.1 mrg } 1143 1.1 mrg 1144 1.1 mrg tree 1145 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1146 1.1 mrg { 1147 1.1 mrg unsigned int i, nargs; 1148 1.1 mrg type_suffix_index type, result_type; 1149 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 1150 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1151 1.1 mrg || !r.require_matching_vector_type (i + 1, type) 1152 1.1 mrg || !r.require_integer_immediate (i + 2) 1153 1.1 mrg || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES) 1154 1.1 mrg return error_mark_node; 1155 1.1 mrg 1156 1.1 mrg if (tree res = r.lookup_form (r.mode_suffix_id, result_type)) 1157 1.1 mrg return res; 1158 1.1 mrg 1159 1.1 mrg return r.report_no_such_form (type); 1160 1.1 mrg } 1161 1.1 mrg 1162 1.1 mrg bool 1163 1.1 mrg check (function_checker &c) const OVERRIDE 1164 1.1 mrg { 1165 1.1 mrg return c.require_immediate_lane_index (2); 1166 1.1 mrg } 1167 1.1 mrg }; 1168 1.1 mrg SHAPE (binary_long_lane) 1169 1.1 mrg 1170 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t) 1171 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0:half>_t, <t0:half>_t). */ 1172 1.1 mrg struct binary_long_opt_n_def : public overloaded_base<0> 1173 1.1 mrg { 1174 1.1 mrg void 1175 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1176 1.1 mrg { 1177 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1178 1.1 mrg build_all (b, "v0,vh0,vh0", group, MODE_none); 1179 1.1 mrg build_all (b, "v0,vh0,sh0", group, MODE_n); 1180 1.1 mrg } 1181 1.1 mrg 1182 1.1 mrg tree 1183 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1184 1.1 mrg { 1185 1.1 mrg unsigned int i, nargs; 1186 1.1 mrg type_suffix_index type, result_type; 1187 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1188 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1189 1.1 mrg || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES) 1190 1.1 mrg return error_mark_node; 1191 1.1 mrg 1192 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 1193 1.1 mrg r.SAME_SIZE, result_type); 1194 1.1 mrg } 1195 1.1 mrg }; 1196 1.1 mrg SHAPE (binary_long_opt_n) 1197 1.1 mrg 1198 1.1 mrg /* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t). 1199 1.1 mrg 1200 1.1 mrg i.e. a binary operation in which the final argument is always a scalar 1201 1.1 mrg rather than a vector. */ 1202 1.1 mrg struct binary_n_def : public overloaded_base<0> 1203 1.1 mrg { 1204 1.1 mrg void 1205 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1206 1.1 mrg { 1207 1.1 mrg b.add_overloaded_functions (group, MODE_n); 1208 1.1 mrg build_all (b, "v0,v0,s0", group, MODE_n); 1209 1.1 mrg } 1210 1.1 mrg 1211 1.1 mrg tree 1212 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1213 1.1 mrg { 1214 1.1 mrg unsigned int i, nargs; 1215 1.1 mrg type_suffix_index type; 1216 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1217 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1218 1.1 mrg || !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS)) 1219 1.1 mrg return error_mark_node; 1220 1.1 mrg 1221 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1222 1.1 mrg } 1223 1.1 mrg }; 1224 1.1 mrg SHAPE (binary_n) 1225 1.1 mrg 1226 1.1 mrg /* sv<t0:half>_t svfoo[_t0](sv<t0>_t, sv<t0>_t) 1227 1.1 mrg sv<t0:half>_t svfoo[_n_t0](sv<t0>_t, <t0>_t) 1228 1.1 mrg 1229 1.1 mrg i.e. a version of binary_opt_n in which the output elements are half the 1230 1.1 mrg width of the input elements. */ 1231 1.1 mrg struct binary_narrowb_opt_n_def : public overloaded_base<0> 1232 1.1 mrg { 1233 1.1 mrg void 1234 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1235 1.1 mrg { 1236 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1237 1.1 mrg build_all (b, "vh0,v0,v0", group, MODE_none); 1238 1.1 mrg build_all (b, "vh0,v0,s0", group, MODE_n); 1239 1.1 mrg } 1240 1.1 mrg 1241 1.1 mrg tree 1242 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1243 1.1 mrg { 1244 1.1 mrg return r.resolve_uniform_opt_n (2); 1245 1.1 mrg } 1246 1.1 mrg }; 1247 1.1 mrg SHAPE (binary_narrowb_opt_n) 1248 1.1 mrg 1249 1.1 mrg /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t, sv<t0>_t) 1250 1.1 mrg sv<t0:half>_t svfoo[_n_t0](sv<t0:half>_t, sv<t0>_t, <t0>_t) 1251 1.1 mrg 1252 1.1 mrg This is the "top" counterpart to binary_narrowb_opt_n. */ 1253 1.1 mrg struct binary_narrowt_opt_n_def : public overloaded_base<0> 1254 1.1 mrg { 1255 1.1 mrg void 1256 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1257 1.1 mrg { 1258 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1259 1.1 mrg build_all (b, "vh0,vh0,v0,v0", group, MODE_none); 1260 1.1 mrg build_all (b, "vh0,vh0,v0,s0", group, MODE_n); 1261 1.1 mrg } 1262 1.1 mrg 1263 1.1 mrg tree 1264 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1265 1.1 mrg { 1266 1.1 mrg unsigned int i, nargs; 1267 1.1 mrg type_suffix_index type; 1268 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 1269 1.1 mrg || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES 1270 1.1 mrg || !r.require_derived_vector_type (i, i + 1, type, r.SAME_TYPE_CLASS, 1271 1.1 mrg r.HALF_SIZE)) 1272 1.1 mrg return error_mark_node; 1273 1.1 mrg 1274 1.1 mrg return r.finish_opt_n_resolution (i + 2, i + 1, type); 1275 1.1 mrg } 1276 1.1 mrg }; 1277 1.1 mrg SHAPE (binary_narrowt_opt_n) 1278 1.1 mrg 1279 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t) 1280 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t) 1281 1.1 mrg 1282 1.1 mrg i.e. the standard shape for binary operations that operate on 1283 1.1 mrg uniform types. */ 1284 1.1 mrg struct binary_opt_n_def : public overloaded_base<0> 1285 1.1 mrg { 1286 1.1 mrg void 1287 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1288 1.1 mrg { 1289 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1290 1.1 mrg build_all (b, "v0,v0,v0", group, MODE_none); 1291 1.1 mrg /* _b functions do not have an _n form, but are classified as 1292 1.1 mrg binary_opt_n so that they can be overloaded with vector 1293 1.1 mrg functions. */ 1294 1.1 mrg if (group.types[0][0] == TYPE_SUFFIX_b) 1295 1.1 mrg gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES); 1296 1.1 mrg else 1297 1.1 mrg build_all (b, "v0,v0,s0", group, MODE_n); 1298 1.1 mrg } 1299 1.1 mrg 1300 1.1 mrg tree 1301 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1302 1.1 mrg { 1303 1.1 mrg return r.resolve_uniform_opt_n (2); 1304 1.1 mrg } 1305 1.1 mrg }; 1306 1.1 mrg SHAPE (binary_opt_n) 1307 1.1 mrg 1308 1.1 mrg /* svbool_t svfoo(svbool_t, svbool_t). */ 1309 1.1 mrg struct binary_pred_def : public nonoverloaded_base 1310 1.1 mrg { 1311 1.1 mrg void 1312 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1313 1.1 mrg { 1314 1.1 mrg build_all (b, "v0,v0,v0", group, MODE_none); 1315 1.1 mrg } 1316 1.1 mrg }; 1317 1.1 mrg SHAPE (binary_pred) 1318 1.1 mrg 1319 1.1 mrg /* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t) 1320 1.1 mrg 1321 1.1 mrg where the final argument must be 90 or 270. */ 1322 1.1 mrg struct binary_rotate_def : public overloaded_base<0> 1323 1.1 mrg { 1324 1.1 mrg void 1325 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1326 1.1 mrg { 1327 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1328 1.1 mrg build_all (b, "v0,v0,v0,su64", group, MODE_none); 1329 1.1 mrg } 1330 1.1 mrg 1331 1.1 mrg tree 1332 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1333 1.1 mrg { 1334 1.1 mrg return r.resolve_uniform (2, 1); 1335 1.1 mrg } 1336 1.1 mrg 1337 1.1 mrg bool 1338 1.1 mrg check (function_checker &c) const OVERRIDE 1339 1.1 mrg { 1340 1.1 mrg return c.require_immediate_either_or (2, 90, 270); 1341 1.1 mrg } 1342 1.1 mrg }; 1343 1.1 mrg SHAPE (binary_rotate) 1344 1.1 mrg 1345 1.1 mrg /* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t) 1346 1.1 mrg 1347 1.1 mrg i.e. a binary function that takes two scalars and returns a vector. 1348 1.1 mrg An explicit type suffix is required. */ 1349 1.1 mrg struct binary_scalar_def : public nonoverloaded_base 1350 1.1 mrg { 1351 1.1 mrg void 1352 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1353 1.1 mrg { 1354 1.1 mrg build_all (b, "v0,s0,s0", group, MODE_none); 1355 1.1 mrg } 1356 1.1 mrg }; 1357 1.1 mrg SHAPE (binary_scalar) 1358 1.1 mrg 1359 1.1 mrg /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t, sv<t0>_t). 1360 1.1 mrg 1361 1.1 mrg i.e. a version of "binary" that returns unsigned integers. */ 1362 1.1 mrg struct binary_to_uint_def : public overloaded_base<0> 1363 1.1 mrg { 1364 1.1 mrg void 1365 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1366 1.1 mrg { 1367 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1368 1.1 mrg build_all (b, "vu0,v0,v0", group, MODE_none); 1369 1.1 mrg } 1370 1.1 mrg 1371 1.1 mrg tree 1372 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1373 1.1 mrg { 1374 1.1 mrg return r.resolve_uniform (2); 1375 1.1 mrg } 1376 1.1 mrg }; 1377 1.1 mrg SHAPE (binary_to_uint) 1378 1.1 mrg 1379 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t) 1380 1.1 mrg 1381 1.1 mrg i.e. a version of "binary" in which the final argument is always an 1382 1.1 mrg unsigned integer. */ 1383 1.1 mrg struct binary_uint_def : public overloaded_base<0> 1384 1.1 mrg { 1385 1.1 mrg void 1386 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1387 1.1 mrg { 1388 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1389 1.1 mrg build_all (b, "v0,v0,vu0", group, MODE_none); 1390 1.1 mrg } 1391 1.1 mrg 1392 1.1 mrg tree 1393 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1394 1.1 mrg { 1395 1.1 mrg unsigned int i, nargs; 1396 1.1 mrg type_suffix_index type; 1397 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1398 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1399 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned)) 1400 1.1 mrg return error_mark_node; 1401 1.1 mrg 1402 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1403 1.1 mrg } 1404 1.1 mrg }; 1405 1.1 mrg SHAPE (binary_uint) 1406 1.1 mrg 1407 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t) 1408 1.1 mrg 1409 1.1 mrg i.e. a version of binary_n in which the final argument is always an 1410 1.1 mrg unsigned integer. */ 1411 1.1 mrg struct binary_uint_n_def : public overloaded_base<0> 1412 1.1 mrg { 1413 1.1 mrg void 1414 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1415 1.1 mrg { 1416 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1417 1.1 mrg build_all (b, "v0,v0,su0", group, MODE_none); 1418 1.1 mrg } 1419 1.1 mrg 1420 1.1 mrg tree 1421 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1422 1.1 mrg { 1423 1.1 mrg unsigned int i, nargs; 1424 1.1 mrg type_suffix_index type; 1425 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1426 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1427 1.1 mrg || !r.require_derived_scalar_type (i + 1, TYPE_unsigned)) 1428 1.1 mrg return error_mark_node; 1429 1.1 mrg 1430 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1431 1.1 mrg } 1432 1.1 mrg }; 1433 1.1 mrg SHAPE (binary_uint_n) 1434 1.1 mrg 1435 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t) 1436 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t) 1437 1.1 mrg 1438 1.1 mrg i.e. a version of the standard binary shape binary_opt_n in which 1439 1.1 mrg the final argument is always an unsigned integer. */ 1440 1.1 mrg struct binary_uint_opt_n_def : public overloaded_base<0> 1441 1.1 mrg { 1442 1.1 mrg void 1443 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1444 1.1 mrg { 1445 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1446 1.1 mrg build_all (b, "v0,v0,vu0", group, MODE_none); 1447 1.1 mrg build_all (b, "v0,v0,su0", group, MODE_n); 1448 1.1 mrg } 1449 1.1 mrg 1450 1.1 mrg tree 1451 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1452 1.1 mrg { 1453 1.1 mrg unsigned int i, nargs; 1454 1.1 mrg type_suffix_index type; 1455 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1456 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 1457 1.1 mrg return error_mark_node; 1458 1.1 mrg 1459 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned); 1460 1.1 mrg } 1461 1.1 mrg }; 1462 1.1 mrg SHAPE (binary_uint_opt_n) 1463 1.1 mrg 1464 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t). 1465 1.1 mrg 1466 1.1 mrg i.e. a version of binary_n in which the final argument is always 1467 1.1 mrg a 64-bit unsigned integer. */ 1468 1.1 mrg struct binary_uint64_n_def : public overloaded_base<0> 1469 1.1 mrg { 1470 1.1 mrg void 1471 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1472 1.1 mrg { 1473 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1474 1.1 mrg build_all (b, "v0,v0,su64", group, MODE_none); 1475 1.1 mrg } 1476 1.1 mrg 1477 1.1 mrg tree 1478 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1479 1.1 mrg { 1480 1.1 mrg unsigned int i, nargs; 1481 1.1 mrg type_suffix_index type; 1482 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1483 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1484 1.1 mrg || !r.require_scalar_type (i + 1, "uint64_t")) 1485 1.1 mrg return error_mark_node; 1486 1.1 mrg 1487 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1488 1.1 mrg } 1489 1.1 mrg }; 1490 1.1 mrg SHAPE (binary_uint64_n) 1491 1.1 mrg 1492 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t) 1493 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t) 1494 1.1 mrg 1495 1.1 mrg i.e. a version of the standard binary shape binary_opt_n in which 1496 1.1 mrg the final argument is always a uint64_t. */ 1497 1.1 mrg struct binary_uint64_opt_n_def : public overloaded_base<0> 1498 1.1 mrg { 1499 1.1 mrg void 1500 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1501 1.1 mrg { 1502 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1503 1.1 mrg build_all (b, "v0,v0,vu64", group, MODE_none); 1504 1.1 mrg build_all (b, "v0,v0,su64", group, MODE_n); 1505 1.1 mrg } 1506 1.1 mrg 1507 1.1 mrg tree 1508 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1509 1.1 mrg { 1510 1.1 mrg unsigned int i, nargs; 1511 1.1 mrg type_suffix_index type; 1512 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1513 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 1514 1.1 mrg return error_mark_node; 1515 1.1 mrg 1516 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64); 1517 1.1 mrg } 1518 1.1 mrg }; 1519 1.1 mrg SHAPE (binary_uint64_opt_n) 1520 1.1 mrg 1521 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t). */ 1522 1.1 mrg struct binary_wide_def : public overloaded_base<0> 1523 1.1 mrg { 1524 1.1 mrg void 1525 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1526 1.1 mrg { 1527 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1528 1.1 mrg build_all (b, "v0,v0,vh0", group, MODE_none); 1529 1.1 mrg } 1530 1.1 mrg 1531 1.1 mrg tree 1532 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1533 1.1 mrg { 1534 1.1 mrg unsigned int i, nargs; 1535 1.1 mrg type_suffix_index type; 1536 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1537 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1538 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS, 1539 1.1 mrg r.HALF_SIZE)) 1540 1.1 mrg return error_mark_node; 1541 1.1 mrg 1542 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1543 1.1 mrg } 1544 1.1 mrg }; 1545 1.1 mrg SHAPE (binary_wide) 1546 1.1 mrg 1547 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t) 1548 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:half>_t). */ 1549 1.1 mrg struct binary_wide_opt_n_def : public overloaded_base<0> 1550 1.1 mrg { 1551 1.1 mrg void 1552 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1553 1.1 mrg { 1554 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1555 1.1 mrg build_all (b, "v0,v0,vh0", group, MODE_none); 1556 1.1 mrg build_all (b, "v0,v0,sh0", group, MODE_n); 1557 1.1 mrg } 1558 1.1 mrg 1559 1.1 mrg tree 1560 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1561 1.1 mrg { 1562 1.1 mrg unsigned int i, nargs; 1563 1.1 mrg type_suffix_index type; 1564 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1565 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 1566 1.1 mrg return error_mark_node; 1567 1.1 mrg 1568 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 1569 1.1 mrg r.HALF_SIZE); 1570 1.1 mrg } 1571 1.1 mrg }; 1572 1.1 mrg SHAPE (binary_wide_opt_n) 1573 1.1 mrg 1574 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t) 1575 1.1 mrg <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t). */ 1576 1.1 mrg struct clast_def : public overloaded_base<0> 1577 1.1 mrg { 1578 1.1 mrg void 1579 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1580 1.1 mrg { 1581 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1582 1.1 mrg build_all (b, "v0,v0,v0", group, MODE_none); 1583 1.1 mrg build_all (b, "s0,s0,v0", group, MODE_n); 1584 1.1 mrg } 1585 1.1 mrg 1586 1.1 mrg tree 1587 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1588 1.1 mrg { 1589 1.1 mrg unsigned int i, nargs; 1590 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1591 1.1 mrg || !r.require_vector_or_scalar_type (i)) 1592 1.1 mrg return error_mark_node; 1593 1.1 mrg 1594 1.1 mrg if (r.scalar_argument_p (i)) 1595 1.1 mrg { 1596 1.1 mrg type_suffix_index type; 1597 1.1 mrg if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS) 1598 1.1 mrg || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES) 1599 1.1 mrg return error_mark_node; 1600 1.1 mrg return r.resolve_to (MODE_n, type); 1601 1.1 mrg } 1602 1.1 mrg else 1603 1.1 mrg { 1604 1.1 mrg type_suffix_index type; 1605 1.1 mrg if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1606 1.1 mrg || !r.require_matching_vector_type (i + 1, type)) 1607 1.1 mrg return error_mark_node; 1608 1.1 mrg return r.resolve_to (MODE_none, type); 1609 1.1 mrg } 1610 1.1 mrg } 1611 1.1 mrg }; 1612 1.1 mrg SHAPE (clast) 1613 1.1 mrg 1614 1.1 mrg /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t). */ 1615 1.1 mrg struct compare_def : public overloaded_base<0> 1616 1.1 mrg { 1617 1.1 mrg void 1618 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1619 1.1 mrg { 1620 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1621 1.1 mrg build_all (b, "vp,v0,v0", group, MODE_none); 1622 1.1 mrg } 1623 1.1 mrg 1624 1.1 mrg tree 1625 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1626 1.1 mrg { 1627 1.1 mrg return r.resolve_uniform (2); 1628 1.1 mrg } 1629 1.1 mrg }; 1630 1.1 mrg SHAPE (compare) 1631 1.1 mrg 1632 1.1 mrg /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t) 1633 1.1 mrg svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t) 1634 1.1 mrg 1635 1.1 mrg i.e. a comparison between two vectors, or between a vector and a scalar. */ 1636 1.1 mrg struct compare_opt_n_def : public overloaded_base<0> 1637 1.1 mrg { 1638 1.1 mrg void 1639 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1640 1.1 mrg { 1641 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1642 1.1 mrg build_all (b, "vp,v0,v0", group, MODE_none); 1643 1.1 mrg build_all (b, "vp,v0,s0", group, MODE_n); 1644 1.1 mrg } 1645 1.1 mrg 1646 1.1 mrg tree 1647 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1648 1.1 mrg { 1649 1.1 mrg return r.resolve_uniform_opt_n (2); 1650 1.1 mrg } 1651 1.1 mrg }; 1652 1.1 mrg SHAPE (compare_opt_n) 1653 1.1 mrg 1654 1.1 mrg /* svbool_t svfoo[_t0](const <t0>_t *, const <t0>_t *). */ 1655 1.1 mrg struct compare_ptr_def : public overloaded_base<0> 1656 1.1 mrg { 1657 1.1 mrg void 1658 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1659 1.1 mrg { 1660 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1661 1.1 mrg build_all (b, "vp,al,al", group, MODE_none); 1662 1.1 mrg } 1663 1.1 mrg 1664 1.1 mrg tree 1665 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1666 1.1 mrg { 1667 1.1 mrg unsigned int i, nargs; 1668 1.1 mrg type_suffix_index type; 1669 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1670 1.1 mrg || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES 1671 1.1 mrg || !r.require_matching_pointer_type (i + 1, i, type)) 1672 1.1 mrg return error_mark_node; 1673 1.1 mrg 1674 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1675 1.1 mrg } 1676 1.1 mrg }; 1677 1.1 mrg SHAPE (compare_ptr) 1678 1.1 mrg 1679 1.1 mrg /* svbool_t svfoo_t0[_t1](<t1>_t, <t1>_t) 1680 1.1 mrg 1681 1.1 mrg where _t0 is a _b<bits> suffix that describes the predicate result. 1682 1.1 mrg There is no direct relationship between the element sizes of _t0 1683 1.1 mrg and _t1. */ 1684 1.1 mrg struct compare_scalar_def : public overloaded_base<1> 1685 1.1 mrg { 1686 1.1 mrg void 1687 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1688 1.1 mrg { 1689 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1690 1.1 mrg build_all (b, "vp,s1,s1", group, MODE_none); 1691 1.1 mrg } 1692 1.1 mrg 1693 1.1 mrg tree 1694 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1695 1.1 mrg { 1696 1.1 mrg unsigned int i, nargs; 1697 1.1 mrg type_suffix_index type; 1698 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1699 1.1 mrg || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES 1700 1.1 mrg || !r.require_matching_integer_scalar_type (i + 1, i, type)) 1701 1.1 mrg return error_mark_node; 1702 1.1 mrg 1703 1.1 mrg return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type); 1704 1.1 mrg } 1705 1.1 mrg }; 1706 1.1 mrg SHAPE (compare_scalar) 1707 1.1 mrg 1708 1.1 mrg /* svbool_t svfoo[_t0](sv<t0>_t, svint64_t) (for signed t0) 1709 1.1 mrg svbool_t svfoo[_n_t0](sv<t0>_t, int64_t) (for signed t0) 1710 1.1 mrg svbool_t svfoo[_t0](sv<t0>_t, svuint64_t) (for unsigned t0) 1711 1.1 mrg svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t) (for unsigned t0) 1712 1.1 mrg 1713 1.1 mrg i.e. a comparison in which the second argument is 64 bits. */ 1714 1.1 mrg struct compare_wide_opt_n_def : public overloaded_base<0> 1715 1.1 mrg { 1716 1.1 mrg void 1717 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1718 1.1 mrg { 1719 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1720 1.1 mrg build_all (b, "vp,v0,vw0", group, MODE_none); 1721 1.1 mrg build_all (b, "vp,v0,sw0", group, MODE_n); 1722 1.1 mrg } 1723 1.1 mrg 1724 1.1 mrg tree 1725 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1726 1.1 mrg { 1727 1.1 mrg unsigned int i, nargs; 1728 1.1 mrg type_suffix_index type; 1729 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1730 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 1731 1.1 mrg return error_mark_node; 1732 1.1 mrg 1733 1.1 mrg return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64); 1734 1.1 mrg } 1735 1.1 mrg }; 1736 1.1 mrg SHAPE (compare_wide_opt_n) 1737 1.1 mrg 1738 1.1 mrg /* uint64_t svfoo(). */ 1739 1.1 mrg struct count_inherent_def : public nonoverloaded_base 1740 1.1 mrg { 1741 1.1 mrg void 1742 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1743 1.1 mrg { 1744 1.1 mrg build_all (b, "su64", group, MODE_none); 1745 1.1 mrg } 1746 1.1 mrg }; 1747 1.1 mrg SHAPE (count_inherent) 1748 1.1 mrg 1749 1.1 mrg /* uint64_t svfoo(enum svpattern). */ 1750 1.1 mrg struct count_pat_def : public nonoverloaded_base 1751 1.1 mrg { 1752 1.1 mrg void 1753 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1754 1.1 mrg { 1755 1.1 mrg build_all (b, "su64,epattern", group, MODE_none); 1756 1.1 mrg } 1757 1.1 mrg }; 1758 1.1 mrg SHAPE (count_pat) 1759 1.1 mrg 1760 1.1 mrg /* uint64_t svfoo(svbool_t). */ 1761 1.1 mrg struct count_pred_def : public nonoverloaded_base 1762 1.1 mrg { 1763 1.1 mrg void 1764 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1765 1.1 mrg { 1766 1.1 mrg build_all (b, "su64,vp", group, MODE_none); 1767 1.1 mrg } 1768 1.1 mrg }; 1769 1.1 mrg SHAPE (count_pred) 1770 1.1 mrg 1771 1.1 mrg /* uint64_t svfoo[_t0](sv<t0>_t). */ 1772 1.1 mrg struct count_vector_def : public overloaded_base<0> 1773 1.1 mrg { 1774 1.1 mrg void 1775 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1776 1.1 mrg { 1777 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1778 1.1 mrg build_all (b, "su64,v0", group, MODE_none); 1779 1.1 mrg } 1780 1.1 mrg 1781 1.1 mrg tree 1782 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1783 1.1 mrg { 1784 1.1 mrg return r.resolve_uniform (1); 1785 1.1 mrg } 1786 1.1 mrg }; 1787 1.1 mrg SHAPE (count_vector) 1788 1.1 mrg 1789 1.1 mrg /* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t) 1790 1.1 mrg 1791 1.1 mrg where there are N arguments in total. */ 1792 1.1 mrg struct create_def : public overloaded_base<0> 1793 1.1 mrg { 1794 1.1 mrg void 1795 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1796 1.1 mrg { 1797 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1798 1.1 mrg build_all (b, "t0,v0*t", group, MODE_none); 1799 1.1 mrg } 1800 1.1 mrg 1801 1.1 mrg tree 1802 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1803 1.1 mrg { 1804 1.1 mrg return r.resolve_uniform (r.vectors_per_tuple ()); 1805 1.1 mrg } 1806 1.1 mrg }; 1807 1.1 mrg SHAPE (create) 1808 1.1 mrg 1809 1.1 mrg /* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t) 1810 1.1 mrg 1811 1.1 mrg where there are enough arguments to fill 128 bits of data (or to 1812 1.1 mrg control 128 bits of data in the case of predicates). */ 1813 1.1 mrg struct dupq_def : public overloaded_base<1> 1814 1.1 mrg { 1815 1.1 mrg void 1816 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1817 1.1 mrg { 1818 1.1 mrg /* The "_n" suffix is optional; the full name has it, but the short 1819 1.1 mrg name doesn't. */ 1820 1.1 mrg build_all (b, "v0,s0*q", group, MODE_n, true); 1821 1.1 mrg } 1822 1.1 mrg 1823 1.1 mrg tree 1824 1.1 mrg resolve (function_resolver &) const OVERRIDE 1825 1.1 mrg { 1826 1.1 mrg /* The short forms just make "_n" implicit, so no resolution is needed. */ 1827 1.1 mrg gcc_unreachable (); 1828 1.1 mrg } 1829 1.1 mrg }; 1830 1.1 mrg SHAPE (dupq) 1831 1.1 mrg 1832 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t) 1833 1.1 mrg 1834 1.1 mrg where the final argument is an integer constant expression that when 1835 1.1 mrg multiplied by the number of bytes in t0 is in the range [0, 255]. */ 1836 1.1 mrg struct ext_def : public overloaded_base<0> 1837 1.1 mrg { 1838 1.1 mrg void 1839 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1840 1.1 mrg { 1841 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1842 1.1 mrg build_all (b, "v0,v0,v0,su64", group, MODE_none); 1843 1.1 mrg } 1844 1.1 mrg 1845 1.1 mrg tree 1846 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1847 1.1 mrg { 1848 1.1 mrg return r.resolve_uniform (2, 1); 1849 1.1 mrg } 1850 1.1 mrg 1851 1.1 mrg bool 1852 1.1 mrg check (function_checker &c) const OVERRIDE 1853 1.1 mrg { 1854 1.1 mrg unsigned int bytes = c.type_suffix (0).element_bytes; 1855 1.1 mrg return c.require_immediate_range (2, 0, 256 / bytes - 1); 1856 1.1 mrg } 1857 1.1 mrg }; 1858 1.1 mrg SHAPE (ext) 1859 1.1 mrg 1860 1.1 mrg /* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t). */ 1861 1.1 mrg struct fold_left_def : public overloaded_base<0> 1862 1.1 mrg { 1863 1.1 mrg void 1864 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1865 1.1 mrg { 1866 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1867 1.1 mrg build_all (b, "s0,s0,v0", group, MODE_none); 1868 1.1 mrg } 1869 1.1 mrg 1870 1.1 mrg tree 1871 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1872 1.1 mrg { 1873 1.1 mrg unsigned int i, nargs; 1874 1.1 mrg type_suffix_index type; 1875 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1876 1.1 mrg || !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS) 1877 1.1 mrg || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES) 1878 1.1 mrg return error_mark_node; 1879 1.1 mrg 1880 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1881 1.1 mrg } 1882 1.1 mrg }; 1883 1.1 mrg SHAPE (fold_left) 1884 1.1 mrg 1885 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t) 1886 1.1 mrg 1887 1.1 mrg where the final argument is an integer constant expression in 1888 1.1 mrg the range [0, N - 1]. */ 1889 1.1 mrg struct get_def : public overloaded_base<0> 1890 1.1 mrg { 1891 1.1 mrg void 1892 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1893 1.1 mrg { 1894 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1895 1.1 mrg build_all (b, "v0,t0,su64", group, MODE_none); 1896 1.1 mrg } 1897 1.1 mrg 1898 1.1 mrg tree 1899 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1900 1.1 mrg { 1901 1.1 mrg unsigned int i, nargs; 1902 1.1 mrg type_suffix_index type; 1903 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1904 1.1 mrg || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES 1905 1.1 mrg || !r.require_integer_immediate (i + 1)) 1906 1.1 mrg return error_mark_node; 1907 1.1 mrg 1908 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1909 1.1 mrg } 1910 1.1 mrg 1911 1.1 mrg bool 1912 1.1 mrg check (function_checker &c) const OVERRIDE 1913 1.1 mrg { 1914 1.1 mrg unsigned int nvectors = c.vectors_per_tuple (); 1915 1.1 mrg return c.require_immediate_range (1, 0, nvectors - 1); 1916 1.1 mrg } 1917 1.1 mrg }; 1918 1.1 mrg SHAPE (get) 1919 1.1 mrg 1920 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t) 1921 1.1 mrg <t0>_t svfoo[_n_t0](<t0>_t, uint64_t) 1922 1.1 mrg 1923 1.1 mrg where the t0 in the vector form is a signed or unsigned integer 1924 1.1 mrg whose size is tied to the [bhwd] suffix of "svfoo". */ 1925 1.1 mrg struct inc_dec_def : public inc_dec_base 1926 1.1 mrg { 1927 1.1 mrg CONSTEXPR inc_dec_def () : inc_dec_base (false) {} 1928 1.1 mrg 1929 1.1 mrg void 1930 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1931 1.1 mrg { 1932 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1933 1.1 mrg /* These functions are unusual in that the type suffixes for 1934 1.1 mrg the scalar and vector forms are not related. The vector 1935 1.1 mrg form always has exactly two potential suffixes while the 1936 1.1 mrg scalar form always has four. */ 1937 1.1 mrg if (group.types[2][0] == NUM_TYPE_SUFFIXES) 1938 1.1 mrg build_all (b, "v0,v0,su64", group, MODE_none); 1939 1.1 mrg else 1940 1.1 mrg build_all (b, "s0,s0,su64", group, MODE_n); 1941 1.1 mrg } 1942 1.1 mrg }; 1943 1.1 mrg SHAPE (inc_dec) 1944 1.1 mrg 1945 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t) 1946 1.1 mrg <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t) 1947 1.1 mrg 1948 1.1 mrg where the t0 in the vector form is a signed or unsigned integer 1949 1.1 mrg whose size is tied to the [bhwd] suffix of "svfoo". */ 1950 1.1 mrg struct inc_dec_pat_def : public inc_dec_base 1951 1.1 mrg { 1952 1.1 mrg CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {} 1953 1.1 mrg 1954 1.1 mrg void 1955 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1956 1.1 mrg { 1957 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1958 1.1 mrg /* These functions are unusual in that the type suffixes for 1959 1.1 mrg the scalar and vector forms are not related. The vector 1960 1.1 mrg form always has exactly two potential suffixes while the 1961 1.1 mrg scalar form always has four. */ 1962 1.1 mrg if (group.types[2][0] == NUM_TYPE_SUFFIXES) 1963 1.1 mrg build_all (b, "v0,v0,epattern,su64", group, MODE_none); 1964 1.1 mrg else 1965 1.1 mrg build_all (b, "s0,s0,epattern,su64", group, MODE_n); 1966 1.1 mrg } 1967 1.1 mrg }; 1968 1.1 mrg SHAPE (inc_dec_pat) 1969 1.1 mrg 1970 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t). */ 1971 1.1 mrg struct inc_dec_pred_def : public overloaded_base<0> 1972 1.1 mrg { 1973 1.1 mrg void 1974 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 1975 1.1 mrg { 1976 1.1 mrg b.add_overloaded_functions (group, MODE_none); 1977 1.1 mrg build_all (b, "v0,v0,vp", group, MODE_none); 1978 1.1 mrg } 1979 1.1 mrg 1980 1.1 mrg tree 1981 1.1 mrg resolve (function_resolver &r) const OVERRIDE 1982 1.1 mrg { 1983 1.1 mrg unsigned int i, nargs; 1984 1.1 mrg type_suffix_index type; 1985 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 1986 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 1987 1.1 mrg || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t)) 1988 1.1 mrg return error_mark_node; 1989 1.1 mrg 1990 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 1991 1.1 mrg } 1992 1.1 mrg }; 1993 1.1 mrg SHAPE (inc_dec_pred) 1994 1.1 mrg 1995 1.1 mrg /* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t) 1996 1.1 mrg 1997 1.1 mrg where _t1 is a _b<bits> suffix that describes the svbool_t argument. */ 1998 1.1 mrg struct inc_dec_pred_scalar_def : public overloaded_base<2> 1999 1.1 mrg { 2000 1.1 mrg void 2001 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2002 1.1 mrg { 2003 1.1 mrg b.add_overloaded_functions (group, MODE_n); 2004 1.1 mrg build_all (b, "s0,s0,vp", group, MODE_n); 2005 1.1 mrg } 2006 1.1 mrg 2007 1.1 mrg tree 2008 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2009 1.1 mrg { 2010 1.1 mrg unsigned int i, nargs; 2011 1.1 mrg type_suffix_index type; 2012 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 2013 1.1 mrg || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES 2014 1.1 mrg || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t)) 2015 1.1 mrg return error_mark_node; 2016 1.1 mrg 2017 1.1 mrg return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]); 2018 1.1 mrg } 2019 1.1 mrg }; 2020 1.1 mrg SHAPE (inc_dec_pred_scalar) 2021 1.1 mrg 2022 1.1 mrg /* sv<t0>[xN]_t svfoo_t0(). */ 2023 1.1 mrg struct inherent_def : public nonoverloaded_base 2024 1.1 mrg { 2025 1.1 mrg void 2026 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2027 1.1 mrg { 2028 1.1 mrg build_all (b, "t0", group, MODE_none); 2029 1.1 mrg } 2030 1.1 mrg }; 2031 1.1 mrg SHAPE (inherent) 2032 1.1 mrg 2033 1.1 mrg /* svbool_t svfoo[_b](). */ 2034 1.1 mrg struct inherent_b_def : public overloaded_base<0> 2035 1.1 mrg { 2036 1.1 mrg void 2037 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2038 1.1 mrg { 2039 1.1 mrg /* The "_b" suffix is optional; the full name has it, but the short 2040 1.1 mrg name doesn't. */ 2041 1.1 mrg build_all (b, "v0", group, MODE_none, true); 2042 1.1 mrg } 2043 1.1 mrg 2044 1.1 mrg tree 2045 1.1 mrg resolve (function_resolver &) const OVERRIDE 2046 1.1 mrg { 2047 1.1 mrg /* The short forms just make "_b" implicit, so no resolution is needed. */ 2048 1.1 mrg gcc_unreachable (); 2049 1.1 mrg } 2050 1.1 mrg }; 2051 1.1 mrg SHAPE (inherent_b) 2052 1.1 mrg 2053 1.1 mrg /* sv<t0>[xN]_t svfoo[_t0](const <t0>_t *) 2054 1.1 mrg sv<t0>[xN]_t svfoo_vnum[_t0](const <t0>_t *, int64_t). */ 2055 1.1 mrg struct load_def : public load_contiguous_base 2056 1.1 mrg { 2057 1.1 mrg void 2058 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2059 1.1 mrg { 2060 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2061 1.1 mrg b.add_overloaded_functions (group, MODE_vnum); 2062 1.1 mrg build_all (b, "t0,al", group, MODE_none); 2063 1.1 mrg build_all (b, "t0,al,ss64", group, MODE_vnum); 2064 1.1 mrg } 2065 1.1 mrg }; 2066 1.1 mrg SHAPE (load) 2067 1.1 mrg 2068 1.1 mrg /* sv<t0>_t svfoo_t0(const <X>_t *) 2069 1.1 mrg sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t) 2070 1.1 mrg 2071 1.1 mrg where <X> is determined by the function base name. */ 2072 1.1 mrg struct load_ext_def : public nonoverloaded_base 2073 1.1 mrg { 2074 1.1 mrg void 2075 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2076 1.1 mrg { 2077 1.1 mrg build_all (b, "t0,al", group, MODE_none); 2078 1.1 mrg build_all (b, "t0,al,ss64", group, MODE_vnum); 2079 1.1 mrg } 2080 1.1 mrg }; 2081 1.1 mrg SHAPE (load_ext) 2082 1.1 mrg 2083 1.1 mrg /* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t) 2084 1.1 mrg sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t) 2085 1.1 mrg sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t) 2086 1.1 mrg sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t) 2087 1.1 mrg 2088 1.1 mrg sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t) 2089 1.1 mrg sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t) 2090 1.1 mrg 2091 1.1 mrg where <X> is determined by the function base name. */ 2092 1.1 mrg struct load_ext_gather_index_def : public load_ext_gather_base 2093 1.1 mrg { 2094 1.1 mrg void 2095 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2096 1.1 mrg { 2097 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2098 1.1 mrg build_sv_index (b, "t0,al,d", group); 2099 1.1 mrg build_vs_index (b, "t0,b,ss64", group); 2100 1.1 mrg } 2101 1.1 mrg }; 2102 1.1 mrg SHAPE (load_ext_gather_index) 2103 1.1 mrg 2104 1.1 mrg /* sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t) 2105 1.1 mrg sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t) 2106 1.1 mrg 2107 1.1 mrg sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t) 2108 1.1 mrg sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t) 2109 1.1 mrg 2110 1.1 mrg where <X> is determined by the function base name. This is 2111 1.1 mrg load_ext_gather_index that doesn't support 32-bit vector indices. */ 2112 1.1 mrg struct load_ext_gather_index_restricted_def : public load_ext_gather_base 2113 1.1 mrg { 2114 1.1 mrg void 2115 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2116 1.1 mrg { 2117 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2118 1.1 mrg build_sv_index64 (b, "t0,al,d", group); 2119 1.1 mrg build_vs_index (b, "t0,b,ss64", group); 2120 1.1 mrg } 2121 1.1 mrg }; 2122 1.1 mrg SHAPE (load_ext_gather_index_restricted) 2123 1.1 mrg 2124 1.1 mrg /* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t) 2125 1.1 mrg sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t) 2126 1.1 mrg sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t) 2127 1.1 mrg sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t) 2128 1.1 mrg 2129 1.1 mrg sv<t0>_t svfoo[_u32base]_t0(svuint32_t) 2130 1.1 mrg sv<t0>_t svfoo[_u64base]_t0(svuint64_t) 2131 1.1 mrg 2132 1.1 mrg sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t) 2133 1.1 mrg sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t) 2134 1.1 mrg 2135 1.1 mrg where <X> is determined by the function base name. */ 2136 1.1 mrg struct load_ext_gather_offset_def : public load_ext_gather_base 2137 1.1 mrg { 2138 1.1 mrg void 2139 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2140 1.1 mrg { 2141 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2142 1.1 mrg build_sv_offset (b, "t0,al,d", group); 2143 1.1 mrg build_v_base (b, "t0,b", group, true); 2144 1.1 mrg build_vs_offset (b, "t0,b,ss64", group); 2145 1.1 mrg } 2146 1.1 mrg }; 2147 1.1 mrg SHAPE (load_ext_gather_offset) 2148 1.1 mrg 2149 1.1 mrg /* sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t) 2150 1.1 mrg sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t) 2151 1.1 mrg sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t) 2152 1.1 mrg 2153 1.1 mrg sv<t0>_t svfoo[_u32base]_t0(svuint32_t) 2154 1.1 mrg sv<t0>_t svfoo[_u64base]_t0(svuint64_t) 2155 1.1 mrg 2156 1.1 mrg sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t) 2157 1.1 mrg sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t) 2158 1.1 mrg 2159 1.1 mrg where <X> is determined by the function base name. This is 2160 1.1 mrg load_ext_gather_offset without the s32 vector offset form. */ 2161 1.1 mrg struct load_ext_gather_offset_restricted_def : public load_ext_gather_base 2162 1.1 mrg { 2163 1.1 mrg void 2164 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2165 1.1 mrg { 2166 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2167 1.1 mrg build_sv_uint_offset (b, "t0,al,d", group); 2168 1.1 mrg build_v_base (b, "t0,b", group, true); 2169 1.1 mrg build_vs_offset (b, "t0,b,ss64", group); 2170 1.1 mrg } 2171 1.1 mrg }; 2172 1.1 mrg SHAPE (load_ext_gather_offset_restricted) 2173 1.1 mrg 2174 1.1 mrg /* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t) 2175 1.1 mrg sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t) 2176 1.1 mrg sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t) 2177 1.1 mrg sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t) 2178 1.1 mrg 2179 1.1 mrg sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t) 2180 1.1 mrg sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t) 2181 1.1 mrg sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t) 2182 1.1 mrg sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t). */ 2183 1.1 mrg struct load_gather_sv_def : public load_gather_sv_base 2184 1.1 mrg { 2185 1.1 mrg void 2186 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2187 1.1 mrg { 2188 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2189 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2190 1.1 mrg build_sv_index (b, "t0,al,d", group); 2191 1.1 mrg build_sv_offset (b, "t0,al,d", group); 2192 1.1 mrg } 2193 1.1 mrg }; 2194 1.1 mrg SHAPE (load_gather_sv) 2195 1.1 mrg 2196 1.1 mrg /* sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t) 2197 1.1 mrg sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t) 2198 1.1 mrg 2199 1.1 mrg sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t) 2200 1.1 mrg sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t) 2201 1.1 mrg sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t) 2202 1.1 mrg 2203 1.1 mrg This is load_gather_sv without the 32-bit vector index forms and 2204 1.1 mrg without the s32 vector offset form. */ 2205 1.1 mrg struct load_gather_sv_restricted_def : public load_gather_sv_base 2206 1.1 mrg { 2207 1.1 mrg void 2208 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2209 1.1 mrg { 2210 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2211 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2212 1.1 mrg build_sv_index64 (b, "t0,al,d", group); 2213 1.1 mrg build_sv_uint_offset (b, "t0,al,d", group); 2214 1.1 mrg } 2215 1.1 mrg }; 2216 1.1 mrg SHAPE (load_gather_sv_restricted) 2217 1.1 mrg 2218 1.1 mrg /* sv<t0>_t svfoo[_u32base]_t0(svuint32_t) 2219 1.1 mrg sv<t0>_t svfoo[_u64base]_t0(svuint64_t) 2220 1.1 mrg 2221 1.1 mrg sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t) 2222 1.1 mrg sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t) 2223 1.1 mrg 2224 1.1 mrg sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t) 2225 1.1 mrg sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t). */ 2226 1.1 mrg struct load_gather_vs_def : public overloaded_base<1> 2227 1.1 mrg { 2228 1.1 mrg void 2229 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2230 1.1 mrg { 2231 1.1 mrg /* The base vector mode is optional; the full name has it but the 2232 1.1 mrg short name doesn't. There is no ambiguity with SHAPE_load_gather_sv 2233 1.1 mrg because the latter uses an implicit type suffix. */ 2234 1.1 mrg build_v_base (b, "t0,b", group, true); 2235 1.1 mrg build_vs_index (b, "t0,b,ss64", group, true); 2236 1.1 mrg build_vs_offset (b, "t0,b,ss64", group, true); 2237 1.1 mrg } 2238 1.1 mrg 2239 1.1 mrg tree 2240 1.1 mrg resolve (function_resolver &) const OVERRIDE 2241 1.1 mrg { 2242 1.1 mrg /* The short name just makes the base vector mode implicit; 2243 1.1 mrg no resolution is needed. */ 2244 1.1 mrg gcc_unreachable (); 2245 1.1 mrg } 2246 1.1 mrg }; 2247 1.1 mrg SHAPE (load_gather_vs) 2248 1.1 mrg 2249 1.1 mrg /* sv<t0>_t svfoo[_t0](const <t0>_t *) 2250 1.1 mrg 2251 1.1 mrg The only difference from "load" is that this shape has no vnum form. */ 2252 1.1 mrg struct load_replicate_def : public load_contiguous_base 2253 1.1 mrg { 2254 1.1 mrg void 2255 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2256 1.1 mrg { 2257 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2258 1.1 mrg build_all (b, "t0,al", group, MODE_none); 2259 1.1 mrg } 2260 1.1 mrg }; 2261 1.1 mrg SHAPE (load_replicate) 2262 1.1 mrg 2263 1.1 mrg /* svbool_t svfoo(enum svpattern). */ 2264 1.1 mrg struct pattern_pred_def : public nonoverloaded_base 2265 1.1 mrg { 2266 1.1 mrg void 2267 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2268 1.1 mrg { 2269 1.1 mrg build_all (b, "vp,epattern", group, MODE_none); 2270 1.1 mrg } 2271 1.1 mrg }; 2272 1.1 mrg SHAPE (pattern_pred) 2273 1.1 mrg 2274 1.1 mrg /* void svfoo(const void *, svprfop) 2275 1.1 mrg void svfoo_vnum(const void *, int64_t, svprfop). */ 2276 1.1 mrg struct prefetch_def : public nonoverloaded_base 2277 1.1 mrg { 2278 1.1 mrg void 2279 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2280 1.1 mrg { 2281 1.1 mrg build_all (b, "_,ap,eprfop", group, MODE_none); 2282 1.1 mrg build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum); 2283 1.1 mrg } 2284 1.1 mrg }; 2285 1.1 mrg SHAPE (prefetch) 2286 1.1 mrg 2287 1.1 mrg /* void svfoo_[s32]index(const void *, svint32_t, svprfop) 2288 1.1 mrg void svfoo_[s64]index(const void *, svint64_t, svprfop) 2289 1.1 mrg void svfoo_[u32]index(const void *, svuint32_t, svprfop) 2290 1.1 mrg void svfoo_[u64]index(const void *, svuint64_t, svprfop) 2291 1.1 mrg 2292 1.1 mrg void svfoo[_u32base](svuint32_t, svprfop) 2293 1.1 mrg void svfoo[_u64base](svuint64_t, svprfop) 2294 1.1 mrg 2295 1.1 mrg void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop) 2296 1.1 mrg void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop). */ 2297 1.1 mrg struct prefetch_gather_index_def : public prefetch_gather_base 2298 1.1 mrg { 2299 1.1 mrg void 2300 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2301 1.1 mrg { 2302 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2303 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2304 1.1 mrg build_sv_index (b, "_,ap,d,eprfop", group); 2305 1.1 mrg build_v_base (b, "_,b,eprfop", group); 2306 1.1 mrg build_vs_index (b, "_,b,ss64,eprfop", group); 2307 1.1 mrg } 2308 1.1 mrg }; 2309 1.1 mrg SHAPE (prefetch_gather_index) 2310 1.1 mrg 2311 1.1 mrg /* void svfoo_[s32]offset(const void *, svint32_t, svprfop) 2312 1.1 mrg void svfoo_[s64]offset(const void *, svint64_t, svprfop) 2313 1.1 mrg void svfoo_[u32]offset(const void *, svuint32_t, svprfop) 2314 1.1 mrg void svfoo_[u64]offset(const void *, svuint64_t, svprfop) 2315 1.1 mrg 2316 1.1 mrg void svfoo[_u32base](svuint32_t, svprfop) 2317 1.1 mrg void svfoo[_u64base](svuint64_t, svprfop) 2318 1.1 mrg 2319 1.1 mrg void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop) 2320 1.1 mrg void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop). */ 2321 1.1 mrg struct prefetch_gather_offset_def : public prefetch_gather_base 2322 1.1 mrg { 2323 1.1 mrg void 2324 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2325 1.1 mrg { 2326 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2327 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2328 1.1 mrg build_sv_offset (b, "_,ap,d,eprfop", group); 2329 1.1 mrg build_v_base (b, "_,b,eprfop", group); 2330 1.1 mrg build_vs_offset (b, "_,b,ss64,eprfop", group); 2331 1.1 mrg } 2332 1.1 mrg }; 2333 1.1 mrg SHAPE (prefetch_gather_offset) 2334 1.1 mrg 2335 1.1 mrg /* bool svfoo(svbool_t). */ 2336 1.1 mrg struct ptest_def : public nonoverloaded_base 2337 1.1 mrg { 2338 1.1 mrg void 2339 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2340 1.1 mrg { 2341 1.1 mrg build_all (b, "sp,vp", group, MODE_none); 2342 1.1 mrg } 2343 1.1 mrg }; 2344 1.1 mrg SHAPE (ptest) 2345 1.1 mrg 2346 1.1 mrg /* svbool_t svfoo(). */ 2347 1.1 mrg struct rdffr_def : public nonoverloaded_base 2348 1.1 mrg { 2349 1.1 mrg void 2350 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2351 1.1 mrg { 2352 1.1 mrg build_all (b, "vp", group, MODE_none); 2353 1.1 mrg } 2354 1.1 mrg }; 2355 1.1 mrg SHAPE (rdffr) 2356 1.1 mrg 2357 1.1 mrg /* <t0>_t svfoo[_t0](sv<t0>_t). */ 2358 1.1 mrg struct reduction_def : public overloaded_base<0> 2359 1.1 mrg { 2360 1.1 mrg void 2361 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2362 1.1 mrg { 2363 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2364 1.1 mrg build_all (b, "s0,v0", group, MODE_none); 2365 1.1 mrg } 2366 1.1 mrg 2367 1.1 mrg tree 2368 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2369 1.1 mrg { 2370 1.1 mrg return r.resolve_uniform (1); 2371 1.1 mrg } 2372 1.1 mrg }; 2373 1.1 mrg SHAPE (reduction) 2374 1.1 mrg 2375 1.1 mrg /* int64_t svfoo[_t0](sv<t0>_t) (for signed t0) 2376 1.1 mrg uint64_t svfoo[_t0](sv<t0>_t) (for unsigned t0) 2377 1.1 mrg <t0>_t svfoo[_t0](sv<t0>_t) (for floating-point t0) 2378 1.1 mrg 2379 1.1 mrg i.e. a version of "reduction" in which the return type for integers 2380 1.1 mrg always has 64 bits. */ 2381 1.1 mrg struct reduction_wide_def : public overloaded_base<0> 2382 1.1 mrg { 2383 1.1 mrg void 2384 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2385 1.1 mrg { 2386 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2387 1.1 mrg build_all (b, "sw0,v0", group, MODE_none); 2388 1.1 mrg } 2389 1.1 mrg 2390 1.1 mrg tree 2391 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2392 1.1 mrg { 2393 1.1 mrg return r.resolve_uniform (1); 2394 1.1 mrg } 2395 1.1 mrg }; 2396 1.1 mrg SHAPE (reduction_wide) 2397 1.1 mrg 2398 1.1 mrg /* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t) 2399 1.1 mrg 2400 1.1 mrg where the second argument is an integer constant expression in the 2401 1.1 mrg range [0, N - 1]. */ 2402 1.1 mrg struct set_def : public overloaded_base<0> 2403 1.1 mrg { 2404 1.1 mrg void 2405 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2406 1.1 mrg { 2407 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2408 1.1 mrg build_all (b, "t0,t0,su64,v0", group, MODE_none); 2409 1.1 mrg } 2410 1.1 mrg 2411 1.1 mrg tree 2412 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2413 1.1 mrg { 2414 1.1 mrg unsigned int i, nargs; 2415 1.1 mrg type_suffix_index type; 2416 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 2417 1.1 mrg || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES 2418 1.1 mrg || !r.require_integer_immediate (i + 1) 2419 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type)) 2420 1.1 mrg return error_mark_node; 2421 1.1 mrg 2422 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 2423 1.1 mrg } 2424 1.1 mrg 2425 1.1 mrg bool 2426 1.1 mrg check (function_checker &c) const OVERRIDE 2427 1.1 mrg { 2428 1.1 mrg unsigned int nvectors = c.vectors_per_tuple (); 2429 1.1 mrg return c.require_immediate_range (1, 0, nvectors - 1); 2430 1.1 mrg } 2431 1.1 mrg }; 2432 1.1 mrg SHAPE (set) 2433 1.1 mrg 2434 1.1 mrg /* void svfoo(). */ 2435 1.1 mrg struct setffr_def : public nonoverloaded_base 2436 1.1 mrg { 2437 1.1 mrg void 2438 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2439 1.1 mrg { 2440 1.1 mrg build_all (b, "_", group, MODE_none); 2441 1.1 mrg } 2442 1.1 mrg }; 2443 1.1 mrg SHAPE (setffr) 2444 1.1 mrg 2445 1.1 mrg /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t) 2446 1.1 mrg 2447 1.1 mrg where the final argument must be an integer constant expression in the 2448 1.1 mrg range [0, sizeof (<t0>_t) * 8 - 1]. */ 2449 1.1 mrg struct shift_left_imm_def : public overloaded_base<0> 2450 1.1 mrg { 2451 1.1 mrg void 2452 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2453 1.1 mrg { 2454 1.1 mrg b.add_overloaded_functions (group, MODE_n); 2455 1.1 mrg build_all (b, "v0,v0,su64", group, MODE_n); 2456 1.1 mrg } 2457 1.1 mrg 2458 1.1 mrg tree 2459 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2460 1.1 mrg { 2461 1.1 mrg return r.resolve_uniform (1, 1); 2462 1.1 mrg } 2463 1.1 mrg 2464 1.1 mrg bool 2465 1.1 mrg check (function_checker &c) const OVERRIDE 2466 1.1 mrg { 2467 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits; 2468 1.1 mrg return c.require_immediate_range (1, 0, bits - 1); 2469 1.1 mrg } 2470 1.1 mrg }; 2471 1.1 mrg SHAPE (shift_left_imm) 2472 1.1 mrg 2473 1.1 mrg /* sv<t0>_t svfoo[_n_t0])(sv<t0:half>_t, uint64_t) 2474 1.1 mrg 2475 1.1 mrg where the final argument must be an integer constant expression in the 2476 1.1 mrg range [0, sizeof (<t0>_t) * 4 - 1]. */ 2477 1.1 mrg struct shift_left_imm_long_def : public binary_imm_long_base 2478 1.1 mrg { 2479 1.1 mrg bool 2480 1.1 mrg check (function_checker &c) const OVERRIDE 2481 1.1 mrg { 2482 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits / 2; 2483 1.1 mrg return c.require_immediate_range (1, 0, bits - 1); 2484 1.1 mrg } 2485 1.1 mrg }; 2486 1.1 mrg SHAPE (shift_left_imm_long) 2487 1.1 mrg 2488 1.1 mrg /* sv<t0:uint>_t svfoo[_n_t0])(sv<t0>_t, uint64_t) 2489 1.1 mrg 2490 1.1 mrg where the final argument must be an integer constant expression in the 2491 1.1 mrg range [0, sizeof (<t0>_t) * 8 - 1]. */ 2492 1.1 mrg struct shift_left_imm_to_uint_def : public shift_left_imm_def 2493 1.1 mrg { 2494 1.1 mrg void 2495 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2496 1.1 mrg { 2497 1.1 mrg b.add_overloaded_functions (group, MODE_n); 2498 1.1 mrg build_all (b, "vu0,v0,su64", group, MODE_n); 2499 1.1 mrg } 2500 1.1 mrg }; 2501 1.1 mrg SHAPE (shift_left_imm_to_uint) 2502 1.1 mrg 2503 1.1 mrg /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t) 2504 1.1 mrg 2505 1.1 mrg where the final argument must be an integer constant expression in the 2506 1.1 mrg range [1, sizeof (<t0>_t) * 8]. */ 2507 1.1 mrg struct shift_right_imm_def : public overloaded_base<0> 2508 1.1 mrg { 2509 1.1 mrg void 2510 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2511 1.1 mrg { 2512 1.1 mrg b.add_overloaded_functions (group, MODE_n); 2513 1.1 mrg build_all (b, "v0,v0,su64", group, MODE_n); 2514 1.1 mrg } 2515 1.1 mrg 2516 1.1 mrg tree 2517 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2518 1.1 mrg { 2519 1.1 mrg return r.resolve_uniform (1, 1); 2520 1.1 mrg } 2521 1.1 mrg 2522 1.1 mrg bool 2523 1.1 mrg check (function_checker &c) const OVERRIDE 2524 1.1 mrg { 2525 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits; 2526 1.1 mrg return c.require_immediate_range (1, 1, bits); 2527 1.1 mrg } 2528 1.1 mrg }; 2529 1.1 mrg SHAPE (shift_right_imm) 2530 1.1 mrg 2531 1.1 mrg /* sv<t0:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t) 2532 1.1 mrg 2533 1.1 mrg where the final argument must be an integer constant expression in the 2534 1.1 mrg range [1, sizeof (<t0>_t) * 4]. */ 2535 1.1 mrg typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base<>, 1> 2536 1.1 mrg shift_right_imm_narrowb_def; 2537 1.1 mrg SHAPE (shift_right_imm_narrowb) 2538 1.1 mrg 2539 1.1 mrg /* sv<t0:half>_t svfoo[_n_t0])(sv<t0:half>_t, sv<t0>_t, uint64_t) 2540 1.1 mrg 2541 1.1 mrg where the final argument must be an integer constant expression in the 2542 1.1 mrg range [1, sizeof (<t0>_t) * 4]. */ 2543 1.1 mrg typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base<>, 2> 2544 1.1 mrg shift_right_imm_narrowt_def; 2545 1.1 mrg SHAPE (shift_right_imm_narrowt) 2546 1.1 mrg 2547 1.1 mrg /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t) 2548 1.1 mrg 2549 1.1 mrg where the final argument must be an integer constant expression in the 2550 1.1 mrg range [1, sizeof (<t0>_t) * 4]. */ 2551 1.1 mrg typedef binary_imm_narrowb_base<TYPE_unsigned> 2552 1.1 mrg binary_imm_narrowb_base_unsigned; 2553 1.1 mrg typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base_unsigned, 1> 2554 1.1 mrg shift_right_imm_narrowb_to_uint_def; 2555 1.1 mrg SHAPE (shift_right_imm_narrowb_to_uint) 2556 1.1 mrg 2557 1.1 mrg /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0:uint:half>_t, sv<t0>_t, uint64_t) 2558 1.1 mrg 2559 1.1 mrg where the final argument must be an integer constant expression in the 2560 1.1 mrg range [1, sizeof (<t0>_t) * 4]. */ 2561 1.1 mrg typedef binary_imm_narrowt_base<TYPE_unsigned> 2562 1.1 mrg binary_imm_narrowt_base_unsigned; 2563 1.1 mrg typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base_unsigned, 2> 2564 1.1 mrg shift_right_imm_narrowt_to_uint_def; 2565 1.1 mrg SHAPE (shift_right_imm_narrowt_to_uint) 2566 1.1 mrg 2567 1.1 mrg /* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t) 2568 1.1 mrg void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t) 2569 1.1 mrg 2570 1.1 mrg where <X> might be tied to <t0> (for non-truncating stores) or might 2571 1.1 mrg depend on the function base name (for truncating stores). */ 2572 1.1 mrg struct store_def : public overloaded_base<0> 2573 1.1 mrg { 2574 1.1 mrg void 2575 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2576 1.1 mrg { 2577 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2578 1.1 mrg b.add_overloaded_functions (group, MODE_vnum); 2579 1.1 mrg build_all (b, "_,as,t0", group, MODE_none); 2580 1.1 mrg build_all (b, "_,as,ss64,t0", group, MODE_vnum); 2581 1.1 mrg } 2582 1.1 mrg 2583 1.1 mrg tree 2584 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2585 1.1 mrg { 2586 1.1 mrg bool vnum_p = r.mode_suffix_id == MODE_vnum; 2587 1.1 mrg gcc_assert (r.mode_suffix_id == MODE_none || vnum_p); 2588 1.1 mrg 2589 1.1 mrg unsigned int i, nargs; 2590 1.1 mrg type_suffix_index type; 2591 1.1 mrg if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs) 2592 1.1 mrg || !r.require_pointer_type (i) 2593 1.1 mrg || (vnum_p && !r.require_scalar_type (i + 1, "int64_t")) 2594 1.1 mrg || ((type = r.infer_tuple_type (nargs - 1)) == NUM_TYPE_SUFFIXES)) 2595 1.1 mrg return error_mark_node; 2596 1.1 mrg 2597 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 2598 1.1 mrg } 2599 1.1 mrg }; 2600 1.1 mrg SHAPE (store) 2601 1.1 mrg 2602 1.1 mrg /* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t) 2603 1.1 mrg void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t) 2604 1.1 mrg void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t) 2605 1.1 mrg void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t) 2606 1.1 mrg 2607 1.1 mrg void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t) 2608 1.1 mrg void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t) 2609 1.1 mrg 2610 1.1 mrg where <X> might be tied to <t0> (for non-truncating stores) or might 2611 1.1 mrg depend on the function base name (for truncating stores). */ 2612 1.1 mrg struct store_scatter_index_def : public store_scatter_base 2613 1.1 mrg { 2614 1.1 mrg void 2615 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2616 1.1 mrg { 2617 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2618 1.1 mrg build_sv_index (b, "_,as,d,t0", group); 2619 1.1 mrg build_vs_index (b, "_,b,ss64,t0", group); 2620 1.1 mrg } 2621 1.1 mrg }; 2622 1.1 mrg SHAPE (store_scatter_index) 2623 1.1 mrg 2624 1.1 mrg /* void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t) 2625 1.1 mrg void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t) 2626 1.1 mrg 2627 1.1 mrg void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t) 2628 1.1 mrg void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t) 2629 1.1 mrg 2630 1.1 mrg i.e. a version of store_scatter_index that doesn't support 32-bit 2631 1.1 mrg vector indices. */ 2632 1.1 mrg struct store_scatter_index_restricted_def : public store_scatter_base 2633 1.1 mrg { 2634 1.1 mrg void 2635 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2636 1.1 mrg { 2637 1.1 mrg b.add_overloaded_functions (group, MODE_index); 2638 1.1 mrg build_sv_index64 (b, "_,as,d,t0", group); 2639 1.1 mrg build_vs_index (b, "_,b,ss64,t0", group); 2640 1.1 mrg } 2641 1.1 mrg }; 2642 1.1 mrg SHAPE (store_scatter_index_restricted) 2643 1.1 mrg 2644 1.1 mrg /* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t) 2645 1.1 mrg void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t) 2646 1.1 mrg void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t) 2647 1.1 mrg void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t) 2648 1.1 mrg 2649 1.1 mrg void svfoo[_u32base_t0](svuint32_t, sv<t0>_t) 2650 1.1 mrg void svfoo[_u64base_t0](svuint64_t, sv<t0>_t) 2651 1.1 mrg 2652 1.1 mrg void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t) 2653 1.1 mrg void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t) 2654 1.1 mrg 2655 1.1 mrg where <X> might be tied to <t0> (for non-truncating stores) or might 2656 1.1 mrg depend on the function base name (for truncating stores). */ 2657 1.1 mrg struct store_scatter_offset_def : public store_scatter_base 2658 1.1 mrg { 2659 1.1 mrg void 2660 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2661 1.1 mrg { 2662 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2663 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2664 1.1 mrg build_sv_offset (b, "_,as,d,t0", group); 2665 1.1 mrg build_v_base (b, "_,b,t0", group); 2666 1.1 mrg build_vs_offset (b, "_,b,ss64,t0", group); 2667 1.1 mrg } 2668 1.1 mrg }; 2669 1.1 mrg SHAPE (store_scatter_offset) 2670 1.1 mrg 2671 1.1 mrg /* void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t) 2672 1.1 mrg void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t) 2673 1.1 mrg void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t) 2674 1.1 mrg 2675 1.1 mrg void svfoo[_u32base_t0](svuint32_t, sv<t0>_t) 2676 1.1 mrg void svfoo[_u64base_t0](svuint64_t, sv<t0>_t) 2677 1.1 mrg 2678 1.1 mrg void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t) 2679 1.1 mrg void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t) 2680 1.1 mrg 2681 1.1 mrg i.e. a version of store_scatter_offset that doesn't support svint32_t 2682 1.1 mrg offsets. */ 2683 1.1 mrg struct store_scatter_offset_restricted_def : public store_scatter_base 2684 1.1 mrg { 2685 1.1 mrg void 2686 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2687 1.1 mrg { 2688 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2689 1.1 mrg b.add_overloaded_functions (group, MODE_offset); 2690 1.1 mrg build_sv_uint_offset (b, "_,as,d,t0", group); 2691 1.1 mrg build_v_base (b, "_,b,t0", group); 2692 1.1 mrg build_vs_offset (b, "_,b,ss64,t0", group); 2693 1.1 mrg } 2694 1.1 mrg }; 2695 1.1 mrg SHAPE (store_scatter_offset_restricted) 2696 1.1 mrg 2697 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, sv<t0:uint>_t). */ 2698 1.1 mrg struct tbl_tuple_def : public overloaded_base<0> 2699 1.1 mrg { 2700 1.1 mrg void 2701 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2702 1.1 mrg { 2703 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2704 1.1 mrg build_all (b, "v0,t0,vu0", group, MODE_none); 2705 1.1 mrg } 2706 1.1 mrg 2707 1.1 mrg tree 2708 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2709 1.1 mrg { 2710 1.1 mrg unsigned int i, nargs; 2711 1.1 mrg type_suffix_index type; 2712 1.1 mrg if (!r.check_gp_argument (2, i, nargs) 2713 1.1 mrg || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES 2714 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned)) 2715 1.1 mrg return error_mark_node; 2716 1.1 mrg 2717 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 2718 1.1 mrg } 2719 1.1 mrg }; 2720 1.1 mrg SHAPE (tbl_tuple) 2721 1.1 mrg 2722 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t). */ 2723 1.1 mrg struct ternary_bfloat_def 2724 1.1 mrg : public ternary_resize2_base<16, TYPE_bfloat, TYPE_bfloat> 2725 1.1 mrg { 2726 1.1 mrg void 2727 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2728 1.1 mrg { 2729 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2730 1.1 mrg build_all (b, "v0,v0,vB,vB", group, MODE_none); 2731 1.1 mrg } 2732 1.1 mrg }; 2733 1.1 mrg SHAPE (ternary_bfloat) 2734 1.1 mrg 2735 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t) 2736 1.1 mrg 2737 1.1 mrg where the final argument is an integer constant expression in the range 2738 1.1 mrg [0, 7]. */ 2739 1.1 mrg typedef ternary_bfloat_lane_base<1> ternary_bfloat_lane_def; 2740 1.1 mrg SHAPE (ternary_bfloat_lane) 2741 1.1 mrg 2742 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t) 2743 1.1 mrg 2744 1.1 mrg where the final argument is an integer constant expression in the range 2745 1.1 mrg [0, 3]. */ 2746 1.1 mrg typedef ternary_bfloat_lane_base<2> ternary_bfloat_lanex2_def; 2747 1.1 mrg SHAPE (ternary_bfloat_lanex2) 2748 1.1 mrg 2749 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t) 2750 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, svbfloat16_t, bfloat16_t). */ 2751 1.1 mrg struct ternary_bfloat_opt_n_def 2752 1.1 mrg : public ternary_resize2_opt_n_base<16, TYPE_bfloat, TYPE_bfloat> 2753 1.1 mrg { 2754 1.1 mrg void 2755 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2756 1.1 mrg { 2757 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2758 1.1 mrg build_all (b, "v0,v0,vB,vB", group, MODE_none); 2759 1.1 mrg build_all (b, "v0,v0,vB,sB", group, MODE_n); 2760 1.1 mrg } 2761 1.1 mrg }; 2762 1.1 mrg SHAPE (ternary_bfloat_opt_n) 2763 1.1 mrg 2764 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t, 2765 1.1 mrg uint64_t) 2766 1.1 mrg 2767 1.1 mrg where the final argument is an integer constant expression in the range 2768 1.1 mrg [0, 16 / sizeof (<t0>_t) - 1]. */ 2769 1.1 mrg struct ternary_intq_uintq_lane_def 2770 1.1 mrg : public ternary_qq_lane_base<TYPE_signed, TYPE_unsigned> 2771 1.1 mrg { 2772 1.1 mrg void 2773 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2774 1.1 mrg { 2775 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2776 1.1 mrg build_all (b, "v0,v0,vqs0,vqu0,su64", group, MODE_none); 2777 1.1 mrg } 2778 1.1 mrg }; 2779 1.1 mrg SHAPE (ternary_intq_uintq_lane) 2780 1.1 mrg 2781 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t) 2782 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:int:quarter>_t, 2783 1.1 mrg <t0:uint:quarter>_t). */ 2784 1.1 mrg struct ternary_intq_uintq_opt_n_def 2785 1.1 mrg : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE, 2786 1.1 mrg TYPE_signed, TYPE_unsigned> 2787 1.1 mrg { 2788 1.1 mrg void 2789 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2790 1.1 mrg { 2791 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2792 1.1 mrg build_all (b, "v0,v0,vqs0,vqu0", group, MODE_none); 2793 1.1 mrg build_all (b, "v0,v0,vqs0,squ0", group, MODE_n); 2794 1.1 mrg } 2795 1.1 mrg }; 2796 1.1 mrg SHAPE (ternary_intq_uintq_opt_n) 2797 1.1 mrg 2798 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t) 2799 1.1 mrg 2800 1.1 mrg where the final argument is an integer constant expression in the 2801 1.1 mrg range [0, 16 / sizeof (<t0>_t) - 1]. */ 2802 1.1 mrg struct ternary_lane_def : public overloaded_base<0> 2803 1.1 mrg { 2804 1.1 mrg void 2805 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2806 1.1 mrg { 2807 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2808 1.1 mrg build_all (b, "v0,v0,v0,v0,su64", group, MODE_none); 2809 1.1 mrg } 2810 1.1 mrg 2811 1.1 mrg tree 2812 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2813 1.1 mrg { 2814 1.1 mrg return r.resolve_uniform (3, 1); 2815 1.1 mrg } 2816 1.1 mrg 2817 1.1 mrg bool 2818 1.1 mrg check (function_checker &c) const OVERRIDE 2819 1.1 mrg { 2820 1.1 mrg return c.require_immediate_lane_index (3); 2821 1.1 mrg } 2822 1.1 mrg }; 2823 1.1 mrg SHAPE (ternary_lane) 2824 1.1 mrg 2825 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t) 2826 1.1 mrg 2827 1.1 mrg where the penultimate argument is an integer constant expression in 2828 1.1 mrg the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument 2829 1.1 mrg is an integer constant expression in {0, 90, 180, 270}. */ 2830 1.1 mrg struct ternary_lane_rotate_def : public overloaded_base<0> 2831 1.1 mrg { 2832 1.1 mrg void 2833 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2834 1.1 mrg { 2835 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2836 1.1 mrg build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none); 2837 1.1 mrg } 2838 1.1 mrg 2839 1.1 mrg tree 2840 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2841 1.1 mrg { 2842 1.1 mrg return r.resolve_uniform (3, 2); 2843 1.1 mrg } 2844 1.1 mrg 2845 1.1 mrg bool 2846 1.1 mrg check (function_checker &c) const OVERRIDE 2847 1.1 mrg { 2848 1.1 mrg return (c.require_immediate_lane_index (3, 2) 2849 1.1 mrg && c.require_immediate_one_of (4, 0, 90, 180, 270)); 2850 1.1 mrg } 2851 1.1 mrg }; 2852 1.1 mrg SHAPE (ternary_lane_rotate) 2853 1.1 mrg 2854 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t, uint64_t) 2855 1.1 mrg 2856 1.1 mrg where the final argument is an integer constant expression in the range 2857 1.1 mrg [0, 32 / sizeof (<t0>_t) - 1]. */ 2858 1.1 mrg struct ternary_long_lane_def 2859 1.1 mrg : public ternary_resize2_lane_base<function_resolver::HALF_SIZE> 2860 1.1 mrg { 2861 1.1 mrg void 2862 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2863 1.1 mrg { 2864 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2865 1.1 mrg build_all (b, "v0,v0,vh0,vh0,su64", group, MODE_none); 2866 1.1 mrg } 2867 1.1 mrg 2868 1.1 mrg bool 2869 1.1 mrg check (function_checker &c) const OVERRIDE 2870 1.1 mrg { 2871 1.1 mrg return c.require_immediate_lane_index (3); 2872 1.1 mrg } 2873 1.1 mrg }; 2874 1.1 mrg SHAPE (ternary_long_lane) 2875 1.1 mrg 2876 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t) 2877 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:half>_t, <t0:half>_t) 2878 1.1 mrg 2879 1.1 mrg i.e. a version of the standard ternary shape ternary_opt_n in which 2880 1.1 mrg the element type of the last two arguments is the half-sized 2881 1.1 mrg equivalent of <t0>. */ 2882 1.1 mrg struct ternary_long_opt_n_def 2883 1.1 mrg : public ternary_resize2_opt_n_base<function_resolver::HALF_SIZE> 2884 1.1 mrg { 2885 1.1 mrg void 2886 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2887 1.1 mrg { 2888 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2889 1.1 mrg build_all (b, "v0,v0,vh0,vh0", group, MODE_none); 2890 1.1 mrg build_all (b, "v0,v0,vh0,sh0", group, MODE_n); 2891 1.1 mrg } 2892 1.1 mrg }; 2893 1.1 mrg SHAPE (ternary_long_opt_n) 2894 1.1 mrg 2895 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t) 2896 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t) 2897 1.1 mrg 2898 1.1 mrg i.e. the standard shape for ternary operations that operate on 2899 1.1 mrg uniform types. */ 2900 1.1 mrg struct ternary_opt_n_def : public overloaded_base<0> 2901 1.1 mrg { 2902 1.1 mrg void 2903 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2904 1.1 mrg { 2905 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2906 1.1 mrg build_all (b, "v0,v0,v0,v0", group, MODE_none); 2907 1.1 mrg build_all (b, "v0,v0,v0,s0", group, MODE_n); 2908 1.1 mrg } 2909 1.1 mrg 2910 1.1 mrg tree 2911 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2912 1.1 mrg { 2913 1.1 mrg return r.resolve_uniform_opt_n (3); 2914 1.1 mrg } 2915 1.1 mrg }; 2916 1.1 mrg SHAPE (ternary_opt_n) 2917 1.1 mrg 2918 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t, uint64_t) 2919 1.1 mrg 2920 1.1 mrg where the final argument is an integer constant expression in the range 2921 1.1 mrg [0, 16 / sizeof (<t0>_t) - 1]. */ 2922 1.1 mrg struct ternary_qq_lane_def : public ternary_qq_lane_base<> 2923 1.1 mrg { 2924 1.1 mrg void 2925 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2926 1.1 mrg { 2927 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2928 1.1 mrg build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none); 2929 1.1 mrg } 2930 1.1 mrg }; 2931 1.1 mrg SHAPE (ternary_qq_lane) 2932 1.1 mrg 2933 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t, 2934 1.1 mrg uint64_t) 2935 1.1 mrg 2936 1.1 mrg where the final argument is an integer constant expression in 2937 1.1 mrg {0, 90, 180, 270}. */ 2938 1.1 mrg struct ternary_qq_lane_rotate_def : public overloaded_base<0> 2939 1.1 mrg { 2940 1.1 mrg void 2941 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2942 1.1 mrg { 2943 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2944 1.1 mrg build_all (b, "v0,v0,vq0,vq0,su64,su64", group, MODE_none); 2945 1.1 mrg } 2946 1.1 mrg 2947 1.1 mrg tree 2948 1.1 mrg resolve (function_resolver &r) const OVERRIDE 2949 1.1 mrg { 2950 1.1 mrg unsigned int i, nargs; 2951 1.1 mrg type_suffix_index type; 2952 1.1 mrg if (!r.check_gp_argument (5, i, nargs) 2953 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 2954 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS, 2955 1.1 mrg r.QUARTER_SIZE) 2956 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS, 2957 1.1 mrg r.QUARTER_SIZE) 2958 1.1 mrg || !r.require_integer_immediate (i + 3) 2959 1.1 mrg || !r.require_integer_immediate (i + 4)) 2960 1.1 mrg return error_mark_node; 2961 1.1 mrg 2962 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 2963 1.1 mrg } 2964 1.1 mrg 2965 1.1 mrg bool 2966 1.1 mrg check (function_checker &c) const OVERRIDE 2967 1.1 mrg { 2968 1.1 mrg return (c.require_immediate_lane_index (3, 4) 2969 1.1 mrg && c.require_immediate_one_of (4, 0, 90, 180, 270)); 2970 1.1 mrg } 2971 1.1 mrg }; 2972 1.1 mrg SHAPE (ternary_qq_lane_rotate) 2973 1.1 mrg 2974 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t) 2975 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:quarter>_t, <t0:quarter>_t) 2976 1.1 mrg 2977 1.1 mrg i.e. a version of the standard ternary shape ternary_opt_n in which 2978 1.1 mrg the element type of the last two arguments is the quarter-sized 2979 1.1 mrg equivalent of <t0>. */ 2980 1.1 mrg struct ternary_qq_opt_n_def 2981 1.1 mrg : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE> 2982 1.1 mrg { 2983 1.1 mrg void 2984 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 2985 1.1 mrg { 2986 1.1 mrg b.add_overloaded_functions (group, MODE_none); 2987 1.1 mrg build_all (b, "v0,v0,vq0,vq0", group, MODE_none); 2988 1.1 mrg build_all (b, "v0,v0,vq0,sq0", group, MODE_n); 2989 1.1 mrg } 2990 1.1 mrg }; 2991 1.1 mrg SHAPE (ternary_qq_opt_n) 2992 1.1 mrg 2993 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t, 2994 1.1 mrg uint64_t) 2995 1.1 mrg 2996 1.1 mrg where the final argument is an integer constant expression in 2997 1.1 mrg {0, 90, 180, 270}. */ 2998 1.1 mrg struct ternary_qq_rotate_def : public overloaded_base<0> 2999 1.1 mrg { 3000 1.1 mrg void 3001 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3002 1.1 mrg { 3003 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3004 1.1 mrg build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none); 3005 1.1 mrg } 3006 1.1 mrg 3007 1.1 mrg tree 3008 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3009 1.1 mrg { 3010 1.1 mrg unsigned int i, nargs; 3011 1.1 mrg type_suffix_index type; 3012 1.1 mrg if (!r.check_gp_argument (4, i, nargs) 3013 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 3014 1.1 mrg || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS, 3015 1.1 mrg r.QUARTER_SIZE) 3016 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS, 3017 1.1 mrg r.QUARTER_SIZE) 3018 1.1 mrg || !r.require_integer_immediate (i + 3)) 3019 1.1 mrg return error_mark_node; 3020 1.1 mrg 3021 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 3022 1.1 mrg } 3023 1.1 mrg 3024 1.1 mrg bool 3025 1.1 mrg check (function_checker &c) const OVERRIDE 3026 1.1 mrg { 3027 1.1 mrg return c.require_immediate_one_of (3, 0, 90, 180, 270); 3028 1.1 mrg } 3029 1.1 mrg }; 3030 1.1 mrg SHAPE (ternary_qq_rotate) 3031 1.1 mrg 3032 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t) 3033 1.1 mrg 3034 1.1 mrg where the final argument is an integer constant expression in 3035 1.1 mrg {0, 90, 180, 270}. */ 3036 1.1 mrg struct ternary_rotate_def : public overloaded_base<0> 3037 1.1 mrg { 3038 1.1 mrg void 3039 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3040 1.1 mrg { 3041 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3042 1.1 mrg build_all (b, "v0,v0,v0,v0,su64", group, MODE_none); 3043 1.1 mrg } 3044 1.1 mrg 3045 1.1 mrg tree 3046 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3047 1.1 mrg { 3048 1.1 mrg return r.resolve_uniform (3, 1); 3049 1.1 mrg } 3050 1.1 mrg 3051 1.1 mrg bool 3052 1.1 mrg check (function_checker &c) const OVERRIDE 3053 1.1 mrg { 3054 1.1 mrg return c.require_immediate_one_of (3, 0, 90, 180, 270); 3055 1.1 mrg } 3056 1.1 mrg }; 3057 1.1 mrg SHAPE (ternary_rotate) 3058 1.1 mrg 3059 1.1 mrg /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t) 3060 1.1 mrg 3061 1.1 mrg where the final argument must be an integer constant expression in the 3062 1.1 mrg range [0, sizeof (<t0>_t) * 8 - 1]. */ 3063 1.1 mrg struct ternary_shift_left_imm_def : public ternary_shift_imm_base 3064 1.1 mrg { 3065 1.1 mrg bool 3066 1.1 mrg check (function_checker &c) const OVERRIDE 3067 1.1 mrg { 3068 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits; 3069 1.1 mrg return c.require_immediate_range (2, 0, bits - 1); 3070 1.1 mrg } 3071 1.1 mrg }; 3072 1.1 mrg SHAPE (ternary_shift_left_imm) 3073 1.1 mrg 3074 1.1 mrg /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t) 3075 1.1 mrg 3076 1.1 mrg where the final argument must be an integer constant expression in the 3077 1.1 mrg range [1, sizeof (<t0>_t) * 8]. */ 3078 1.1 mrg struct ternary_shift_right_imm_def : public ternary_shift_imm_base 3079 1.1 mrg { 3080 1.1 mrg bool 3081 1.1 mrg check (function_checker &c) const OVERRIDE 3082 1.1 mrg { 3083 1.1 mrg unsigned int bits = c.type_suffix (0).element_bits; 3084 1.1 mrg return c.require_immediate_range (2, 1, bits); 3085 1.1 mrg } 3086 1.1 mrg }; 3087 1.1 mrg SHAPE (ternary_shift_right_imm) 3088 1.1 mrg 3089 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0:uint>_t). */ 3090 1.1 mrg struct ternary_uint_def : public overloaded_base<0> 3091 1.1 mrg { 3092 1.1 mrg void 3093 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3094 1.1 mrg { 3095 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3096 1.1 mrg build_all (b, "v0,v0,v0,vu0", group, MODE_none); 3097 1.1 mrg } 3098 1.1 mrg 3099 1.1 mrg tree 3100 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3101 1.1 mrg { 3102 1.1 mrg unsigned int i, nargs; 3103 1.1 mrg type_suffix_index type; 3104 1.1 mrg if (!r.check_gp_argument (3, i, nargs) 3105 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 3106 1.1 mrg || !r.require_matching_vector_type (i + 1, type) 3107 1.1 mrg || !r.require_derived_vector_type (i + 2, i, type, TYPE_unsigned)) 3108 1.1 mrg return error_mark_node; 3109 1.1 mrg 3110 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 3111 1.1 mrg } 3112 1.1 mrg }; 3113 1.1 mrg SHAPE (ternary_uint) 3114 1.1 mrg 3115 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, svu<t0:uint:quarter>_t, 3116 1.1 mrg sv<t0:int:quarter>_t). */ 3117 1.1 mrg struct ternary_uintq_intq_def 3118 1.1 mrg : public ternary_resize2_base<function_resolver::QUARTER_SIZE, 3119 1.1 mrg TYPE_unsigned, TYPE_signed> 3120 1.1 mrg { 3121 1.1 mrg void 3122 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3123 1.1 mrg { 3124 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3125 1.1 mrg build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none); 3126 1.1 mrg } 3127 1.1 mrg }; 3128 1.1 mrg SHAPE (ternary_uintq_intq) 3129 1.1 mrg 3130 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t, 3131 1.1 mrg uint64_t) 3132 1.1 mrg 3133 1.1 mrg where the final argument is an integer constant expression in the range 3134 1.1 mrg [0, 16 / sizeof (<t0>_t) - 1]. */ 3135 1.1 mrg struct ternary_uintq_intq_lane_def 3136 1.1 mrg : public ternary_qq_lane_base<TYPE_unsigned, TYPE_signed> 3137 1.1 mrg { 3138 1.1 mrg void 3139 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3140 1.1 mrg { 3141 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3142 1.1 mrg build_all (b, "v0,v0,vqu0,vqs0,su64", group, MODE_none); 3143 1.1 mrg } 3144 1.1 mrg }; 3145 1.1 mrg SHAPE (ternary_uintq_intq_lane) 3146 1.1 mrg 3147 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t) 3148 1.1 mrg sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:uint:quarter>_t, 3149 1.1 mrg <t0:int:quarter>_t). */ 3150 1.1 mrg struct ternary_uintq_intq_opt_n_def 3151 1.1 mrg : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE, 3152 1.1 mrg TYPE_unsigned, TYPE_signed> 3153 1.1 mrg { 3154 1.1 mrg void 3155 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3156 1.1 mrg { 3157 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3158 1.1 mrg build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none); 3159 1.1 mrg build_all (b, "v0,v0,vqu0,sqs0", group, MODE_n); 3160 1.1 mrg } 3161 1.1 mrg }; 3162 1.1 mrg SHAPE (ternary_uintq_intq_opt_n) 3163 1.1 mrg 3164 1.1 mrg /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t) 3165 1.1 mrg 3166 1.1 mrg where the final argument is an integer constant expression in the 3167 1.1 mrg range [0, 7]. */ 3168 1.1 mrg struct tmad_def : public overloaded_base<0> 3169 1.1 mrg { 3170 1.1 mrg void 3171 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3172 1.1 mrg { 3173 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3174 1.1 mrg build_all (b, "v0,v0,v0,su64", group, MODE_none); 3175 1.1 mrg } 3176 1.1 mrg 3177 1.1 mrg tree 3178 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3179 1.1 mrg { 3180 1.1 mrg return r.resolve_uniform (2, 1); 3181 1.1 mrg } 3182 1.1 mrg 3183 1.1 mrg bool 3184 1.1 mrg check (function_checker &c) const OVERRIDE 3185 1.1 mrg { 3186 1.1 mrg return c.require_immediate_range (2, 0, 7); 3187 1.1 mrg } 3188 1.1 mrg }; 3189 1.1 mrg SHAPE (tmad) 3190 1.1 mrg 3191 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0>_t) 3192 1.1 mrg 3193 1.1 mrg i.e. the standard shape for unary operations that operate on 3194 1.1 mrg uniform types. */ 3195 1.1 mrg struct unary_def : public overloaded_base<0> 3196 1.1 mrg { 3197 1.1 mrg void 3198 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3199 1.1 mrg { 3200 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3201 1.1 mrg build_all (b, "v0,v0", group, MODE_none); 3202 1.1 mrg } 3203 1.1 mrg 3204 1.1 mrg tree 3205 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3206 1.1 mrg { 3207 1.1 mrg return r.resolve_unary (); 3208 1.1 mrg } 3209 1.1 mrg }; 3210 1.1 mrg SHAPE (unary) 3211 1.1 mrg 3212 1.1 mrg /* sv<t0>_t svfoo_t0[_t1](sv<t1>_t) 3213 1.1 mrg 3214 1.1 mrg where the target type <t0> must be specified explicitly but the source 3215 1.1 mrg type <t1> can be inferred. */ 3216 1.1 mrg struct unary_convert_def : public overloaded_base<1> 3217 1.1 mrg { 3218 1.1 mrg void 3219 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3220 1.1 mrg { 3221 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3222 1.1 mrg build_all (b, "v0,v1", group, MODE_none); 3223 1.1 mrg } 3224 1.1 mrg 3225 1.1 mrg tree 3226 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3227 1.1 mrg { 3228 1.1 mrg return r.resolve_unary (r.type_suffix (0).tclass, 3229 1.1 mrg r.type_suffix (0).element_bits); 3230 1.1 mrg } 3231 1.1 mrg }; 3232 1.1 mrg SHAPE (unary_convert) 3233 1.1 mrg 3234 1.1 mrg /* sv<t0>_t svfoo_t0[_t1](sv<t0>_t, sv<t1>_t) 3235 1.1 mrg 3236 1.1 mrg This is a version of unary_convert in which the even-indexed 3237 1.1 mrg elements are passed in as a first parameter, before any governing 3238 1.1 mrg predicate. */ 3239 1.1 mrg struct unary_convert_narrowt_def : public overloaded_base<1> 3240 1.1 mrg { 3241 1.1 mrg void 3242 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3243 1.1 mrg { 3244 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3245 1.1 mrg build_all (b, "v0,v1", group, MODE_none); 3246 1.1 mrg } 3247 1.1 mrg 3248 1.1 mrg tree 3249 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3250 1.1 mrg { 3251 1.1 mrg return r.resolve_unary (r.type_suffix (0).tclass, 3252 1.1 mrg r.type_suffix (0).element_bits, true); 3253 1.1 mrg } 3254 1.1 mrg }; 3255 1.1 mrg SHAPE (unary_convert_narrowt) 3256 1.1 mrg 3257 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0:half>_t). */ 3258 1.1 mrg struct unary_long_def : public overloaded_base<0> 3259 1.1 mrg { 3260 1.1 mrg void 3261 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3262 1.1 mrg { 3263 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3264 1.1 mrg build_all (b, "v0,vh0", group, MODE_none); 3265 1.1 mrg } 3266 1.1 mrg 3267 1.1 mrg tree 3268 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3269 1.1 mrg { 3270 1.1 mrg unsigned int i, nargs; 3271 1.1 mrg type_suffix_index type, result_type; 3272 1.1 mrg if (!r.check_gp_argument (1, i, nargs) 3273 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES 3274 1.1 mrg || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES) 3275 1.1 mrg return error_mark_node; 3276 1.1 mrg 3277 1.1 mrg if (tree res = r.lookup_form (r.mode_suffix_id, result_type)) 3278 1.1 mrg return res; 3279 1.1 mrg 3280 1.1 mrg return r.report_no_such_form (type); 3281 1.1 mrg } 3282 1.1 mrg }; 3283 1.1 mrg SHAPE (unary_long) 3284 1.1 mrg 3285 1.1 mrg /* sv<t0>_t svfoo[_n]_t0(<t0>_t). */ 3286 1.1 mrg struct unary_n_def : public overloaded_base<1> 3287 1.1 mrg { 3288 1.1 mrg void 3289 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3290 1.1 mrg { 3291 1.1 mrg /* The "_n" suffix is optional; the full name has it, but the short 3292 1.1 mrg name doesn't. */ 3293 1.1 mrg build_all (b, "v0,s0", group, MODE_n, true); 3294 1.1 mrg } 3295 1.1 mrg 3296 1.1 mrg tree 3297 1.1 mrg resolve (function_resolver &) const OVERRIDE 3298 1.1 mrg { 3299 1.1 mrg /* The short forms just make "_n" implicit, so no resolution is needed. */ 3300 1.1 mrg gcc_unreachable (); 3301 1.1 mrg } 3302 1.1 mrg }; 3303 1.1 mrg SHAPE (unary_n) 3304 1.1 mrg 3305 1.1 mrg /* sv<t0:half>_t svfoo[_t0](sv<t0>_t). */ 3306 1.1 mrg typedef unary_narrowb_base<> unary_narrowb_def; 3307 1.1 mrg SHAPE (unary_narrowb) 3308 1.1 mrg 3309 1.1 mrg /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t). */ 3310 1.1 mrg typedef unary_narrowt_base<> unary_narrowt_def; 3311 1.1 mrg SHAPE (unary_narrowt) 3312 1.1 mrg 3313 1.1 mrg /* sv<t0:uint:half>_t svfoo[_t0](sv<t0>_t). */ 3314 1.1 mrg typedef unary_narrowb_base<TYPE_unsigned> unary_narrowb_to_uint_def; 3315 1.1 mrg SHAPE (unary_narrowb_to_uint) 3316 1.1 mrg 3317 1.1 mrg /* sv<t0:uint:half>_t svfoo[_t0](sv<t0:uint:half>_t, sv<t0>_t). */ 3318 1.1 mrg typedef unary_narrowt_base<TYPE_unsigned> unary_narrowt_to_uint_def; 3319 1.1 mrg SHAPE (unary_narrowt_to_uint) 3320 1.1 mrg 3321 1.1 mrg /* svbool_t svfoo(svbool_t). */ 3322 1.1 mrg struct unary_pred_def : public nonoverloaded_base 3323 1.1 mrg { 3324 1.1 mrg void 3325 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3326 1.1 mrg { 3327 1.1 mrg build_all (b, "v0,v0", group, MODE_none); 3328 1.1 mrg } 3329 1.1 mrg }; 3330 1.1 mrg SHAPE (unary_pred) 3331 1.1 mrg 3332 1.1 mrg /* sv<t0:int>_t svfoo[_t0](sv<t0>_t) 3333 1.1 mrg 3334 1.1 mrg i.e. a version of "unary" in which the returned vector contains 3335 1.1 mrg signed integers. */ 3336 1.1 mrg struct unary_to_int_def : public overloaded_base<0> 3337 1.1 mrg { 3338 1.1 mrg void 3339 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3340 1.1 mrg { 3341 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3342 1.1 mrg build_all (b, "vs0,v0", group, MODE_none); 3343 1.1 mrg } 3344 1.1 mrg 3345 1.1 mrg tree 3346 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3347 1.1 mrg { 3348 1.1 mrg return r.resolve_unary (TYPE_signed); 3349 1.1 mrg } 3350 1.1 mrg }; 3351 1.1 mrg SHAPE (unary_to_int) 3352 1.1 mrg 3353 1.1 mrg /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t) 3354 1.1 mrg 3355 1.1 mrg i.e. a version of "unary" in which the returned vector contains 3356 1.1 mrg unsigned integers. */ 3357 1.1 mrg struct unary_to_uint_def : public overloaded_base<0> 3358 1.1 mrg { 3359 1.1 mrg void 3360 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3361 1.1 mrg { 3362 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3363 1.1 mrg build_all (b, "vu0,v0", group, MODE_none); 3364 1.1 mrg } 3365 1.1 mrg 3366 1.1 mrg tree 3367 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3368 1.1 mrg { 3369 1.1 mrg return r.resolve_unary (TYPE_unsigned); 3370 1.1 mrg } 3371 1.1 mrg }; 3372 1.1 mrg SHAPE (unary_to_uint) 3373 1.1 mrg 3374 1.1 mrg /* sv<t0>_t svfoo[_t0](sv<t0:uint>_t) 3375 1.1 mrg 3376 1.1 mrg where <t0> always belongs a certain type class, and where <t0:uint> 3377 1.1 mrg therefore uniquely determines <t0>. */ 3378 1.1 mrg struct unary_uint_def : public overloaded_base<0> 3379 1.1 mrg { 3380 1.1 mrg void 3381 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3382 1.1 mrg { 3383 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3384 1.1 mrg build_all (b, "v0,vu0", group, MODE_none); 3385 1.1 mrg } 3386 1.1 mrg 3387 1.1 mrg tree 3388 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3389 1.1 mrg { 3390 1.1 mrg unsigned int i, nargs; 3391 1.1 mrg type_suffix_index type; 3392 1.1 mrg if (!r.check_gp_argument (1, i, nargs) 3393 1.1 mrg || (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES) 3394 1.1 mrg return error_mark_node; 3395 1.1 mrg 3396 1.1 mrg /* Search for a valid suffix with the same number of bits as TYPE. */ 3397 1.1 mrg unsigned int element_bits = type_suffixes[type].element_bits; 3398 1.1 mrg if (type_suffixes[type].unsigned_p) 3399 1.1 mrg for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j) 3400 1.1 mrg if (type_suffixes[j].element_bits == element_bits) 3401 1.1 mrg if (tree res = r.lookup_form (r.mode_suffix_id, 3402 1.1 mrg type_suffix_index (j))) 3403 1.1 mrg return res; 3404 1.1 mrg 3405 1.1 mrg return r.report_no_such_form (type); 3406 1.1 mrg } 3407 1.1 mrg }; 3408 1.1 mrg SHAPE (unary_uint) 3409 1.1 mrg 3410 1.1 mrg /* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t) 3411 1.1 mrg 3412 1.1 mrg i.e. a version of "unary" in which the source elements are half the 3413 1.1 mrg size of the destination elements, but have the same type class. */ 3414 1.1 mrg struct unary_widen_def : public overloaded_base<0> 3415 1.1 mrg { 3416 1.1 mrg void 3417 1.1 mrg build (function_builder &b, const function_group_info &group) const OVERRIDE 3418 1.1 mrg { 3419 1.1 mrg b.add_overloaded_functions (group, MODE_none); 3420 1.1 mrg build_all (b, "v0,vh0", group, MODE_none); 3421 1.1 mrg } 3422 1.1 mrg 3423 1.1 mrg tree 3424 1.1 mrg resolve (function_resolver &r) const OVERRIDE 3425 1.1 mrg { 3426 1.1 mrg unsigned int i, nargs; 3427 1.1 mrg type_suffix_index type; 3428 1.1 mrg if (!r.check_gp_argument (1, i, nargs) 3429 1.1 mrg || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES) 3430 1.1 mrg return error_mark_node; 3431 1.1 mrg 3432 1.1 mrg /* There is only a single form for predicates. */ 3433 1.1 mrg if (type == TYPE_SUFFIX_b) 3434 1.1 mrg return r.resolve_to (r.mode_suffix_id, type); 3435 1.1 mrg 3436 1.1 mrg if (type_suffixes[type].integer_p 3437 1.1 mrg && type_suffixes[type].element_bits < 64) 3438 1.1 mrg { 3439 1.1 mrg type_suffix_index wide_suffix 3440 1.1 mrg = find_type_suffix (type_suffixes[type].tclass, 3441 1.1 mrg type_suffixes[type].element_bits * 2); 3442 1.1 mrg if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix)) 3443 1.1 mrg return res; 3444 1.1 mrg } 3445 1.1 mrg 3446 1.1 mrg return r.report_no_such_form (type); 3447 1.1 mrg } 3448 1.1 mrg }; 3449 1.1 mrg SHAPE (unary_widen) 3450 1.1 mrg 3451 1.1 mrg } 3452