1 /* Builtins' description for AArch64 SIMD architecture. 2 Copyright (C) 2011-2013 Free Software Foundation, Inc. 3 Contributed by ARM Ltd. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "tm.h" 25 #include "rtl.h" 26 #include "tree.h" 27 #include "expr.h" 28 #include "tm_p.h" 29 #include "recog.h" 30 #include "langhooks.h" 31 #include "diagnostic-core.h" 32 #include "optabs.h" 33 34 enum aarch64_simd_builtin_type_mode 35 { 36 T_V8QI, 37 T_V4HI, 38 T_V2SI, 39 T_V2SF, 40 T_DI, 41 T_DF, 42 T_V16QI, 43 T_V8HI, 44 T_V4SI, 45 T_V4SF, 46 T_V2DI, 47 T_V2DF, 48 T_TI, 49 T_EI, 50 T_OI, 51 T_XI, 52 T_SI, 53 T_HI, 54 T_QI, 55 T_MAX 56 }; 57 58 #define v8qi_UP T_V8QI 59 #define v4hi_UP T_V4HI 60 #define v2si_UP T_V2SI 61 #define v2sf_UP T_V2SF 62 #define di_UP T_DI 63 #define df_UP T_DF 64 #define v16qi_UP T_V16QI 65 #define v8hi_UP T_V8HI 66 #define v4si_UP T_V4SI 67 #define v4sf_UP T_V4SF 68 #define v2di_UP T_V2DI 69 #define v2df_UP T_V2DF 70 #define ti_UP T_TI 71 #define ei_UP T_EI 72 #define oi_UP T_OI 73 #define xi_UP T_XI 74 #define si_UP T_SI 75 #define hi_UP T_HI 76 #define qi_UP T_QI 77 78 #define UP(X) X##_UP 79 80 typedef enum 81 { 82 AARCH64_SIMD_BINOP, 83 AARCH64_SIMD_TERNOP, 84 AARCH64_SIMD_QUADOP, 85 AARCH64_SIMD_UNOP, 86 AARCH64_SIMD_GETLANE, 87 AARCH64_SIMD_SETLANE, 88 AARCH64_SIMD_CREATE, 89 AARCH64_SIMD_DUP, 90 AARCH64_SIMD_DUPLANE, 91 AARCH64_SIMD_COMBINE, 92 AARCH64_SIMD_SPLIT, 93 AARCH64_SIMD_LANEMUL, 94 AARCH64_SIMD_LANEMULL, 95 AARCH64_SIMD_LANEMULH, 96 AARCH64_SIMD_LANEMAC, 97 AARCH64_SIMD_SCALARMUL, 98 AARCH64_SIMD_SCALARMULL, 99 AARCH64_SIMD_SCALARMULH, 100 AARCH64_SIMD_SCALARMAC, 101 AARCH64_SIMD_CONVERT, 102 AARCH64_SIMD_FIXCONV, 103 AARCH64_SIMD_SELECT, 104 AARCH64_SIMD_RESULTPAIR, 105 AARCH64_SIMD_REINTERP, 106 AARCH64_SIMD_VTBL, 107 AARCH64_SIMD_VTBX, 108 AARCH64_SIMD_LOAD1, 109 AARCH64_SIMD_LOAD1LANE, 110 AARCH64_SIMD_STORE1, 111 AARCH64_SIMD_STORE1LANE, 112 AARCH64_SIMD_LOADSTRUCT, 113 AARCH64_SIMD_LOADSTRUCTLANE, 114 AARCH64_SIMD_STORESTRUCT, 115 AARCH64_SIMD_STORESTRUCTLANE, 116 AARCH64_SIMD_LOGICBINOP, 117 AARCH64_SIMD_SHIFTINSERT, 118 AARCH64_SIMD_SHIFTIMM, 119 AARCH64_SIMD_SHIFTACC 120 } aarch64_simd_itype; 121 122 typedef struct 123 { 124 const char *name; 125 const aarch64_simd_itype itype; 126 enum aarch64_simd_builtin_type_mode mode; 127 const enum insn_code code; 128 unsigned int fcode; 129 } aarch64_simd_builtin_datum; 130 131 #define CF(N, X) CODE_FOR_aarch64_##N##X 132 133 #define VAR1(T, N, A) \ 134 {#N, AARCH64_SIMD_##T, UP (A), CF (N, A), 0}, 135 #define VAR2(T, N, A, B) \ 136 VAR1 (T, N, A) \ 137 VAR1 (T, N, B) 138 #define VAR3(T, N, A, B, C) \ 139 VAR2 (T, N, A, B) \ 140 VAR1 (T, N, C) 141 #define VAR4(T, N, A, B, C, D) \ 142 VAR3 (T, N, A, B, C) \ 143 VAR1 (T, N, D) 144 #define VAR5(T, N, A, B, C, D, E) \ 145 VAR4 (T, N, A, B, C, D) \ 146 VAR1 (T, N, E) 147 #define VAR6(T, N, A, B, C, D, E, F) \ 148 VAR5 (T, N, A, B, C, D, E) \ 149 VAR1 (T, N, F) 150 #define VAR7(T, N, A, B, C, D, E, F, G) \ 151 VAR6 (T, N, A, B, C, D, E, F) \ 152 VAR1 (T, N, G) 153 #define VAR8(T, N, A, B, C, D, E, F, G, H) \ 154 VAR7 (T, N, A, B, C, D, E, F, G) \ 155 VAR1 (T, N, H) 156 #define VAR9(T, N, A, B, C, D, E, F, G, H, I) \ 157 VAR8 (T, N, A, B, C, D, E, F, G, H) \ 158 VAR1 (T, N, I) 159 #define VAR10(T, N, A, B, C, D, E, F, G, H, I, J) \ 160 VAR9 (T, N, A, B, C, D, E, F, G, H, I) \ 161 VAR1 (T, N, J) 162 #define VAR11(T, N, A, B, C, D, E, F, G, H, I, J, K) \ 163 VAR10 (T, N, A, B, C, D, E, F, G, H, I, J) \ 164 VAR1 (T, N, K) 165 #define VAR12(T, N, A, B, C, D, E, F, G, H, I, J, K, L) \ 166 VAR11 (T, N, A, B, C, D, E, F, G, H, I, J, K) \ 167 VAR1 (T, N, L) 168 169 /* BUILTIN_<ITERATOR> macros should expand to cover the same range of 170 modes as is given for each define_mode_iterator in 171 config/aarch64/iterators.md. */ 172 173 #define BUILTIN_DX(T, N) \ 174 VAR2 (T, N, di, df) 175 #define BUILTIN_SDQ_I(T, N) \ 176 VAR4 (T, N, qi, hi, si, di) 177 #define BUILTIN_SD_HSI(T, N) \ 178 VAR2 (T, N, hi, si) 179 #define BUILTIN_V2F(T, N) \ 180 VAR2 (T, N, v2sf, v2df) 181 #define BUILTIN_VALL(T, N) \ 182 VAR10 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, v2sf, v4sf, v2df) 183 #define BUILTIN_VB(T, N) \ 184 VAR2 (T, N, v8qi, v16qi) 185 #define BUILTIN_VD(T, N) \ 186 VAR4 (T, N, v8qi, v4hi, v2si, v2sf) 187 #define BUILTIN_VDC(T, N) \ 188 VAR6 (T, N, v8qi, v4hi, v2si, v2sf, di, df) 189 #define BUILTIN_VDIC(T, N) \ 190 VAR3 (T, N, v8qi, v4hi, v2si) 191 #define BUILTIN_VDN(T, N) \ 192 VAR3 (T, N, v4hi, v2si, di) 193 #define BUILTIN_VDQ(T, N) \ 194 VAR7 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di) 195 #define BUILTIN_VDQF(T, N) \ 196 VAR3 (T, N, v2sf, v4sf, v2df) 197 #define BUILTIN_VDQHS(T, N) \ 198 VAR4 (T, N, v4hi, v8hi, v2si, v4si) 199 #define BUILTIN_VDQIF(T, N) \ 200 VAR9 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2sf, v4sf, v2df) 201 #define BUILTIN_VDQM(T, N) \ 202 VAR6 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si) 203 #define BUILTIN_VDQV(T, N) \ 204 VAR5 (T, N, v8qi, v16qi, v4hi, v8hi, v4si) 205 #define BUILTIN_VDQ_BHSI(T, N) \ 206 VAR6 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si) 207 #define BUILTIN_VDQ_I(T, N) \ 208 VAR7 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di) 209 #define BUILTIN_VDW(T, N) \ 210 VAR3 (T, N, v8qi, v4hi, v2si) 211 #define BUILTIN_VD_BHSI(T, N) \ 212 VAR3 (T, N, v8qi, v4hi, v2si) 213 #define BUILTIN_VD_HSI(T, N) \ 214 VAR2 (T, N, v4hi, v2si) 215 #define BUILTIN_VD_RE(T, N) \ 216 VAR6 (T, N, v8qi, v4hi, v2si, v2sf, di, df) 217 #define BUILTIN_VQ(T, N) \ 218 VAR6 (T, N, v16qi, v8hi, v4si, v2di, v4sf, v2df) 219 #define BUILTIN_VQN(T, N) \ 220 VAR3 (T, N, v8hi, v4si, v2di) 221 #define BUILTIN_VQW(T, N) \ 222 VAR3 (T, N, v16qi, v8hi, v4si) 223 #define BUILTIN_VQ_HSI(T, N) \ 224 VAR2 (T, N, v8hi, v4si) 225 #define BUILTIN_VQ_S(T, N) \ 226 VAR6 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si) 227 #define BUILTIN_VSDQ_HSI(T, N) \ 228 VAR6 (T, N, v4hi, v8hi, v2si, v4si, hi, si) 229 #define BUILTIN_VSDQ_I(T, N) \ 230 VAR11 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si, di) 231 #define BUILTIN_VSDQ_I_BHSI(T, N) \ 232 VAR10 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si) 233 #define BUILTIN_VSDQ_I_DI(T, N) \ 234 VAR8 (T, N, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, di) 235 #define BUILTIN_VSD_HSI(T, N) \ 236 VAR4 (T, N, v4hi, v2si, hi, si) 237 #define BUILTIN_VSQN_HSDI(T, N) \ 238 VAR6 (T, N, v8hi, v4si, v2di, hi, si, di) 239 #define BUILTIN_VSTRUCT(T, N) \ 240 VAR3 (T, N, oi, ci, xi) 241 242 static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = { 243 #include "aarch64-simd-builtins.def" 244 }; 245 246 #undef VAR1 247 #define VAR1(T, N, A) \ 248 AARCH64_SIMD_BUILTIN_##N##A, 249 250 enum aarch64_builtins 251 { 252 AARCH64_BUILTIN_MIN, 253 AARCH64_SIMD_BUILTIN_BASE, 254 #include "aarch64-simd-builtins.def" 255 AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE 256 + ARRAY_SIZE (aarch64_simd_builtin_data), 257 AARCH64_BUILTIN_MAX 258 }; 259 260 #undef BUILTIN_DX 261 #undef BUILTIN_SDQ_I 262 #undef BUILTIN_SD_HSI 263 #undef BUILTIN_V2F 264 #undef BUILTIN_VALL 265 #undef BUILTIN_VB 266 #undef BUILTIN_VD 267 #undef BUILTIN_VDC 268 #undef BUILTIN_VDIC 269 #undef BUILTIN_VDN 270 #undef BUILTIN_VDQ 271 #undef BUILTIN_VDQF 272 #undef BUILTIN_VDQHS 273 #undef BUILTIN_VDQIF 274 #undef BUILTIN_VDQM 275 #undef BUILTIN_VDQV 276 #undef BUILTIN_VDQ_BHSI 277 #undef BUILTIN_VDQ_I 278 #undef BUILTIN_VDW 279 #undef BUILTIN_VD_BHSI 280 #undef BUILTIN_VD_HSI 281 #undef BUILTIN_VD_RE 282 #undef BUILTIN_VQ 283 #undef BUILTIN_VQN 284 #undef BUILTIN_VQW 285 #undef BUILTIN_VQ_HSI 286 #undef BUILTIN_VQ_S 287 #undef BUILTIN_VSDQ_HSI 288 #undef BUILTIN_VSDQ_I 289 #undef BUILTIN_VSDQ_I_BHSI 290 #undef BUILTIN_VSDQ_I_DI 291 #undef BUILTIN_VSD_HSI 292 #undef BUILTIN_VSQN_HSDI 293 #undef BUILTIN_VSTRUCT 294 #undef CF 295 #undef VAR1 296 #undef VAR2 297 #undef VAR3 298 #undef VAR4 299 #undef VAR5 300 #undef VAR6 301 #undef VAR7 302 #undef VAR8 303 #undef VAR9 304 #undef VAR10 305 #undef VAR11 306 307 static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX]; 308 309 #define NUM_DREG_TYPES 6 310 #define NUM_QREG_TYPES 6 311 312 static void 313 aarch64_init_simd_builtins (void) 314 { 315 unsigned int i, fcode = AARCH64_SIMD_BUILTIN_BASE + 1; 316 317 /* Scalar type nodes. */ 318 tree aarch64_simd_intQI_type_node; 319 tree aarch64_simd_intHI_type_node; 320 tree aarch64_simd_polyQI_type_node; 321 tree aarch64_simd_polyHI_type_node; 322 tree aarch64_simd_intSI_type_node; 323 tree aarch64_simd_intDI_type_node; 324 tree aarch64_simd_float_type_node; 325 tree aarch64_simd_double_type_node; 326 327 /* Pointer to scalar type nodes. */ 328 tree intQI_pointer_node; 329 tree intHI_pointer_node; 330 tree intSI_pointer_node; 331 tree intDI_pointer_node; 332 tree float_pointer_node; 333 tree double_pointer_node; 334 335 /* Const scalar type nodes. */ 336 tree const_intQI_node; 337 tree const_intHI_node; 338 tree const_intSI_node; 339 tree const_intDI_node; 340 tree const_float_node; 341 tree const_double_node; 342 343 /* Pointer to const scalar type nodes. */ 344 tree const_intQI_pointer_node; 345 tree const_intHI_pointer_node; 346 tree const_intSI_pointer_node; 347 tree const_intDI_pointer_node; 348 tree const_float_pointer_node; 349 tree const_double_pointer_node; 350 351 /* Vector type nodes. */ 352 tree V8QI_type_node; 353 tree V4HI_type_node; 354 tree V2SI_type_node; 355 tree V2SF_type_node; 356 tree V16QI_type_node; 357 tree V8HI_type_node; 358 tree V4SI_type_node; 359 tree V4SF_type_node; 360 tree V2DI_type_node; 361 tree V2DF_type_node; 362 363 /* Scalar unsigned type nodes. */ 364 tree intUQI_type_node; 365 tree intUHI_type_node; 366 tree intUSI_type_node; 367 tree intUDI_type_node; 368 369 /* Opaque integer types for structures of vectors. */ 370 tree intEI_type_node; 371 tree intOI_type_node; 372 tree intCI_type_node; 373 tree intXI_type_node; 374 375 /* Pointer to vector type nodes. */ 376 tree V8QI_pointer_node; 377 tree V4HI_pointer_node; 378 tree V2SI_pointer_node; 379 tree V2SF_pointer_node; 380 tree V16QI_pointer_node; 381 tree V8HI_pointer_node; 382 tree V4SI_pointer_node; 383 tree V4SF_pointer_node; 384 tree V2DI_pointer_node; 385 tree V2DF_pointer_node; 386 387 /* Operations which return results as pairs. */ 388 tree void_ftype_pv8qi_v8qi_v8qi; 389 tree void_ftype_pv4hi_v4hi_v4hi; 390 tree void_ftype_pv2si_v2si_v2si; 391 tree void_ftype_pv2sf_v2sf_v2sf; 392 tree void_ftype_pdi_di_di; 393 tree void_ftype_pv16qi_v16qi_v16qi; 394 tree void_ftype_pv8hi_v8hi_v8hi; 395 tree void_ftype_pv4si_v4si_v4si; 396 tree void_ftype_pv4sf_v4sf_v4sf; 397 tree void_ftype_pv2di_v2di_v2di; 398 tree void_ftype_pv2df_v2df_v2df; 399 400 tree reinterp_ftype_dreg[NUM_DREG_TYPES][NUM_DREG_TYPES]; 401 tree reinterp_ftype_qreg[NUM_QREG_TYPES][NUM_QREG_TYPES]; 402 tree dreg_types[NUM_DREG_TYPES], qreg_types[NUM_QREG_TYPES]; 403 404 /* Create distinguished type nodes for AARCH64_SIMD vector element types, 405 and pointers to values of such types, so we can detect them later. */ 406 aarch64_simd_intQI_type_node = 407 make_signed_type (GET_MODE_PRECISION (QImode)); 408 aarch64_simd_intHI_type_node = 409 make_signed_type (GET_MODE_PRECISION (HImode)); 410 aarch64_simd_polyQI_type_node = 411 make_signed_type (GET_MODE_PRECISION (QImode)); 412 aarch64_simd_polyHI_type_node = 413 make_signed_type (GET_MODE_PRECISION (HImode)); 414 aarch64_simd_intSI_type_node = 415 make_signed_type (GET_MODE_PRECISION (SImode)); 416 aarch64_simd_intDI_type_node = 417 make_signed_type (GET_MODE_PRECISION (DImode)); 418 aarch64_simd_float_type_node = make_node (REAL_TYPE); 419 aarch64_simd_double_type_node = make_node (REAL_TYPE); 420 TYPE_PRECISION (aarch64_simd_float_type_node) = FLOAT_TYPE_SIZE; 421 TYPE_PRECISION (aarch64_simd_double_type_node) = DOUBLE_TYPE_SIZE; 422 layout_type (aarch64_simd_float_type_node); 423 layout_type (aarch64_simd_double_type_node); 424 425 /* Define typedefs which exactly correspond to the modes we are basing vector 426 types on. If you change these names you'll need to change 427 the table used by aarch64_mangle_type too. */ 428 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intQI_type_node, 429 "__builtin_aarch64_simd_qi"); 430 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intHI_type_node, 431 "__builtin_aarch64_simd_hi"); 432 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intSI_type_node, 433 "__builtin_aarch64_simd_si"); 434 (*lang_hooks.types.register_builtin_type) (aarch64_simd_float_type_node, 435 "__builtin_aarch64_simd_sf"); 436 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intDI_type_node, 437 "__builtin_aarch64_simd_di"); 438 (*lang_hooks.types.register_builtin_type) (aarch64_simd_double_type_node, 439 "__builtin_aarch64_simd_df"); 440 (*lang_hooks.types.register_builtin_type) (aarch64_simd_polyQI_type_node, 441 "__builtin_aarch64_simd_poly8"); 442 (*lang_hooks.types.register_builtin_type) (aarch64_simd_polyHI_type_node, 443 "__builtin_aarch64_simd_poly16"); 444 445 intQI_pointer_node = build_pointer_type (aarch64_simd_intQI_type_node); 446 intHI_pointer_node = build_pointer_type (aarch64_simd_intHI_type_node); 447 intSI_pointer_node = build_pointer_type (aarch64_simd_intSI_type_node); 448 intDI_pointer_node = build_pointer_type (aarch64_simd_intDI_type_node); 449 float_pointer_node = build_pointer_type (aarch64_simd_float_type_node); 450 double_pointer_node = build_pointer_type (aarch64_simd_double_type_node); 451 452 /* Next create constant-qualified versions of the above types. */ 453 const_intQI_node = build_qualified_type (aarch64_simd_intQI_type_node, 454 TYPE_QUAL_CONST); 455 const_intHI_node = build_qualified_type (aarch64_simd_intHI_type_node, 456 TYPE_QUAL_CONST); 457 const_intSI_node = build_qualified_type (aarch64_simd_intSI_type_node, 458 TYPE_QUAL_CONST); 459 const_intDI_node = build_qualified_type (aarch64_simd_intDI_type_node, 460 TYPE_QUAL_CONST); 461 const_float_node = build_qualified_type (aarch64_simd_float_type_node, 462 TYPE_QUAL_CONST); 463 const_double_node = build_qualified_type (aarch64_simd_double_type_node, 464 TYPE_QUAL_CONST); 465 466 const_intQI_pointer_node = build_pointer_type (const_intQI_node); 467 const_intHI_pointer_node = build_pointer_type (const_intHI_node); 468 const_intSI_pointer_node = build_pointer_type (const_intSI_node); 469 const_intDI_pointer_node = build_pointer_type (const_intDI_node); 470 const_float_pointer_node = build_pointer_type (const_float_node); 471 const_double_pointer_node = build_pointer_type (const_double_node); 472 473 /* Now create vector types based on our AARCH64 SIMD element types. */ 474 /* 64-bit vectors. */ 475 V8QI_type_node = 476 build_vector_type_for_mode (aarch64_simd_intQI_type_node, V8QImode); 477 V4HI_type_node = 478 build_vector_type_for_mode (aarch64_simd_intHI_type_node, V4HImode); 479 V2SI_type_node = 480 build_vector_type_for_mode (aarch64_simd_intSI_type_node, V2SImode); 481 V2SF_type_node = 482 build_vector_type_for_mode (aarch64_simd_float_type_node, V2SFmode); 483 /* 128-bit vectors. */ 484 V16QI_type_node = 485 build_vector_type_for_mode (aarch64_simd_intQI_type_node, V16QImode); 486 V8HI_type_node = 487 build_vector_type_for_mode (aarch64_simd_intHI_type_node, V8HImode); 488 V4SI_type_node = 489 build_vector_type_for_mode (aarch64_simd_intSI_type_node, V4SImode); 490 V4SF_type_node = 491 build_vector_type_for_mode (aarch64_simd_float_type_node, V4SFmode); 492 V2DI_type_node = 493 build_vector_type_for_mode (aarch64_simd_intDI_type_node, V2DImode); 494 V2DF_type_node = 495 build_vector_type_for_mode (aarch64_simd_double_type_node, V2DFmode); 496 497 /* Unsigned integer types for various mode sizes. */ 498 intUQI_type_node = make_unsigned_type (GET_MODE_PRECISION (QImode)); 499 intUHI_type_node = make_unsigned_type (GET_MODE_PRECISION (HImode)); 500 intUSI_type_node = make_unsigned_type (GET_MODE_PRECISION (SImode)); 501 intUDI_type_node = make_unsigned_type (GET_MODE_PRECISION (DImode)); 502 503 (*lang_hooks.types.register_builtin_type) (intUQI_type_node, 504 "__builtin_aarch64_simd_uqi"); 505 (*lang_hooks.types.register_builtin_type) (intUHI_type_node, 506 "__builtin_aarch64_simd_uhi"); 507 (*lang_hooks.types.register_builtin_type) (intUSI_type_node, 508 "__builtin_aarch64_simd_usi"); 509 (*lang_hooks.types.register_builtin_type) (intUDI_type_node, 510 "__builtin_aarch64_simd_udi"); 511 512 /* Opaque integer types for structures of vectors. */ 513 intEI_type_node = make_signed_type (GET_MODE_PRECISION (EImode)); 514 intOI_type_node = make_signed_type (GET_MODE_PRECISION (OImode)); 515 intCI_type_node = make_signed_type (GET_MODE_PRECISION (CImode)); 516 intXI_type_node = make_signed_type (GET_MODE_PRECISION (XImode)); 517 518 (*lang_hooks.types.register_builtin_type) (intTI_type_node, 519 "__builtin_aarch64_simd_ti"); 520 (*lang_hooks.types.register_builtin_type) (intEI_type_node, 521 "__builtin_aarch64_simd_ei"); 522 (*lang_hooks.types.register_builtin_type) (intOI_type_node, 523 "__builtin_aarch64_simd_oi"); 524 (*lang_hooks.types.register_builtin_type) (intCI_type_node, 525 "__builtin_aarch64_simd_ci"); 526 (*lang_hooks.types.register_builtin_type) (intXI_type_node, 527 "__builtin_aarch64_simd_xi"); 528 529 /* Pointers to vector types. */ 530 V8QI_pointer_node = build_pointer_type (V8QI_type_node); 531 V4HI_pointer_node = build_pointer_type (V4HI_type_node); 532 V2SI_pointer_node = build_pointer_type (V2SI_type_node); 533 V2SF_pointer_node = build_pointer_type (V2SF_type_node); 534 V16QI_pointer_node = build_pointer_type (V16QI_type_node); 535 V8HI_pointer_node = build_pointer_type (V8HI_type_node); 536 V4SI_pointer_node = build_pointer_type (V4SI_type_node); 537 V4SF_pointer_node = build_pointer_type (V4SF_type_node); 538 V2DI_pointer_node = build_pointer_type (V2DI_type_node); 539 V2DF_pointer_node = build_pointer_type (V2DF_type_node); 540 541 /* Operations which return results as pairs. */ 542 void_ftype_pv8qi_v8qi_v8qi = 543 build_function_type_list (void_type_node, V8QI_pointer_node, 544 V8QI_type_node, V8QI_type_node, NULL); 545 void_ftype_pv4hi_v4hi_v4hi = 546 build_function_type_list (void_type_node, V4HI_pointer_node, 547 V4HI_type_node, V4HI_type_node, NULL); 548 void_ftype_pv2si_v2si_v2si = 549 build_function_type_list (void_type_node, V2SI_pointer_node, 550 V2SI_type_node, V2SI_type_node, NULL); 551 void_ftype_pv2sf_v2sf_v2sf = 552 build_function_type_list (void_type_node, V2SF_pointer_node, 553 V2SF_type_node, V2SF_type_node, NULL); 554 void_ftype_pdi_di_di = 555 build_function_type_list (void_type_node, intDI_pointer_node, 556 aarch64_simd_intDI_type_node, 557 aarch64_simd_intDI_type_node, NULL); 558 void_ftype_pv16qi_v16qi_v16qi = 559 build_function_type_list (void_type_node, V16QI_pointer_node, 560 V16QI_type_node, V16QI_type_node, NULL); 561 void_ftype_pv8hi_v8hi_v8hi = 562 build_function_type_list (void_type_node, V8HI_pointer_node, 563 V8HI_type_node, V8HI_type_node, NULL); 564 void_ftype_pv4si_v4si_v4si = 565 build_function_type_list (void_type_node, V4SI_pointer_node, 566 V4SI_type_node, V4SI_type_node, NULL); 567 void_ftype_pv4sf_v4sf_v4sf = 568 build_function_type_list (void_type_node, V4SF_pointer_node, 569 V4SF_type_node, V4SF_type_node, NULL); 570 void_ftype_pv2di_v2di_v2di = 571 build_function_type_list (void_type_node, V2DI_pointer_node, 572 V2DI_type_node, V2DI_type_node, NULL); 573 void_ftype_pv2df_v2df_v2df = 574 build_function_type_list (void_type_node, V2DF_pointer_node, 575 V2DF_type_node, V2DF_type_node, NULL); 576 577 dreg_types[0] = V8QI_type_node; 578 dreg_types[1] = V4HI_type_node; 579 dreg_types[2] = V2SI_type_node; 580 dreg_types[3] = V2SF_type_node; 581 dreg_types[4] = aarch64_simd_intDI_type_node; 582 dreg_types[5] = aarch64_simd_double_type_node; 583 584 qreg_types[0] = V16QI_type_node; 585 qreg_types[1] = V8HI_type_node; 586 qreg_types[2] = V4SI_type_node; 587 qreg_types[3] = V4SF_type_node; 588 qreg_types[4] = V2DI_type_node; 589 qreg_types[5] = V2DF_type_node; 590 591 /* If NUM_DREG_TYPES != NUM_QREG_TYPES, we will need separate nested loops 592 for qreg and dreg reinterp inits. */ 593 for (i = 0; i < NUM_DREG_TYPES; i++) 594 { 595 int j; 596 for (j = 0; j < NUM_DREG_TYPES; j++) 597 { 598 reinterp_ftype_dreg[i][j] 599 = build_function_type_list (dreg_types[i], dreg_types[j], NULL); 600 reinterp_ftype_qreg[i][j] 601 = build_function_type_list (qreg_types[i], qreg_types[j], NULL); 602 } 603 } 604 605 for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++) 606 { 607 aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i]; 608 const char *const modenames[] = 609 { 610 "v8qi", "v4hi", "v2si", "v2sf", "di", "df", 611 "v16qi", "v8hi", "v4si", "v4sf", "v2di", "v2df", 612 "ti", "ei", "oi", "xi", "si", "hi", "qi" 613 }; 614 char namebuf[60]; 615 tree ftype = NULL; 616 tree fndecl = NULL; 617 int is_load = 0; 618 int is_store = 0; 619 620 gcc_assert (ARRAY_SIZE (modenames) == T_MAX); 621 622 d->fcode = fcode; 623 624 switch (d->itype) 625 { 626 case AARCH64_SIMD_LOAD1: 627 case AARCH64_SIMD_LOAD1LANE: 628 case AARCH64_SIMD_LOADSTRUCT: 629 case AARCH64_SIMD_LOADSTRUCTLANE: 630 is_load = 1; 631 /* Fall through. */ 632 case AARCH64_SIMD_STORE1: 633 case AARCH64_SIMD_STORE1LANE: 634 case AARCH64_SIMD_STORESTRUCT: 635 case AARCH64_SIMD_STORESTRUCTLANE: 636 if (!is_load) 637 is_store = 1; 638 /* Fall through. */ 639 case AARCH64_SIMD_UNOP: 640 case AARCH64_SIMD_BINOP: 641 case AARCH64_SIMD_TERNOP: 642 case AARCH64_SIMD_QUADOP: 643 case AARCH64_SIMD_COMBINE: 644 case AARCH64_SIMD_CONVERT: 645 case AARCH64_SIMD_CREATE: 646 case AARCH64_SIMD_DUP: 647 case AARCH64_SIMD_DUPLANE: 648 case AARCH64_SIMD_FIXCONV: 649 case AARCH64_SIMD_GETLANE: 650 case AARCH64_SIMD_LANEMAC: 651 case AARCH64_SIMD_LANEMUL: 652 case AARCH64_SIMD_LANEMULH: 653 case AARCH64_SIMD_LANEMULL: 654 case AARCH64_SIMD_LOGICBINOP: 655 case AARCH64_SIMD_SCALARMAC: 656 case AARCH64_SIMD_SCALARMUL: 657 case AARCH64_SIMD_SCALARMULH: 658 case AARCH64_SIMD_SCALARMULL: 659 case AARCH64_SIMD_SELECT: 660 case AARCH64_SIMD_SETLANE: 661 case AARCH64_SIMD_SHIFTACC: 662 case AARCH64_SIMD_SHIFTIMM: 663 case AARCH64_SIMD_SHIFTINSERT: 664 case AARCH64_SIMD_SPLIT: 665 case AARCH64_SIMD_VTBL: 666 case AARCH64_SIMD_VTBX: 667 { 668 int k; 669 tree return_type = void_type_node, args = void_list_node; 670 tree eltype; 671 /* Build a function type directly from the insn_data for this 672 builtin. The build_function_type () function takes care of 673 removing duplicates for us. */ 674 675 for (k = insn_data[d->code].n_operands -1; k >= 0; k--) 676 { 677 /* Skip an internal operand for vget_{low, high}. */ 678 if (k == 2 && d->itype == AARCH64_SIMD_SPLIT) 679 continue; 680 681 if (is_load && k == 1) 682 { 683 /* AdvSIMD load patterns always have the memory operand 684 (a DImode pointer) in the operand 1 position. We 685 want a const pointer to the element type in that 686 position. */ 687 gcc_assert (insn_data[d->code].operand[k].mode == DImode); 688 689 switch (d->mode) 690 { 691 case T_V8QI: 692 case T_V16QI: 693 eltype = const_intQI_pointer_node; 694 break; 695 696 case T_V4HI: 697 case T_V8HI: 698 eltype = const_intHI_pointer_node; 699 break; 700 701 case T_V2SI: 702 case T_V4SI: 703 eltype = const_intSI_pointer_node; 704 break; 705 706 case T_V2SF: 707 case T_V4SF: 708 eltype = const_float_pointer_node; 709 break; 710 711 case T_DI: 712 case T_V2DI: 713 eltype = const_intDI_pointer_node; 714 break; 715 716 case T_DF: 717 case T_V2DF: 718 eltype = const_double_pointer_node; 719 break; 720 721 default: 722 gcc_unreachable (); 723 } 724 } 725 else if (is_store && k == 0) 726 { 727 /* Similarly, AdvSIMD store patterns use operand 0 as 728 the memory location to store to (a DImode pointer). 729 Use a pointer to the element type of the store in 730 that position. */ 731 gcc_assert (insn_data[d->code].operand[k].mode == DImode); 732 733 switch (d->mode) 734 { 735 case T_V8QI: 736 case T_V16QI: 737 eltype = intQI_pointer_node; 738 break; 739 740 case T_V4HI: 741 case T_V8HI: 742 eltype = intHI_pointer_node; 743 break; 744 745 case T_V2SI: 746 case T_V4SI: 747 eltype = intSI_pointer_node; 748 break; 749 750 case T_V2SF: 751 case T_V4SF: 752 eltype = float_pointer_node; 753 break; 754 755 case T_DI: 756 case T_V2DI: 757 eltype = intDI_pointer_node; 758 break; 759 760 case T_DF: 761 case T_V2DF: 762 eltype = double_pointer_node; 763 break; 764 765 default: 766 gcc_unreachable (); 767 } 768 } 769 else 770 { 771 switch (insn_data[d->code].operand[k].mode) 772 { 773 case VOIDmode: 774 eltype = void_type_node; 775 break; 776 /* Scalars. */ 777 case QImode: 778 eltype = aarch64_simd_intQI_type_node; 779 break; 780 case HImode: 781 eltype = aarch64_simd_intHI_type_node; 782 break; 783 case SImode: 784 eltype = aarch64_simd_intSI_type_node; 785 break; 786 case SFmode: 787 eltype = aarch64_simd_float_type_node; 788 break; 789 case DFmode: 790 eltype = aarch64_simd_double_type_node; 791 break; 792 case DImode: 793 eltype = aarch64_simd_intDI_type_node; 794 break; 795 case TImode: 796 eltype = intTI_type_node; 797 break; 798 case EImode: 799 eltype = intEI_type_node; 800 break; 801 case OImode: 802 eltype = intOI_type_node; 803 break; 804 case CImode: 805 eltype = intCI_type_node; 806 break; 807 case XImode: 808 eltype = intXI_type_node; 809 break; 810 /* 64-bit vectors. */ 811 case V8QImode: 812 eltype = V8QI_type_node; 813 break; 814 case V4HImode: 815 eltype = V4HI_type_node; 816 break; 817 case V2SImode: 818 eltype = V2SI_type_node; 819 break; 820 case V2SFmode: 821 eltype = V2SF_type_node; 822 break; 823 /* 128-bit vectors. */ 824 case V16QImode: 825 eltype = V16QI_type_node; 826 break; 827 case V8HImode: 828 eltype = V8HI_type_node; 829 break; 830 case V4SImode: 831 eltype = V4SI_type_node; 832 break; 833 case V4SFmode: 834 eltype = V4SF_type_node; 835 break; 836 case V2DImode: 837 eltype = V2DI_type_node; 838 break; 839 case V2DFmode: 840 eltype = V2DF_type_node; 841 break; 842 default: 843 gcc_unreachable (); 844 } 845 } 846 847 if (k == 0 && !is_store) 848 return_type = eltype; 849 else 850 args = tree_cons (NULL_TREE, eltype, args); 851 } 852 ftype = build_function_type (return_type, args); 853 } 854 break; 855 856 case AARCH64_SIMD_RESULTPAIR: 857 { 858 switch (insn_data[d->code].operand[1].mode) 859 { 860 case V8QImode: 861 ftype = void_ftype_pv8qi_v8qi_v8qi; 862 break; 863 case V4HImode: 864 ftype = void_ftype_pv4hi_v4hi_v4hi; 865 break; 866 case V2SImode: 867 ftype = void_ftype_pv2si_v2si_v2si; 868 break; 869 case V2SFmode: 870 ftype = void_ftype_pv2sf_v2sf_v2sf; 871 break; 872 case DImode: 873 ftype = void_ftype_pdi_di_di; 874 break; 875 case V16QImode: 876 ftype = void_ftype_pv16qi_v16qi_v16qi; 877 break; 878 case V8HImode: 879 ftype = void_ftype_pv8hi_v8hi_v8hi; 880 break; 881 case V4SImode: 882 ftype = void_ftype_pv4si_v4si_v4si; 883 break; 884 case V4SFmode: 885 ftype = void_ftype_pv4sf_v4sf_v4sf; 886 break; 887 case V2DImode: 888 ftype = void_ftype_pv2di_v2di_v2di; 889 break; 890 case V2DFmode: 891 ftype = void_ftype_pv2df_v2df_v2df; 892 break; 893 default: 894 gcc_unreachable (); 895 } 896 } 897 break; 898 899 case AARCH64_SIMD_REINTERP: 900 { 901 /* We iterate over 6 doubleword types, then 6 quadword 902 types. */ 903 int rhs_d = d->mode % NUM_DREG_TYPES; 904 int rhs_q = (d->mode - NUM_DREG_TYPES) % NUM_QREG_TYPES; 905 switch (insn_data[d->code].operand[0].mode) 906 { 907 case V8QImode: 908 ftype = reinterp_ftype_dreg[0][rhs_d]; 909 break; 910 case V4HImode: 911 ftype = reinterp_ftype_dreg[1][rhs_d]; 912 break; 913 case V2SImode: 914 ftype = reinterp_ftype_dreg[2][rhs_d]; 915 break; 916 case V2SFmode: 917 ftype = reinterp_ftype_dreg[3][rhs_d]; 918 break; 919 case DImode: 920 ftype = reinterp_ftype_dreg[4][rhs_d]; 921 break; 922 case DFmode: 923 ftype = reinterp_ftype_dreg[5][rhs_d]; 924 break; 925 case V16QImode: 926 ftype = reinterp_ftype_qreg[0][rhs_q]; 927 break; 928 case V8HImode: 929 ftype = reinterp_ftype_qreg[1][rhs_q]; 930 break; 931 case V4SImode: 932 ftype = reinterp_ftype_qreg[2][rhs_q]; 933 break; 934 case V4SFmode: 935 ftype = reinterp_ftype_qreg[3][rhs_q]; 936 break; 937 case V2DImode: 938 ftype = reinterp_ftype_qreg[4][rhs_q]; 939 break; 940 case V2DFmode: 941 ftype = reinterp_ftype_qreg[5][rhs_q]; 942 break; 943 default: 944 gcc_unreachable (); 945 } 946 } 947 break; 948 949 default: 950 gcc_unreachable (); 951 } 952 gcc_assert (ftype != NULL); 953 954 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s%s", 955 d->name, modenames[d->mode]); 956 957 fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD, 958 NULL, NULL_TREE); 959 aarch64_builtin_decls[fcode] = fndecl; 960 } 961 } 962 963 void 964 aarch64_init_builtins (void) 965 { 966 if (TARGET_SIMD) 967 aarch64_init_simd_builtins (); 968 } 969 970 tree 971 aarch64_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) 972 { 973 if (code >= AARCH64_BUILTIN_MAX) 974 return error_mark_node; 975 976 return aarch64_builtin_decls[code]; 977 } 978 979 typedef enum 980 { 981 SIMD_ARG_COPY_TO_REG, 982 SIMD_ARG_CONSTANT, 983 SIMD_ARG_STOP 984 } builtin_simd_arg; 985 986 #define SIMD_MAX_BUILTIN_ARGS 5 987 988 static rtx 989 aarch64_simd_expand_args (rtx target, int icode, int have_retval, 990 tree exp, ...) 991 { 992 va_list ap; 993 rtx pat; 994 tree arg[SIMD_MAX_BUILTIN_ARGS]; 995 rtx op[SIMD_MAX_BUILTIN_ARGS]; 996 enum machine_mode tmode = insn_data[icode].operand[0].mode; 997 enum machine_mode mode[SIMD_MAX_BUILTIN_ARGS]; 998 int argc = 0; 999 1000 if (have_retval 1001 && (!target 1002 || GET_MODE (target) != tmode 1003 || !(*insn_data[icode].operand[0].predicate) (target, tmode))) 1004 target = gen_reg_rtx (tmode); 1005 1006 va_start (ap, exp); 1007 1008 for (;;) 1009 { 1010 builtin_simd_arg thisarg = (builtin_simd_arg) va_arg (ap, int); 1011 1012 if (thisarg == SIMD_ARG_STOP) 1013 break; 1014 else 1015 { 1016 arg[argc] = CALL_EXPR_ARG (exp, argc); 1017 op[argc] = expand_normal (arg[argc]); 1018 mode[argc] = insn_data[icode].operand[argc + have_retval].mode; 1019 1020 switch (thisarg) 1021 { 1022 case SIMD_ARG_COPY_TO_REG: 1023 /*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */ 1024 if (!(*insn_data[icode].operand[argc + have_retval].predicate) 1025 (op[argc], mode[argc])) 1026 op[argc] = copy_to_mode_reg (mode[argc], op[argc]); 1027 break; 1028 1029 case SIMD_ARG_CONSTANT: 1030 if (!(*insn_data[icode].operand[argc + have_retval].predicate) 1031 (op[argc], mode[argc])) 1032 error_at (EXPR_LOCATION (exp), "incompatible type for argument %d, " 1033 "expected %<const int%>", argc + 1); 1034 break; 1035 1036 case SIMD_ARG_STOP: 1037 gcc_unreachable (); 1038 } 1039 1040 argc++; 1041 } 1042 } 1043 1044 va_end (ap); 1045 1046 if (have_retval) 1047 switch (argc) 1048 { 1049 case 1: 1050 pat = GEN_FCN (icode) (target, op[0]); 1051 break; 1052 1053 case 2: 1054 pat = GEN_FCN (icode) (target, op[0], op[1]); 1055 break; 1056 1057 case 3: 1058 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]); 1059 break; 1060 1061 case 4: 1062 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]); 1063 break; 1064 1065 case 5: 1066 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]); 1067 break; 1068 1069 default: 1070 gcc_unreachable (); 1071 } 1072 else 1073 switch (argc) 1074 { 1075 case 1: 1076 pat = GEN_FCN (icode) (op[0]); 1077 break; 1078 1079 case 2: 1080 pat = GEN_FCN (icode) (op[0], op[1]); 1081 break; 1082 1083 case 3: 1084 pat = GEN_FCN (icode) (op[0], op[1], op[2]); 1085 break; 1086 1087 case 4: 1088 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); 1089 break; 1090 1091 case 5: 1092 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]); 1093 break; 1094 1095 default: 1096 gcc_unreachable (); 1097 } 1098 1099 if (!pat) 1100 return 0; 1101 1102 emit_insn (pat); 1103 1104 return target; 1105 } 1106 1107 /* Expand an AArch64 AdvSIMD builtin(intrinsic). */ 1108 rtx 1109 aarch64_simd_expand_builtin (int fcode, tree exp, rtx target) 1110 { 1111 aarch64_simd_builtin_datum *d = 1112 &aarch64_simd_builtin_data[fcode - (AARCH64_SIMD_BUILTIN_BASE + 1)]; 1113 aarch64_simd_itype itype = d->itype; 1114 enum insn_code icode = d->code; 1115 1116 switch (itype) 1117 { 1118 case AARCH64_SIMD_UNOP: 1119 return aarch64_simd_expand_args (target, icode, 1, exp, 1120 SIMD_ARG_COPY_TO_REG, 1121 SIMD_ARG_STOP); 1122 1123 case AARCH64_SIMD_BINOP: 1124 { 1125 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); 1126 /* Handle constants only if the predicate allows it. */ 1127 bool op1_const_int_p = 1128 (CONST_INT_P (arg2) 1129 && (*insn_data[icode].operand[2].predicate) 1130 (arg2, insn_data[icode].operand[2].mode)); 1131 return aarch64_simd_expand_args 1132 (target, icode, 1, exp, 1133 SIMD_ARG_COPY_TO_REG, 1134 op1_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG, 1135 SIMD_ARG_STOP); 1136 } 1137 1138 case AARCH64_SIMD_TERNOP: 1139 return aarch64_simd_expand_args (target, icode, 1, exp, 1140 SIMD_ARG_COPY_TO_REG, 1141 SIMD_ARG_COPY_TO_REG, 1142 SIMD_ARG_COPY_TO_REG, 1143 SIMD_ARG_STOP); 1144 1145 case AARCH64_SIMD_QUADOP: 1146 return aarch64_simd_expand_args (target, icode, 1, exp, 1147 SIMD_ARG_COPY_TO_REG, 1148 SIMD_ARG_COPY_TO_REG, 1149 SIMD_ARG_COPY_TO_REG, 1150 SIMD_ARG_COPY_TO_REG, 1151 SIMD_ARG_STOP); 1152 case AARCH64_SIMD_LOAD1: 1153 case AARCH64_SIMD_LOADSTRUCT: 1154 return aarch64_simd_expand_args (target, icode, 1, exp, 1155 SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP); 1156 1157 case AARCH64_SIMD_STORE1: 1158 case AARCH64_SIMD_STORESTRUCT: 1159 return aarch64_simd_expand_args (target, icode, 0, exp, 1160 SIMD_ARG_COPY_TO_REG, 1161 SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP); 1162 1163 case AARCH64_SIMD_REINTERP: 1164 return aarch64_simd_expand_args (target, icode, 1, exp, 1165 SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP); 1166 1167 case AARCH64_SIMD_CREATE: 1168 return aarch64_simd_expand_args (target, icode, 1, exp, 1169 SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP); 1170 1171 case AARCH64_SIMD_COMBINE: 1172 return aarch64_simd_expand_args (target, icode, 1, exp, 1173 SIMD_ARG_COPY_TO_REG, 1174 SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP); 1175 1176 case AARCH64_SIMD_GETLANE: 1177 return aarch64_simd_expand_args (target, icode, 1, exp, 1178 SIMD_ARG_COPY_TO_REG, 1179 SIMD_ARG_CONSTANT, 1180 SIMD_ARG_STOP); 1181 1182 case AARCH64_SIMD_SETLANE: 1183 return aarch64_simd_expand_args (target, icode, 1, exp, 1184 SIMD_ARG_COPY_TO_REG, 1185 SIMD_ARG_COPY_TO_REG, 1186 SIMD_ARG_CONSTANT, 1187 SIMD_ARG_STOP); 1188 1189 case AARCH64_SIMD_SHIFTIMM: 1190 return aarch64_simd_expand_args (target, icode, 1, exp, 1191 SIMD_ARG_COPY_TO_REG, 1192 SIMD_ARG_CONSTANT, 1193 SIMD_ARG_STOP); 1194 1195 case AARCH64_SIMD_SHIFTACC: 1196 case AARCH64_SIMD_SHIFTINSERT: 1197 return aarch64_simd_expand_args (target, icode, 1, exp, 1198 SIMD_ARG_COPY_TO_REG, 1199 SIMD_ARG_COPY_TO_REG, 1200 SIMD_ARG_CONSTANT, 1201 SIMD_ARG_STOP); 1202 1203 default: 1204 gcc_unreachable (); 1205 } 1206 } 1207 1208 /* Expand an expression EXP that calls a built-in function, 1209 with result going to TARGET if that's convenient. */ 1210 rtx 1211 aarch64_expand_builtin (tree exp, 1212 rtx target, 1213 rtx subtarget ATTRIBUTE_UNUSED, 1214 enum machine_mode mode ATTRIBUTE_UNUSED, 1215 int ignore ATTRIBUTE_UNUSED) 1216 { 1217 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); 1218 int fcode = DECL_FUNCTION_CODE (fndecl); 1219 1220 if (fcode >= AARCH64_SIMD_BUILTIN_BASE) 1221 return aarch64_simd_expand_builtin (fcode, exp, target); 1222 1223 return NULL_RTX; 1224 } 1225 1226 tree 1227 aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) 1228 { 1229 enum machine_mode in_mode, out_mode; 1230 int in_n, out_n; 1231 1232 if (TREE_CODE (type_out) != VECTOR_TYPE 1233 || TREE_CODE (type_in) != VECTOR_TYPE) 1234 return NULL_TREE; 1235 1236 out_mode = TYPE_MODE (TREE_TYPE (type_out)); 1237 out_n = TYPE_VECTOR_SUBPARTS (type_out); 1238 in_mode = TYPE_MODE (TREE_TYPE (type_in)); 1239 in_n = TYPE_VECTOR_SUBPARTS (type_in); 1240 1241 #undef AARCH64_CHECK_BUILTIN_MODE 1242 #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1 1243 #define AARCH64_FIND_FRINT_VARIANT(N) \ 1244 (AARCH64_CHECK_BUILTIN_MODE (2, D) \ 1245 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2df] \ 1246 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \ 1247 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v4sf] \ 1248 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \ 1249 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2sf] \ 1250 : NULL_TREE))) 1251 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) 1252 { 1253 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl); 1254 switch (fn) 1255 { 1256 #undef AARCH64_CHECK_BUILTIN_MODE 1257 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \ 1258 (out_mode == N##Fmode && out_n == C \ 1259 && in_mode == N##Fmode && in_n == C) 1260 case BUILT_IN_FLOOR: 1261 case BUILT_IN_FLOORF: 1262 return AARCH64_FIND_FRINT_VARIANT (frintm); 1263 case BUILT_IN_CEIL: 1264 case BUILT_IN_CEILF: 1265 return AARCH64_FIND_FRINT_VARIANT (frintp); 1266 case BUILT_IN_TRUNC: 1267 case BUILT_IN_TRUNCF: 1268 return AARCH64_FIND_FRINT_VARIANT (frintz); 1269 case BUILT_IN_ROUND: 1270 case BUILT_IN_ROUNDF: 1271 return AARCH64_FIND_FRINT_VARIANT (frinta); 1272 case BUILT_IN_NEARBYINT: 1273 case BUILT_IN_NEARBYINTF: 1274 return AARCH64_FIND_FRINT_VARIANT (frinti); 1275 case BUILT_IN_SQRT: 1276 case BUILT_IN_SQRTF: 1277 return AARCH64_FIND_FRINT_VARIANT (sqrt); 1278 #undef AARCH64_CHECK_BUILTIN_MODE 1279 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \ 1280 (out_mode == N##Imode && out_n == C \ 1281 && in_mode == N##Fmode && in_n == C) 1282 case BUILT_IN_LFLOOR: 1283 return AARCH64_FIND_FRINT_VARIANT (fcvtms); 1284 case BUILT_IN_LCEIL: 1285 return AARCH64_FIND_FRINT_VARIANT (fcvtps); 1286 default: 1287 return NULL_TREE; 1288 } 1289 } 1290 1291 return NULL_TREE; 1292 } 1293 #undef AARCH64_CHECK_BUILTIN_MODE 1294 #undef AARCH64_FIND_FRINT_VARIANT 1295