1 /* Target-specific built-in function support for the Power architecture.
2 See also rs6000-c.c, rs6000-gen-builtins.c, rs6000-builtins.def, and
3 rs6000-overloads.def.
4 Note that "normal" builtins (generic math functions, etc.) are handled
5 in rs6000.c.
6
7 Copyright (C) 2002-2022 Free Software Foundation, Inc.
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published
13 by the Free Software Foundation; either version 3, or (at your
14 option) any later version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
24
25 #define IN_TARGET_CODE 1
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "target.h"
31 #include "backend.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "memmodel.h"
35 #include "gimple.h"
36 #include "tm_p.h"
37 #include "optabs.h"
38 #include "recog.h"
39 #include "diagnostic-core.h"
40 #include "fold-const.h"
41 #include "stor-layout.h"
42 #include "calls.h"
43 #include "varasm.h"
44 #include "explow.h"
45 #include "expr.h"
46 #include "langhooks.h"
47 #include "gimplify.h"
48 #include "gimple-fold.h"
49 #include "gimple-iterator.h"
50 #include "ssa.h"
51 #include "tree-ssa-propagate.h"
52 #include "builtins.h"
53 #include "tree-vector-builder.h"
54 #if TARGET_XCOFF
55 #include "xcoffout.h" /* get declarations of xcoff_*_section_name */
56 #endif
57 #include "ppc-auxv.h"
58 #include "rs6000-internal.h"
59
60 /* Built in types. */
61 tree rs6000_builtin_types[RS6000_BTI_MAX];
62
63 /* Support targetm.vectorize.builtin_mask_for_load. */
64 tree altivec_builtin_mask_for_load;
65
66 /* **** General support functions **** */
67
68 /* Raise an error message for a builtin function that is called without the
69 appropriate target options being set. */
70
71 void
rs6000_invalid_builtin(enum rs6000_gen_builtins fncode)72 rs6000_invalid_builtin (enum rs6000_gen_builtins fncode)
73 {
74 size_t j = (size_t) fncode;
75 const char *name = rs6000_builtin_info[j].bifname;
76
77 switch (rs6000_builtin_info[j].enable)
78 {
79 case ENB_P5:
80 error ("%qs requires the %qs option", name, "-mcpu=power5");
81 break;
82 case ENB_P6:
83 error ("%qs requires the %qs option", name, "-mcpu=power6");
84 break;
85 case ENB_P6_64:
86 error ("%qs requires the %qs option and either the %qs or %qs option",
87 name, "-mcpu=power6", "-m64", "-mpowerpc64");
88 break;
89 case ENB_ALTIVEC:
90 error ("%qs requires the %qs option", name, "-maltivec");
91 break;
92 case ENB_CELL:
93 error ("%qs requires the %qs option", name, "-mcpu=cell");
94 break;
95 case ENB_VSX:
96 error ("%qs requires the %qs option", name, "-mvsx");
97 break;
98 case ENB_P7:
99 error ("%qs requires the %qs option", name, "-mcpu=power7");
100 break;
101 case ENB_P7_64:
102 error ("%qs requires the %qs option and either the %qs or %qs option",
103 name, "-mcpu=power7", "-m64", "-mpowerpc64");
104 break;
105 case ENB_P8:
106 error ("%qs requires the %qs option", name, "-mcpu=power8");
107 break;
108 case ENB_P8V:
109 error ("%qs requires the %qs and %qs options", name, "-mcpu=power8",
110 "-mvsx");
111 break;
112 case ENB_P9:
113 error ("%qs requires the %qs option", name, "-mcpu=power9");
114 break;
115 case ENB_P9_64:
116 error ("%qs requires the %qs option and either the %qs or %qs option",
117 name, "-mcpu=power9", "-m64", "-mpowerpc64");
118 break;
119 case ENB_P9V:
120 error ("%qs requires the %qs and %qs options", name, "-mcpu=power9",
121 "-mvsx");
122 break;
123 case ENB_IEEE128_HW:
124 error ("%qs requires quad-precision floating-point arithmetic", name);
125 break;
126 case ENB_DFP:
127 error ("%qs requires the %qs option", name, "-mhard-dfp");
128 break;
129 case ENB_CRYPTO:
130 error ("%qs requires the %qs option", name, "-mcrypto");
131 break;
132 case ENB_HTM:
133 error ("%qs requires the %qs option", name, "-mhtm");
134 break;
135 case ENB_P10:
136 error ("%qs requires the %qs option", name, "-mcpu=power10");
137 break;
138 case ENB_P10_64:
139 error ("%qs requires the %qs option and either the %qs or %qs option",
140 name, "-mcpu=power10", "-m64", "-mpowerpc64");
141 break;
142 case ENB_MMA:
143 error ("%qs requires the %qs option", name, "-mmma");
144 break;
145 default:
146 case ENB_ALWAYS:
147 gcc_unreachable ();
148 }
149 }
150
151 /* Check whether a builtin function is supported in this target
152 configuration. */
153 bool
rs6000_builtin_is_supported(enum rs6000_gen_builtins fncode)154 rs6000_builtin_is_supported (enum rs6000_gen_builtins fncode)
155 {
156 switch (rs6000_builtin_info[(size_t) fncode].enable)
157 {
158 case ENB_ALWAYS:
159 return true;
160 case ENB_P5:
161 return TARGET_POPCNTB;
162 case ENB_P6:
163 return TARGET_CMPB;
164 case ENB_P6_64:
165 return TARGET_CMPB && TARGET_POWERPC64;
166 case ENB_P7:
167 return TARGET_POPCNTD;
168 case ENB_P7_64:
169 return TARGET_POPCNTD && TARGET_POWERPC64;
170 case ENB_P8:
171 return TARGET_POWER8;
172 case ENB_P8V:
173 return TARGET_P8_VECTOR;
174 case ENB_P9:
175 return TARGET_MODULO;
176 case ENB_P9_64:
177 return TARGET_MODULO && TARGET_POWERPC64;
178 case ENB_P9V:
179 return TARGET_P9_VECTOR;
180 case ENB_P10:
181 return TARGET_POWER10;
182 case ENB_P10_64:
183 return TARGET_POWER10 && TARGET_POWERPC64;
184 case ENB_ALTIVEC:
185 return TARGET_ALTIVEC;
186 case ENB_VSX:
187 return TARGET_VSX;
188 case ENB_CELL:
189 return TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL;
190 case ENB_IEEE128_HW:
191 return TARGET_FLOAT128_HW;
192 case ENB_DFP:
193 return TARGET_DFP;
194 case ENB_CRYPTO:
195 return TARGET_CRYPTO;
196 case ENB_HTM:
197 return TARGET_HTM;
198 case ENB_MMA:
199 return TARGET_MMA;
200 default:
201 gcc_unreachable ();
202 }
203 gcc_unreachable ();
204 }
205
206 /* Target hook for early folding of built-ins, shamelessly stolen
207 from ia64.cc. */
208
209 tree
rs6000_fold_builtin(tree fndecl ATTRIBUTE_UNUSED,int n_args ATTRIBUTE_UNUSED,tree * args ATTRIBUTE_UNUSED,bool ignore ATTRIBUTE_UNUSED)210 rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED,
211 int n_args ATTRIBUTE_UNUSED,
212 tree *args ATTRIBUTE_UNUSED,
213 bool ignore ATTRIBUTE_UNUSED)
214 {
215 #ifdef SUBTARGET_FOLD_BUILTIN
216 return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore);
217 #else
218 return NULL_TREE;
219 #endif
220 }
221
222 tree
rs6000_builtin_decl(unsigned code,bool)223 rs6000_builtin_decl (unsigned code, bool /* initialize_p */)
224 {
225 rs6000_gen_builtins fcode = (rs6000_gen_builtins) code;
226
227 if (fcode >= RS6000_OVLD_MAX)
228 return error_mark_node;
229
230 return rs6000_builtin_decls[code];
231 }
232
233 /* Implement targetm.vectorize.builtin_mask_for_load. */
234 tree
rs6000_builtin_mask_for_load(void)235 rs6000_builtin_mask_for_load (void)
236 {
237 /* Don't use lvsl/vperm for P8 and similarly efficient machines. */
238 if ((TARGET_ALTIVEC && !TARGET_VSX)
239 || (TARGET_VSX && !TARGET_EFFICIENT_UNALIGNED_VSX))
240 return altivec_builtin_mask_for_load;
241 else
242 return 0;
243 }
244
245 /* Implement targetm.vectorize.builtin_md_vectorized_function. */
246
247 tree
rs6000_builtin_md_vectorized_function(tree fndecl,tree type_out,tree type_in)248 rs6000_builtin_md_vectorized_function (tree fndecl, tree type_out,
249 tree type_in)
250 {
251 machine_mode in_mode, out_mode;
252 int in_n, out_n;
253
254 if (TARGET_DEBUG_BUILTIN)
255 fprintf (stderr,
256 "rs6000_builtin_md_vectorized_function (%s, %s, %s)\n",
257 IDENTIFIER_POINTER (DECL_NAME (fndecl)),
258 GET_MODE_NAME (TYPE_MODE (type_out)),
259 GET_MODE_NAME (TYPE_MODE (type_in)));
260
261 /* TODO: Should this be gcc_assert? */
262 if (TREE_CODE (type_out) != VECTOR_TYPE
263 || TREE_CODE (type_in) != VECTOR_TYPE)
264 return NULL_TREE;
265
266 out_mode = TYPE_MODE (TREE_TYPE (type_out));
267 out_n = TYPE_VECTOR_SUBPARTS (type_out);
268 in_mode = TYPE_MODE (TREE_TYPE (type_in));
269 in_n = TYPE_VECTOR_SUBPARTS (type_in);
270
271 enum rs6000_gen_builtins fn
272 = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
273 switch (fn)
274 {
275 case RS6000_BIF_RSQRTF:
276 if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
277 && out_mode == SFmode && out_n == 4
278 && in_mode == SFmode && in_n == 4)
279 return rs6000_builtin_decls[RS6000_BIF_VRSQRTFP];
280 break;
281 case RS6000_BIF_RSQRT:
282 if (VECTOR_UNIT_VSX_P (V2DFmode)
283 && out_mode == DFmode && out_n == 2
284 && in_mode == DFmode && in_n == 2)
285 return rs6000_builtin_decls[RS6000_BIF_RSQRT_2DF];
286 break;
287 case RS6000_BIF_RECIPF:
288 if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
289 && out_mode == SFmode && out_n == 4
290 && in_mode == SFmode && in_n == 4)
291 return rs6000_builtin_decls[RS6000_BIF_VRECIPFP];
292 break;
293 case RS6000_BIF_RECIP:
294 if (VECTOR_UNIT_VSX_P (V2DFmode)
295 && out_mode == DFmode && out_n == 2
296 && in_mode == DFmode && in_n == 2)
297 return rs6000_builtin_decls[RS6000_BIF_RECIP_V2DF];
298 break;
299 default:
300 break;
301 }
302
303 machine_mode in_vmode = TYPE_MODE (type_in);
304 machine_mode out_vmode = TYPE_MODE (type_out);
305
306 /* Power10 supported vectorized built-in functions. */
307 if (TARGET_POWER10
308 && in_vmode == out_vmode
309 && VECTOR_UNIT_ALTIVEC_OR_VSX_P (in_vmode))
310 {
311 machine_mode exp_mode = DImode;
312 machine_mode exp_vmode = V2DImode;
313 enum rs6000_gen_builtins bif;
314 switch (fn)
315 {
316 case RS6000_BIF_DIVWE:
317 case RS6000_BIF_DIVWEU:
318 exp_mode = SImode;
319 exp_vmode = V4SImode;
320 if (fn == RS6000_BIF_DIVWE)
321 bif = RS6000_BIF_VDIVESW;
322 else
323 bif = RS6000_BIF_VDIVEUW;
324 break;
325 case RS6000_BIF_DIVDE:
326 case RS6000_BIF_DIVDEU:
327 if (fn == RS6000_BIF_DIVDE)
328 bif = RS6000_BIF_VDIVESD;
329 else
330 bif = RS6000_BIF_VDIVEUD;
331 break;
332 case RS6000_BIF_CFUGED:
333 bif = RS6000_BIF_VCFUGED;
334 break;
335 case RS6000_BIF_CNTLZDM:
336 bif = RS6000_BIF_VCLZDM;
337 break;
338 case RS6000_BIF_CNTTZDM:
339 bif = RS6000_BIF_VCTZDM;
340 break;
341 case RS6000_BIF_PDEPD:
342 bif = RS6000_BIF_VPDEPD;
343 break;
344 case RS6000_BIF_PEXTD:
345 bif = RS6000_BIF_VPEXTD;
346 break;
347 default:
348 return NULL_TREE;
349 }
350
351 if (in_mode == exp_mode && in_vmode == exp_vmode)
352 return rs6000_builtin_decls[bif];
353 }
354
355 return NULL_TREE;
356 }
357
358 /* Returns a code for a target-specific builtin that implements
359 reciprocal of the function, or NULL_TREE if not available. */
360
361 tree
rs6000_builtin_reciprocal(tree fndecl)362 rs6000_builtin_reciprocal (tree fndecl)
363 {
364 switch (DECL_MD_FUNCTION_CODE (fndecl))
365 {
366 case RS6000_BIF_XVSQRTDP:
367 if (!RS6000_RECIP_AUTO_RSQRTE_P (V2DFmode))
368 return NULL_TREE;
369
370 return rs6000_builtin_decls[RS6000_BIF_RSQRT_2DF];
371
372 case RS6000_BIF_XVSQRTSP:
373 if (!RS6000_RECIP_AUTO_RSQRTE_P (V4SFmode))
374 return NULL_TREE;
375
376 return rs6000_builtin_decls[RS6000_BIF_RSQRT_4SF];
377
378 default:
379 return NULL_TREE;
380 }
381 }
382
383 /* **** Initialization support **** */
384
385 /* Create a builtin vector type with a name. Taking care not to give
386 the canonical type a name. */
387
388 static tree
rs6000_vector_type(const char * name,tree elt_type,unsigned num_elts)389 rs6000_vector_type (const char *name, tree elt_type, unsigned num_elts)
390 {
391 tree result = build_vector_type (elt_type, num_elts);
392
393 /* Copy so we don't give the canonical type a name. */
394 result = build_variant_type_copy (result);
395
396 add_builtin_type (name, result);
397
398 return result;
399 }
400
401 /* Debug utility to translate a type node to a single textual token. */
402 static
rs6000_type_string(tree type_node)403 const char *rs6000_type_string (tree type_node)
404 {
405 if (type_node == NULL_TREE)
406 return "**NULL**";
407 else if (type_node == void_type_node)
408 return "void";
409 else if (type_node == long_integer_type_node)
410 return "long";
411 else if (type_node == long_unsigned_type_node)
412 return "ulong";
413 else if (type_node == long_long_integer_type_node)
414 return "longlong";
415 else if (type_node == long_long_unsigned_type_node)
416 return "ulonglong";
417 else if (type_node == bool_V2DI_type_node)
418 return "vbll";
419 else if (type_node == bool_V4SI_type_node)
420 return "vbi";
421 else if (type_node == bool_V8HI_type_node)
422 return "vbs";
423 else if (type_node == bool_V16QI_type_node)
424 return "vbc";
425 else if (type_node == bool_int_type_node)
426 return "bool";
427 else if (type_node == dfloat64_type_node)
428 return "_Decimal64";
429 else if (type_node == double_type_node)
430 return "double";
431 else if (type_node == intDI_type_node)
432 return "sll";
433 else if (type_node == intHI_type_node)
434 return "ss";
435 else if (type_node == ibm128_float_type_node)
436 return "__ibm128";
437 else if (type_node == ieee128_float_type_node)
438 return "__ieee128";
439 else if (type_node == opaque_V4SI_type_node)
440 return "opaque";
441 else if (POINTER_TYPE_P (type_node))
442 return "void*";
443 else if (type_node == intQI_type_node || type_node == char_type_node)
444 return "sc";
445 else if (type_node == dfloat32_type_node)
446 return "_Decimal32";
447 else if (type_node == float_type_node)
448 return "float";
449 else if (type_node == intSI_type_node || type_node == integer_type_node)
450 return "si";
451 else if (type_node == dfloat128_type_node)
452 return "_Decimal128";
453 else if (type_node == long_double_type_node)
454 return "longdouble";
455 else if (type_node == intTI_type_node)
456 return "sq";
457 else if (type_node == unsigned_intDI_type_node)
458 return "ull";
459 else if (type_node == unsigned_intHI_type_node)
460 return "us";
461 else if (type_node == unsigned_intQI_type_node)
462 return "uc";
463 else if (type_node == unsigned_intSI_type_node)
464 return "ui";
465 else if (type_node == unsigned_intTI_type_node)
466 return "uq";
467 else if (type_node == unsigned_V1TI_type_node)
468 return "vuq";
469 else if (type_node == unsigned_V2DI_type_node)
470 return "vull";
471 else if (type_node == unsigned_V4SI_type_node)
472 return "vui";
473 else if (type_node == unsigned_V8HI_type_node)
474 return "vus";
475 else if (type_node == unsigned_V16QI_type_node)
476 return "vuc";
477 else if (type_node == V16QI_type_node)
478 return "vsc";
479 else if (type_node == V1TI_type_node)
480 return "vsq";
481 else if (type_node == V2DF_type_node)
482 return "vd";
483 else if (type_node == V2DI_type_node)
484 return "vsll";
485 else if (type_node == V4SF_type_node)
486 return "vf";
487 else if (type_node == V4SI_type_node)
488 return "vsi";
489 else if (type_node == V8HI_type_node)
490 return "vss";
491 else if (type_node == pixel_V8HI_type_node)
492 return "vp";
493 else if (type_node == pcvoid_type_node)
494 return "voidc*";
495 else if (type_node == float128_type_node)
496 return "_Float128";
497 else if (type_node == vector_pair_type_node)
498 return "__vector_pair";
499 else if (type_node == vector_quad_type_node)
500 return "__vector_quad";
501
502 return "unknown";
503 }
504
505 void
rs6000_init_builtins(void)506 rs6000_init_builtins (void)
507 {
508 tree tdecl;
509 tree t;
510
511 if (TARGET_DEBUG_BUILTIN)
512 fprintf (stderr, "rs6000_init_builtins%s%s\n",
513 (TARGET_ALTIVEC) ? ", altivec" : "",
514 (TARGET_VSX) ? ", vsx" : "");
515
516 V2DI_type_node = rs6000_vector_type ("__vector long long",
517 long_long_integer_type_node, 2);
518 ptr_V2DI_type_node
519 = build_pointer_type (build_qualified_type (V2DI_type_node,
520 TYPE_QUAL_CONST));
521
522 V2DF_type_node = rs6000_vector_type ("__vector double", double_type_node, 2);
523 ptr_V2DF_type_node
524 = build_pointer_type (build_qualified_type (V2DF_type_node,
525 TYPE_QUAL_CONST));
526
527 V4SI_type_node = rs6000_vector_type ("__vector signed int",
528 intSI_type_node, 4);
529 ptr_V4SI_type_node
530 = build_pointer_type (build_qualified_type (V4SI_type_node,
531 TYPE_QUAL_CONST));
532
533 V4SF_type_node = rs6000_vector_type ("__vector float", float_type_node, 4);
534 ptr_V4SF_type_node
535 = build_pointer_type (build_qualified_type (V4SF_type_node,
536 TYPE_QUAL_CONST));
537
538 V8HI_type_node = rs6000_vector_type ("__vector signed short",
539 intHI_type_node, 8);
540 ptr_V8HI_type_node
541 = build_pointer_type (build_qualified_type (V8HI_type_node,
542 TYPE_QUAL_CONST));
543
544 V16QI_type_node = rs6000_vector_type ("__vector signed char",
545 intQI_type_node, 16);
546 ptr_V16QI_type_node
547 = build_pointer_type (build_qualified_type (V16QI_type_node,
548 TYPE_QUAL_CONST));
549
550 unsigned_V16QI_type_node = rs6000_vector_type ("__vector unsigned char",
551 unsigned_intQI_type_node, 16);
552 ptr_unsigned_V16QI_type_node
553 = build_pointer_type (build_qualified_type (unsigned_V16QI_type_node,
554 TYPE_QUAL_CONST));
555
556 unsigned_V8HI_type_node = rs6000_vector_type ("__vector unsigned short",
557 unsigned_intHI_type_node, 8);
558 ptr_unsigned_V8HI_type_node
559 = build_pointer_type (build_qualified_type (unsigned_V8HI_type_node,
560 TYPE_QUAL_CONST));
561
562 unsigned_V4SI_type_node = rs6000_vector_type ("__vector unsigned int",
563 unsigned_intSI_type_node, 4);
564 ptr_unsigned_V4SI_type_node
565 = build_pointer_type (build_qualified_type (unsigned_V4SI_type_node,
566 TYPE_QUAL_CONST));
567
568 unsigned_V2DI_type_node
569 = rs6000_vector_type ("__vector unsigned long long",
570 long_long_unsigned_type_node, 2);
571
572 ptr_unsigned_V2DI_type_node
573 = build_pointer_type (build_qualified_type (unsigned_V2DI_type_node,
574 TYPE_QUAL_CONST));
575
576 opaque_V4SI_type_node = build_opaque_vector_type (intSI_type_node, 4);
577
578 const_str_type_node
579 = build_pointer_type (build_qualified_type (char_type_node,
580 TYPE_QUAL_CONST));
581
582 /* We use V1TI mode as a special container to hold __int128_t items that
583 must live in VSX registers. */
584 if (intTI_type_node)
585 {
586 V1TI_type_node = rs6000_vector_type ("__vector __int128",
587 intTI_type_node, 1);
588 ptr_V1TI_type_node
589 = build_pointer_type (build_qualified_type (V1TI_type_node,
590 TYPE_QUAL_CONST));
591 unsigned_V1TI_type_node
592 = rs6000_vector_type ("__vector unsigned __int128",
593 unsigned_intTI_type_node, 1);
594 ptr_unsigned_V1TI_type_node
595 = build_pointer_type (build_qualified_type (unsigned_V1TI_type_node,
596 TYPE_QUAL_CONST));
597 }
598
599 /* The 'vector bool ...' types must be kept distinct from 'vector unsigned ...'
600 types, especially in C++ land. Similarly, 'vector pixel' is distinct from
601 'vector unsigned short'. */
602
603 bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
604 bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
605 bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
606 bool_long_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node);
607 pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
608
609 long_integer_type_internal_node = long_integer_type_node;
610 long_unsigned_type_internal_node = long_unsigned_type_node;
611 long_long_integer_type_internal_node = long_long_integer_type_node;
612 long_long_unsigned_type_internal_node = long_long_unsigned_type_node;
613 intQI_type_internal_node = intQI_type_node;
614 uintQI_type_internal_node = unsigned_intQI_type_node;
615 intHI_type_internal_node = intHI_type_node;
616 uintHI_type_internal_node = unsigned_intHI_type_node;
617 intSI_type_internal_node = intSI_type_node;
618 uintSI_type_internal_node = unsigned_intSI_type_node;
619 intDI_type_internal_node = intDI_type_node;
620 uintDI_type_internal_node = unsigned_intDI_type_node;
621 intTI_type_internal_node = intTI_type_node;
622 uintTI_type_internal_node = unsigned_intTI_type_node;
623 float_type_internal_node = float_type_node;
624 double_type_internal_node = double_type_node;
625 long_double_type_internal_node = long_double_type_node;
626 dfloat64_type_internal_node = dfloat64_type_node;
627 dfloat128_type_internal_node = dfloat128_type_node;
628 void_type_internal_node = void_type_node;
629
630 ptr_intQI_type_node
631 = build_pointer_type (build_qualified_type (intQI_type_internal_node,
632 TYPE_QUAL_CONST));
633 ptr_uintQI_type_node
634 = build_pointer_type (build_qualified_type (uintQI_type_internal_node,
635 TYPE_QUAL_CONST));
636 ptr_intHI_type_node
637 = build_pointer_type (build_qualified_type (intHI_type_internal_node,
638 TYPE_QUAL_CONST));
639 ptr_uintHI_type_node
640 = build_pointer_type (build_qualified_type (uintHI_type_internal_node,
641 TYPE_QUAL_CONST));
642 ptr_intSI_type_node
643 = build_pointer_type (build_qualified_type (intSI_type_internal_node,
644 TYPE_QUAL_CONST));
645 ptr_uintSI_type_node
646 = build_pointer_type (build_qualified_type (uintSI_type_internal_node,
647 TYPE_QUAL_CONST));
648 ptr_intDI_type_node
649 = build_pointer_type (build_qualified_type (intDI_type_internal_node,
650 TYPE_QUAL_CONST));
651 ptr_uintDI_type_node
652 = build_pointer_type (build_qualified_type (uintDI_type_internal_node,
653 TYPE_QUAL_CONST));
654 ptr_intTI_type_node
655 = build_pointer_type (build_qualified_type (intTI_type_internal_node,
656 TYPE_QUAL_CONST));
657 ptr_uintTI_type_node
658 = build_pointer_type (build_qualified_type (uintTI_type_internal_node,
659 TYPE_QUAL_CONST));
660
661 t = build_qualified_type (long_integer_type_internal_node, TYPE_QUAL_CONST);
662 ptr_long_integer_type_node = build_pointer_type (t);
663
664 t = build_qualified_type (long_unsigned_type_internal_node, TYPE_QUAL_CONST);
665 ptr_long_unsigned_type_node = build_pointer_type (t);
666
667 ptr_float_type_node
668 = build_pointer_type (build_qualified_type (float_type_internal_node,
669 TYPE_QUAL_CONST));
670 ptr_double_type_node
671 = build_pointer_type (build_qualified_type (double_type_internal_node,
672 TYPE_QUAL_CONST));
673 ptr_long_double_type_node
674 = build_pointer_type (build_qualified_type (long_double_type_internal_node,
675 TYPE_QUAL_CONST));
676 if (dfloat64_type_node)
677 {
678 t = build_qualified_type (dfloat64_type_internal_node, TYPE_QUAL_CONST);
679 ptr_dfloat64_type_node = build_pointer_type (t);
680 }
681 else
682 ptr_dfloat64_type_node = NULL;
683
684 if (dfloat128_type_node)
685 {
686 t = build_qualified_type (dfloat128_type_internal_node, TYPE_QUAL_CONST);
687 ptr_dfloat128_type_node = build_pointer_type (t);
688 }
689 else
690 ptr_dfloat128_type_node = NULL;
691
692 t = build_qualified_type (long_long_integer_type_internal_node,
693 TYPE_QUAL_CONST);
694 ptr_long_long_integer_type_node = build_pointer_type (t);
695
696 t = build_qualified_type (long_long_unsigned_type_internal_node,
697 TYPE_QUAL_CONST);
698 ptr_long_long_unsigned_type_node = build_pointer_type (t);
699
700 /* 128-bit floating point support. KFmode is IEEE 128-bit floating point.
701 IFmode is the IBM extended 128-bit format that is a pair of doubles.
702 TFmode will be either IEEE 128-bit floating point or the IBM double-double
703 format that uses a pair of doubles, depending on the switches and
704 defaults.
705
706 If we don't support for either 128-bit IBM double double or IEEE 128-bit
707 floating point, we need make sure the type is non-zero or else self-test
708 fails during bootstrap.
709
710 Always create __ibm128 as a separate type, even if the current long double
711 format is IBM extended double.
712
713 For IEEE 128-bit floating point, always create the type __ieee128. If the
714 user used -mfloat128, rs6000-c.cc will create a define from __float128 to
715 __ieee128. */
716 if (TARGET_LONG_DOUBLE_128 && (!TARGET_IEEEQUAD || TARGET_FLOAT128_TYPE))
717 {
718 if (!TARGET_IEEEQUAD)
719 ibm128_float_type_node = long_double_type_node;
720 else
721 {
722 ibm128_float_type_node = make_node (REAL_TYPE);
723 TYPE_PRECISION (ibm128_float_type_node) = 128;
724 SET_TYPE_MODE (ibm128_float_type_node, IFmode);
725 layout_type (ibm128_float_type_node);
726 }
727 t = build_qualified_type (ibm128_float_type_node, TYPE_QUAL_CONST);
728 lang_hooks.types.register_builtin_type (ibm128_float_type_node,
729 "__ibm128");
730 }
731 else
732 ibm128_float_type_node = NULL_TREE;
733
734 if (TARGET_FLOAT128_TYPE)
735 {
736 if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
737 ieee128_float_type_node = long_double_type_node;
738 else
739 ieee128_float_type_node = float128_type_node;
740 t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST);
741 lang_hooks.types.register_builtin_type (ieee128_float_type_node,
742 "__ieee128");
743 }
744 else
745 ieee128_float_type_node = NULL_TREE;
746
747 /* Vector pair and vector quad support. */
748 vector_pair_type_node = make_node (OPAQUE_TYPE);
749 SET_TYPE_MODE (vector_pair_type_node, OOmode);
750 TYPE_SIZE (vector_pair_type_node) = bitsize_int (GET_MODE_BITSIZE (OOmode));
751 TYPE_PRECISION (vector_pair_type_node) = GET_MODE_BITSIZE (OOmode);
752 TYPE_SIZE_UNIT (vector_pair_type_node) = size_int (GET_MODE_SIZE (OOmode));
753 SET_TYPE_ALIGN (vector_pair_type_node, 256);
754 TYPE_USER_ALIGN (vector_pair_type_node) = 0;
755 lang_hooks.types.register_builtin_type (vector_pair_type_node,
756 "__vector_pair");
757 t = build_qualified_type (vector_pair_type_node, TYPE_QUAL_CONST);
758 ptr_vector_pair_type_node = build_pointer_type (t);
759
760 vector_quad_type_node = make_node (OPAQUE_TYPE);
761 SET_TYPE_MODE (vector_quad_type_node, XOmode);
762 TYPE_SIZE (vector_quad_type_node) = bitsize_int (GET_MODE_BITSIZE (XOmode));
763 TYPE_PRECISION (vector_quad_type_node) = GET_MODE_BITSIZE (XOmode);
764 TYPE_SIZE_UNIT (vector_quad_type_node) = size_int (GET_MODE_SIZE (XOmode));
765 SET_TYPE_ALIGN (vector_quad_type_node, 512);
766 TYPE_USER_ALIGN (vector_quad_type_node) = 0;
767 lang_hooks.types.register_builtin_type (vector_quad_type_node,
768 "__vector_quad");
769 t = build_qualified_type (vector_quad_type_node, TYPE_QUAL_CONST);
770 ptr_vector_quad_type_node = build_pointer_type (t);
771
772 tdecl = add_builtin_type ("__bool char", bool_char_type_node);
773 TYPE_NAME (bool_char_type_node) = tdecl;
774
775 tdecl = add_builtin_type ("__bool short", bool_short_type_node);
776 TYPE_NAME (bool_short_type_node) = tdecl;
777
778 tdecl = add_builtin_type ("__bool int", bool_int_type_node);
779 TYPE_NAME (bool_int_type_node) = tdecl;
780
781 tdecl = add_builtin_type ("__pixel", pixel_type_node);
782 TYPE_NAME (pixel_type_node) = tdecl;
783
784 bool_V16QI_type_node = rs6000_vector_type ("__vector __bool char",
785 bool_char_type_node, 16);
786 ptr_bool_V16QI_type_node
787 = build_pointer_type (build_qualified_type (bool_V16QI_type_node,
788 TYPE_QUAL_CONST));
789
790 bool_V8HI_type_node = rs6000_vector_type ("__vector __bool short",
791 bool_short_type_node, 8);
792 ptr_bool_V8HI_type_node
793 = build_pointer_type (build_qualified_type (bool_V8HI_type_node,
794 TYPE_QUAL_CONST));
795
796 bool_V4SI_type_node = rs6000_vector_type ("__vector __bool int",
797 bool_int_type_node, 4);
798 ptr_bool_V4SI_type_node
799 = build_pointer_type (build_qualified_type (bool_V4SI_type_node,
800 TYPE_QUAL_CONST));
801
802 bool_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64
803 ? "__vector __bool long"
804 : "__vector __bool long long",
805 bool_long_long_type_node, 2);
806 ptr_bool_V2DI_type_node
807 = build_pointer_type (build_qualified_type (bool_V2DI_type_node,
808 TYPE_QUAL_CONST));
809
810 bool_V1TI_type_node = rs6000_vector_type ("__vector __bool __int128",
811 intTI_type_node, 1);
812 ptr_bool_V1TI_type_node
813 = build_pointer_type (build_qualified_type (bool_V1TI_type_node,
814 TYPE_QUAL_CONST));
815
816 pixel_V8HI_type_node = rs6000_vector_type ("__vector __pixel",
817 pixel_type_node, 8);
818 ptr_pixel_V8HI_type_node
819 = build_pointer_type (build_qualified_type (pixel_V8HI_type_node,
820 TYPE_QUAL_CONST));
821 pcvoid_type_node
822 = build_pointer_type (build_qualified_type (void_type_node,
823 TYPE_QUAL_CONST));
824
825 /* Execute the autogenerated initialization code for builtins. */
826 rs6000_init_generated_builtins ();
827
828 if (TARGET_DEBUG_BUILTIN)
829 {
830 fprintf (stderr, "\nAutogenerated built-in functions:\n\n");
831 for (int i = 1; i < (int) RS6000_BIF_MAX; i++)
832 {
833 bif_enable e = rs6000_builtin_info[i].enable;
834 if (e == ENB_P5 && !TARGET_POPCNTB)
835 continue;
836 if (e == ENB_P6 && !TARGET_CMPB)
837 continue;
838 if (e == ENB_P6_64 && !(TARGET_CMPB && TARGET_POWERPC64))
839 continue;
840 if (e == ENB_ALTIVEC && !TARGET_ALTIVEC)
841 continue;
842 if (e == ENB_VSX && !TARGET_VSX)
843 continue;
844 if (e == ENB_P7 && !TARGET_POPCNTD)
845 continue;
846 if (e == ENB_P7_64 && !(TARGET_POPCNTD && TARGET_POWERPC64))
847 continue;
848 if (e == ENB_P8 && !TARGET_DIRECT_MOVE)
849 continue;
850 if (e == ENB_P8V && !TARGET_P8_VECTOR)
851 continue;
852 if (e == ENB_P9 && !TARGET_MODULO)
853 continue;
854 if (e == ENB_P9_64 && !(TARGET_MODULO && TARGET_POWERPC64))
855 continue;
856 if (e == ENB_P9V && !TARGET_P9_VECTOR)
857 continue;
858 if (e == ENB_IEEE128_HW && !TARGET_FLOAT128_HW)
859 continue;
860 if (e == ENB_DFP && !TARGET_DFP)
861 continue;
862 if (e == ENB_CRYPTO && !TARGET_CRYPTO)
863 continue;
864 if (e == ENB_HTM && !TARGET_HTM)
865 continue;
866 if (e == ENB_P10 && !TARGET_POWER10)
867 continue;
868 if (e == ENB_P10_64 && !(TARGET_POWER10 && TARGET_POWERPC64))
869 continue;
870 if (e == ENB_MMA && !TARGET_MMA)
871 continue;
872 tree fntype = rs6000_builtin_info_fntype[i];
873 tree t = TREE_TYPE (fntype);
874 fprintf (stderr, "%s %s (", rs6000_type_string (t),
875 rs6000_builtin_info[i].bifname);
876 t = TYPE_ARG_TYPES (fntype);
877 while (t && TREE_VALUE (t) != void_type_node)
878 {
879 fprintf (stderr, "%s",
880 rs6000_type_string (TREE_VALUE (t)));
881 t = TREE_CHAIN (t);
882 if (t && TREE_VALUE (t) != void_type_node)
883 fprintf (stderr, ", ");
884 }
885 fprintf (stderr, "); %s [%4d]\n",
886 rs6000_builtin_info[i].attr_string, (int) i);
887 }
888 fprintf (stderr, "\nEnd autogenerated built-in functions.\n\n\n");
889 }
890
891 if (TARGET_XCOFF)
892 {
893 /* AIX libm provides clog as __clog. */
894 if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
895 set_user_assembler_name (tdecl, "__clog");
896
897 /* When long double is 64 bit, some long double builtins of libc
898 functions (like __builtin_frexpl) must call the double version
899 (frexp) not the long double version (frexpl) that expects a 128 bit
900 argument. */
901 if (! TARGET_LONG_DOUBLE_128)
902 {
903 if ((tdecl = builtin_decl_explicit (BUILT_IN_FMODL)) != NULL_TREE)
904 set_user_assembler_name (tdecl, "fmod");
905 if ((tdecl = builtin_decl_explicit (BUILT_IN_FREXPL)) != NULL_TREE)
906 set_user_assembler_name (tdecl, "frexp");
907 if ((tdecl = builtin_decl_explicit (BUILT_IN_LDEXPL)) != NULL_TREE)
908 set_user_assembler_name (tdecl, "ldexp");
909 if ((tdecl = builtin_decl_explicit (BUILT_IN_MODFL)) != NULL_TREE)
910 set_user_assembler_name (tdecl, "modf");
911 }
912 }
913
914 altivec_builtin_mask_for_load
915 = rs6000_builtin_decls[RS6000_BIF_MASK_FOR_LOAD];
916
917 #ifdef SUBTARGET_INIT_BUILTINS
918 SUBTARGET_INIT_BUILTINS;
919 #endif
920
921 return;
922 }
923
924 /* **** GIMPLE folding support **** */
925
926 /* Helper function to handle the gimple folding of a vector compare
927 operation. This sets up true/false vectors, and uses the
928 VEC_COND_EXPR operation.
929 CODE indicates which comparison is to be made. (EQ, GT, ...).
930 TYPE indicates the type of the result.
931 Code is inserted before GSI. */
932 static tree
fold_build_vec_cmp(tree_code code,tree type,tree arg0,tree arg1,gimple_stmt_iterator * gsi)933 fold_build_vec_cmp (tree_code code, tree type, tree arg0, tree arg1,
934 gimple_stmt_iterator *gsi)
935 {
936 tree cmp_type = truth_type_for (type);
937 tree zero_vec = build_zero_cst (type);
938 tree minus_one_vec = build_minus_one_cst (type);
939 tree temp = create_tmp_reg_or_ssa_name (cmp_type);
940 gimple *g = gimple_build_assign (temp, code, arg0, arg1);
941 gsi_insert_before (gsi, g, GSI_SAME_STMT);
942 return fold_build3 (VEC_COND_EXPR, type, temp, minus_one_vec, zero_vec);
943 }
944
945 /* Helper function to handle the in-between steps for the
946 vector compare built-ins. */
947 static void
fold_compare_helper(gimple_stmt_iterator * gsi,tree_code code,gimple * stmt)948 fold_compare_helper (gimple_stmt_iterator *gsi, tree_code code, gimple *stmt)
949 {
950 tree arg0 = gimple_call_arg (stmt, 0);
951 tree arg1 = gimple_call_arg (stmt, 1);
952 tree lhs = gimple_call_lhs (stmt);
953 tree cmp = fold_build_vec_cmp (code, TREE_TYPE (lhs), arg0, arg1, gsi);
954 gimple *g = gimple_build_assign (lhs, cmp);
955 gimple_set_location (g, gimple_location (stmt));
956 gsi_replace (gsi, g, true);
957 }
958
959 /* Helper function to map V2DF and V4SF types to their
960 integral equivalents (V2DI and V4SI). */
map_to_integral_tree_type(tree input_tree_type)961 tree map_to_integral_tree_type (tree input_tree_type)
962 {
963 if (INTEGRAL_TYPE_P (TREE_TYPE (input_tree_type)))
964 return input_tree_type;
965 else
966 {
967 if (types_compatible_p (TREE_TYPE (input_tree_type),
968 TREE_TYPE (V2DF_type_node)))
969 return V2DI_type_node;
970 else if (types_compatible_p (TREE_TYPE (input_tree_type),
971 TREE_TYPE (V4SF_type_node)))
972 return V4SI_type_node;
973 else
974 gcc_unreachable ();
975 }
976 }
977
978 /* Helper function to handle the vector merge[hl] built-ins. The
979 implementation difference between h and l versions for this code are in
980 the values used when building of the permute vector for high word versus
981 low word merge. The variance is keyed off the use_high parameter. */
982 static void
fold_mergehl_helper(gimple_stmt_iterator * gsi,gimple * stmt,int use_high)983 fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high)
984 {
985 tree arg0 = gimple_call_arg (stmt, 0);
986 tree arg1 = gimple_call_arg (stmt, 1);
987 tree lhs = gimple_call_lhs (stmt);
988 tree lhs_type = TREE_TYPE (lhs);
989 int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type);
990 int midpoint = n_elts / 2;
991 int offset = 0;
992
993 if (use_high == 1)
994 offset = midpoint;
995
996 /* The permute_type will match the lhs for integral types. For double and
997 float types, the permute type needs to map to the V2 or V4 type that
998 matches size. */
999 tree permute_type;
1000 permute_type = map_to_integral_tree_type (lhs_type);
1001 tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1);
1002
1003 for (int i = 0; i < midpoint; i++)
1004 {
1005 elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
1006 offset + i));
1007 elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
1008 offset + n_elts + i));
1009 }
1010
1011 tree permute = elts.build ();
1012
1013 gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute);
1014 gimple_set_location (g, gimple_location (stmt));
1015 gsi_replace (gsi, g, true);
1016 }
1017
1018 /* Helper function to handle the vector merge[eo] built-ins. */
1019 static void
fold_mergeeo_helper(gimple_stmt_iterator * gsi,gimple * stmt,int use_odd)1020 fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd)
1021 {
1022 tree arg0 = gimple_call_arg (stmt, 0);
1023 tree arg1 = gimple_call_arg (stmt, 1);
1024 tree lhs = gimple_call_lhs (stmt);
1025 tree lhs_type = TREE_TYPE (lhs);
1026 int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type);
1027
1028 /* The permute_type will match the lhs for integral types. For double and
1029 float types, the permute type needs to map to the V2 or V4 type that
1030 matches size. */
1031 tree permute_type;
1032 permute_type = map_to_integral_tree_type (lhs_type);
1033
1034 tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1);
1035
1036 /* Build the permute vector. */
1037 for (int i = 0; i < n_elts / 2; i++)
1038 {
1039 elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
1040 2*i + use_odd));
1041 elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
1042 2*i + use_odd + n_elts));
1043 }
1044
1045 tree permute = elts.build ();
1046
1047 gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute);
1048 gimple_set_location (g, gimple_location (stmt));
1049 gsi_replace (gsi, g, true);
1050 }
1051
1052 /* Helper function to sort out which built-ins may be valid without having
1053 a LHS. */
1054 static bool
rs6000_builtin_valid_without_lhs(enum rs6000_gen_builtins fn_code,tree fndecl)1055 rs6000_builtin_valid_without_lhs (enum rs6000_gen_builtins fn_code,
1056 tree fndecl)
1057 {
1058 if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
1059 return true;
1060
1061 switch (fn_code)
1062 {
1063 case RS6000_BIF_STVX_V16QI:
1064 case RS6000_BIF_STVX_V8HI:
1065 case RS6000_BIF_STVX_V4SI:
1066 case RS6000_BIF_STVX_V4SF:
1067 case RS6000_BIF_STVX_V2DI:
1068 case RS6000_BIF_STVX_V2DF:
1069 case RS6000_BIF_STXVW4X_V16QI:
1070 case RS6000_BIF_STXVW4X_V8HI:
1071 case RS6000_BIF_STXVW4X_V4SF:
1072 case RS6000_BIF_STXVW4X_V4SI:
1073 case RS6000_BIF_STXVD2X_V2DF:
1074 case RS6000_BIF_STXVD2X_V2DI:
1075 return true;
1076 default:
1077 return false;
1078 }
1079 }
1080
1081 /* Expand the MMA built-ins early, so that we can convert the pass-by-reference
1082 __vector_quad arguments into pass-by-value arguments, leading to more
1083 efficient code generation. */
1084 static bool
rs6000_gimple_fold_mma_builtin(gimple_stmt_iterator * gsi,rs6000_gen_builtins fn_code)1085 rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
1086 rs6000_gen_builtins fn_code)
1087 {
1088 gimple *stmt = gsi_stmt (*gsi);
1089 size_t fncode = (size_t) fn_code;
1090
1091 if (!bif_is_mma (rs6000_builtin_info[fncode]))
1092 return false;
1093
1094 /* Each call that can be gimple-expanded has an associated built-in
1095 function that it will expand into. If this one doesn't, we have
1096 already expanded it! Exceptions: lxvp and stxvp. */
1097 if (rs6000_builtin_info[fncode].assoc_bif == RS6000_BIF_NONE
1098 && fncode != RS6000_BIF_LXVP
1099 && fncode != RS6000_BIF_STXVP)
1100 return false;
1101
1102 bifdata *bd = &rs6000_builtin_info[fncode];
1103 unsigned nopnds = bd->nargs;
1104 gimple_seq new_seq = NULL;
1105 gimple *new_call;
1106 tree new_decl;
1107
1108 /* Compatibility built-ins; we used to call these
1109 __builtin_mma_{dis,}assemble_pair, but now we call them
1110 __builtin_vsx_{dis,}assemble_pair. Handle the old versions. */
1111 if (fncode == RS6000_BIF_ASSEMBLE_PAIR)
1112 fncode = RS6000_BIF_ASSEMBLE_PAIR_V;
1113 else if (fncode == RS6000_BIF_DISASSEMBLE_PAIR)
1114 fncode = RS6000_BIF_DISASSEMBLE_PAIR_V;
1115
1116 if (fncode == RS6000_BIF_DISASSEMBLE_ACC
1117 || fncode == RS6000_BIF_DISASSEMBLE_PAIR_V)
1118 {
1119 /* This is an MMA disassemble built-in function. */
1120 push_gimplify_context (true);
1121 unsigned nvec = (fncode == RS6000_BIF_DISASSEMBLE_ACC) ? 4 : 2;
1122 tree dst_ptr = gimple_call_arg (stmt, 0);
1123 tree src_ptr = gimple_call_arg (stmt, 1);
1124 tree src_type = (fncode == RS6000_BIF_DISASSEMBLE_ACC)
1125 ? build_pointer_type (vector_quad_type_node)
1126 : build_pointer_type (vector_pair_type_node);
1127 if (TREE_TYPE (src_ptr) != src_type)
1128 src_ptr = build1 (NOP_EXPR, src_type, src_ptr);
1129
1130 tree src = create_tmp_reg_or_ssa_name (TREE_TYPE (src_type));
1131 gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq);
1132
1133 /* If we are not disassembling an accumulator/pair or our destination is
1134 another accumulator/pair, then just copy the entire thing as is. */
1135 if ((fncode == RS6000_BIF_DISASSEMBLE_ACC
1136 && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_quad_type_node)
1137 || (fncode == RS6000_BIF_DISASSEMBLE_PAIR_V
1138 && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_pair_type_node))
1139 {
1140 tree dst = build_simple_mem_ref (build1 (VIEW_CONVERT_EXPR,
1141 src_type, dst_ptr));
1142 gimplify_assign (dst, src, &new_seq);
1143 pop_gimplify_context (NULL);
1144 gsi_replace_with_seq (gsi, new_seq, true);
1145 return true;
1146 }
1147
1148 /* If we're disassembling an accumulator into a different type, we need
1149 to emit a xxmfacc instruction now, since we cannot do it later. */
1150 if (fncode == RS6000_BIF_DISASSEMBLE_ACC)
1151 {
1152 new_decl = rs6000_builtin_decls[RS6000_BIF_XXMFACC_INTERNAL];
1153 new_call = gimple_build_call (new_decl, 1, src);
1154 src = create_tmp_reg_or_ssa_name (vector_quad_type_node);
1155 gimple_call_set_lhs (new_call, src);
1156 gimple_seq_add_stmt (&new_seq, new_call);
1157 }
1158
1159 /* Copy the accumulator/pair vector by vector. */
1160 new_decl
1161 = rs6000_builtin_decls[rs6000_builtin_info[fncode].assoc_bif];
1162 tree dst_type = build_pointer_type_for_mode (unsigned_V16QI_type_node,
1163 ptr_mode, true);
1164 tree dst_base = build1 (VIEW_CONVERT_EXPR, dst_type, dst_ptr);
1165 for (unsigned i = 0; i < nvec; i++)
1166 {
1167 unsigned index = WORDS_BIG_ENDIAN ? i : nvec - 1 - i;
1168 tree dst = build2 (MEM_REF, unsigned_V16QI_type_node, dst_base,
1169 build_int_cst (dst_type, index * 16));
1170 tree dstssa = create_tmp_reg_or_ssa_name (unsigned_V16QI_type_node);
1171 new_call = gimple_build_call (new_decl, 2, src,
1172 build_int_cstu (uint16_type_node, i));
1173 gimple_call_set_lhs (new_call, dstssa);
1174 gimple_seq_add_stmt (&new_seq, new_call);
1175 gimplify_assign (dst, dstssa, &new_seq);
1176 }
1177 pop_gimplify_context (NULL);
1178 gsi_replace_with_seq (gsi, new_seq, true);
1179 return true;
1180 }
1181
1182 /* TODO: Do some factoring on these two chunks. */
1183 if (fncode == RS6000_BIF_LXVP)
1184 {
1185 push_gimplify_context (true);
1186 tree offset = gimple_call_arg (stmt, 0);
1187 tree ptr = gimple_call_arg (stmt, 1);
1188 tree lhs = gimple_call_lhs (stmt);
1189 if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node)
1190 ptr = build1 (VIEW_CONVERT_EXPR,
1191 build_pointer_type (vector_pair_type_node), ptr);
1192 tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR,
1193 TREE_TYPE (ptr), ptr, offset));
1194 gimplify_assign (lhs, mem, &new_seq);
1195 pop_gimplify_context (NULL);
1196 gsi_replace_with_seq (gsi, new_seq, true);
1197 return true;
1198 }
1199
1200 if (fncode == RS6000_BIF_STXVP)
1201 {
1202 push_gimplify_context (true);
1203 tree src = gimple_call_arg (stmt, 0);
1204 tree offset = gimple_call_arg (stmt, 1);
1205 tree ptr = gimple_call_arg (stmt, 2);
1206 if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node)
1207 ptr = build1 (VIEW_CONVERT_EXPR,
1208 build_pointer_type (vector_pair_type_node), ptr);
1209 tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR,
1210 TREE_TYPE (ptr), ptr, offset));
1211 gimplify_assign (mem, src, &new_seq);
1212 pop_gimplify_context (NULL);
1213 gsi_replace_with_seq (gsi, new_seq, true);
1214 return true;
1215 }
1216
1217 /* Convert this built-in into an internal version that uses pass-by-value
1218 arguments. The internal built-in is found in the assoc_bif field. */
1219 new_decl = rs6000_builtin_decls[rs6000_builtin_info[fncode].assoc_bif];
1220 tree lhs, op[MAX_MMA_OPERANDS];
1221 tree acc = gimple_call_arg (stmt, 0);
1222 push_gimplify_context (true);
1223
1224 if (bif_is_quad (*bd))
1225 {
1226 /* This built-in has a pass-by-reference accumulator input, so load it
1227 into a temporary accumulator for use as a pass-by-value input. */
1228 op[0] = create_tmp_reg_or_ssa_name (vector_quad_type_node);
1229 for (unsigned i = 1; i < nopnds; i++)
1230 op[i] = gimple_call_arg (stmt, i);
1231 gimplify_assign (op[0], build_simple_mem_ref (acc), &new_seq);
1232 }
1233 else
1234 {
1235 /* This built-in does not use its pass-by-reference accumulator argument
1236 as an input argument, so remove it from the input list. */
1237 nopnds--;
1238 for (unsigned i = 0; i < nopnds; i++)
1239 op[i] = gimple_call_arg (stmt, i + 1);
1240 }
1241
1242 switch (nopnds)
1243 {
1244 case 0:
1245 new_call = gimple_build_call (new_decl, 0);
1246 break;
1247 case 1:
1248 new_call = gimple_build_call (new_decl, 1, op[0]);
1249 break;
1250 case 2:
1251 new_call = gimple_build_call (new_decl, 2, op[0], op[1]);
1252 break;
1253 case 3:
1254 new_call = gimple_build_call (new_decl, 3, op[0], op[1], op[2]);
1255 break;
1256 case 4:
1257 new_call = gimple_build_call (new_decl, 4, op[0], op[1], op[2], op[3]);
1258 break;
1259 case 5:
1260 new_call = gimple_build_call (new_decl, 5, op[0], op[1], op[2], op[3],
1261 op[4]);
1262 break;
1263 case 6:
1264 new_call = gimple_build_call (new_decl, 6, op[0], op[1], op[2], op[3],
1265 op[4], op[5]);
1266 break;
1267 case 7:
1268 new_call = gimple_build_call (new_decl, 7, op[0], op[1], op[2], op[3],
1269 op[4], op[5], op[6]);
1270 break;
1271 default:
1272 gcc_unreachable ();
1273 }
1274
1275 if (fncode == RS6000_BIF_BUILD_PAIR || fncode == RS6000_BIF_ASSEMBLE_PAIR_V)
1276 lhs = create_tmp_reg_or_ssa_name (vector_pair_type_node);
1277 else
1278 lhs = create_tmp_reg_or_ssa_name (vector_quad_type_node);
1279 gimple_call_set_lhs (new_call, lhs);
1280 gimple_seq_add_stmt (&new_seq, new_call);
1281 gimplify_assign (build_simple_mem_ref (acc), lhs, &new_seq);
1282 pop_gimplify_context (NULL);
1283 gsi_replace_with_seq (gsi, new_seq, true);
1284
1285 return true;
1286 }
1287
1288 /* Fold a machine-dependent built-in in GIMPLE. (For folding into
1289 a constant, use rs6000_fold_builtin.) */
1290 bool
rs6000_gimple_fold_builtin(gimple_stmt_iterator * gsi)1291 rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
1292 {
1293 gimple *stmt = gsi_stmt (*gsi);
1294 tree fndecl = gimple_call_fndecl (stmt);
1295 gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD);
1296 enum rs6000_gen_builtins fn_code
1297 = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
1298 tree arg0, arg1, lhs, temp;
1299 enum tree_code bcode;
1300 gimple *g;
1301
1302 /* For an unresolved overloaded builtin, return early here since there
1303 is no builtin info for it and we are unable to fold it. */
1304 if (fn_code > RS6000_OVLD_NONE)
1305 return false;
1306
1307 size_t uns_fncode = (size_t) fn_code;
1308 enum insn_code icode = rs6000_builtin_info[uns_fncode].icode;
1309 const char *fn_name1 = rs6000_builtin_info[uns_fncode].bifname;
1310 const char *fn_name2 = (icode != CODE_FOR_nothing)
1311 ? get_insn_name ((int) icode)
1312 : "nothing";
1313
1314 if (TARGET_DEBUG_BUILTIN)
1315 fprintf (stderr, "rs6000_gimple_fold_builtin %d %s %s\n",
1316 fn_code, fn_name1, fn_name2);
1317
1318 /* Prevent gimple folding for code that does not have a LHS, unless it is
1319 allowed per the rs6000_builtin_valid_without_lhs helper function. */
1320 if (!gimple_call_lhs (stmt)
1321 && !rs6000_builtin_valid_without_lhs (fn_code, fndecl))
1322 return false;
1323
1324 /* Don't fold invalid builtins, let rs6000_expand_builtin diagnose it. */
1325 if (!rs6000_builtin_is_supported (fn_code))
1326 return false;
1327
1328 if (rs6000_gimple_fold_mma_builtin (gsi, fn_code))
1329 return true;
1330
1331 switch (fn_code)
1332 {
1333 /* Flavors of vec_add. We deliberately don't expand
1334 RS6000_BIF_VADDUQM as it gets lowered from V1TImode to
1335 TImode, resulting in much poorer code generation. */
1336 case RS6000_BIF_VADDUBM:
1337 case RS6000_BIF_VADDUHM:
1338 case RS6000_BIF_VADDUWM:
1339 case RS6000_BIF_VADDUDM:
1340 case RS6000_BIF_VADDFP:
1341 case RS6000_BIF_XVADDDP:
1342 case RS6000_BIF_XVADDSP:
1343 bcode = PLUS_EXPR;
1344 do_binary:
1345 arg0 = gimple_call_arg (stmt, 0);
1346 arg1 = gimple_call_arg (stmt, 1);
1347 lhs = gimple_call_lhs (stmt);
1348 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (lhs)))
1349 && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (lhs))))
1350 {
1351 /* Ensure the binary operation is performed in a type
1352 that wraps if it is integral type. */
1353 gimple_seq stmts = NULL;
1354 tree type = unsigned_type_for (TREE_TYPE (lhs));
1355 tree uarg0 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1356 type, arg0);
1357 tree uarg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1358 type, arg1);
1359 tree res = gimple_build (&stmts, gimple_location (stmt), bcode,
1360 type, uarg0, uarg1);
1361 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1362 g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR,
1363 build1 (VIEW_CONVERT_EXPR,
1364 TREE_TYPE (lhs), res));
1365 gsi_replace (gsi, g, true);
1366 return true;
1367 }
1368 g = gimple_build_assign (lhs, bcode, arg0, arg1);
1369 gimple_set_location (g, gimple_location (stmt));
1370 gsi_replace (gsi, g, true);
1371 return true;
1372 /* Flavors of vec_sub. We deliberately don't expand
1373 RS6000_BIF_VSUBUQM. */
1374 case RS6000_BIF_VSUBUBM:
1375 case RS6000_BIF_VSUBUHM:
1376 case RS6000_BIF_VSUBUWM:
1377 case RS6000_BIF_VSUBUDM:
1378 case RS6000_BIF_VSUBFP:
1379 case RS6000_BIF_XVSUBDP:
1380 case RS6000_BIF_XVSUBSP:
1381 bcode = MINUS_EXPR;
1382 goto do_binary;
1383 case RS6000_BIF_XVMULSP:
1384 case RS6000_BIF_XVMULDP:
1385 arg0 = gimple_call_arg (stmt, 0);
1386 arg1 = gimple_call_arg (stmt, 1);
1387 lhs = gimple_call_lhs (stmt);
1388 g = gimple_build_assign (lhs, MULT_EXPR, arg0, arg1);
1389 gimple_set_location (g, gimple_location (stmt));
1390 gsi_replace (gsi, g, true);
1391 return true;
1392 /* Even element flavors of vec_mul (signed). */
1393 case RS6000_BIF_VMULESB:
1394 case RS6000_BIF_VMULESH:
1395 case RS6000_BIF_VMULESW:
1396 /* Even element flavors of vec_mul (unsigned). */
1397 case RS6000_BIF_VMULEUB:
1398 case RS6000_BIF_VMULEUH:
1399 case RS6000_BIF_VMULEUW:
1400 arg0 = gimple_call_arg (stmt, 0);
1401 arg1 = gimple_call_arg (stmt, 1);
1402 lhs = gimple_call_lhs (stmt);
1403 g = gimple_build_assign (lhs, VEC_WIDEN_MULT_EVEN_EXPR, arg0, arg1);
1404 gimple_set_location (g, gimple_location (stmt));
1405 gsi_replace (gsi, g, true);
1406 return true;
1407 /* Odd element flavors of vec_mul (signed). */
1408 case RS6000_BIF_VMULOSB:
1409 case RS6000_BIF_VMULOSH:
1410 case RS6000_BIF_VMULOSW:
1411 /* Odd element flavors of vec_mul (unsigned). */
1412 case RS6000_BIF_VMULOUB:
1413 case RS6000_BIF_VMULOUH:
1414 case RS6000_BIF_VMULOUW:
1415 arg0 = gimple_call_arg (stmt, 0);
1416 arg1 = gimple_call_arg (stmt, 1);
1417 lhs = gimple_call_lhs (stmt);
1418 g = gimple_build_assign (lhs, VEC_WIDEN_MULT_ODD_EXPR, arg0, arg1);
1419 gimple_set_location (g, gimple_location (stmt));
1420 gsi_replace (gsi, g, true);
1421 return true;
1422 /* Flavors of vec_div (Integer). */
1423 case RS6000_BIF_DIV_V2DI:
1424 case RS6000_BIF_UDIV_V2DI:
1425 arg0 = gimple_call_arg (stmt, 0);
1426 arg1 = gimple_call_arg (stmt, 1);
1427 lhs = gimple_call_lhs (stmt);
1428 g = gimple_build_assign (lhs, TRUNC_DIV_EXPR, arg0, arg1);
1429 gimple_set_location (g, gimple_location (stmt));
1430 gsi_replace (gsi, g, true);
1431 return true;
1432 /* Flavors of vec_div (Float). */
1433 case RS6000_BIF_XVDIVSP:
1434 case RS6000_BIF_XVDIVDP:
1435 arg0 = gimple_call_arg (stmt, 0);
1436 arg1 = gimple_call_arg (stmt, 1);
1437 lhs = gimple_call_lhs (stmt);
1438 g = gimple_build_assign (lhs, RDIV_EXPR, arg0, arg1);
1439 gimple_set_location (g, gimple_location (stmt));
1440 gsi_replace (gsi, g, true);
1441 return true;
1442 /* Flavors of vec_and. */
1443 case RS6000_BIF_VAND_V16QI_UNS:
1444 case RS6000_BIF_VAND_V16QI:
1445 case RS6000_BIF_VAND_V8HI_UNS:
1446 case RS6000_BIF_VAND_V8HI:
1447 case RS6000_BIF_VAND_V4SI_UNS:
1448 case RS6000_BIF_VAND_V4SI:
1449 case RS6000_BIF_VAND_V2DI_UNS:
1450 case RS6000_BIF_VAND_V2DI:
1451 case RS6000_BIF_VAND_V4SF:
1452 case RS6000_BIF_VAND_V2DF:
1453 arg0 = gimple_call_arg (stmt, 0);
1454 arg1 = gimple_call_arg (stmt, 1);
1455 lhs = gimple_call_lhs (stmt);
1456 g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, arg1);
1457 gimple_set_location (g, gimple_location (stmt));
1458 gsi_replace (gsi, g, true);
1459 return true;
1460 /* Flavors of vec_andc. */
1461 case RS6000_BIF_VANDC_V16QI_UNS:
1462 case RS6000_BIF_VANDC_V16QI:
1463 case RS6000_BIF_VANDC_V8HI_UNS:
1464 case RS6000_BIF_VANDC_V8HI:
1465 case RS6000_BIF_VANDC_V4SI_UNS:
1466 case RS6000_BIF_VANDC_V4SI:
1467 case RS6000_BIF_VANDC_V2DI_UNS:
1468 case RS6000_BIF_VANDC_V2DI:
1469 case RS6000_BIF_VANDC_V4SF:
1470 case RS6000_BIF_VANDC_V2DF:
1471 arg0 = gimple_call_arg (stmt, 0);
1472 arg1 = gimple_call_arg (stmt, 1);
1473 lhs = gimple_call_lhs (stmt);
1474 temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
1475 g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1);
1476 gimple_set_location (g, gimple_location (stmt));
1477 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1478 g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, temp);
1479 gimple_set_location (g, gimple_location (stmt));
1480 gsi_replace (gsi, g, true);
1481 return true;
1482 /* Flavors of vec_nand. */
1483 case RS6000_BIF_NAND_V16QI_UNS:
1484 case RS6000_BIF_NAND_V16QI:
1485 case RS6000_BIF_NAND_V8HI_UNS:
1486 case RS6000_BIF_NAND_V8HI:
1487 case RS6000_BIF_NAND_V4SI_UNS:
1488 case RS6000_BIF_NAND_V4SI:
1489 case RS6000_BIF_NAND_V2DI_UNS:
1490 case RS6000_BIF_NAND_V2DI:
1491 case RS6000_BIF_NAND_V4SF:
1492 case RS6000_BIF_NAND_V2DF:
1493 arg0 = gimple_call_arg (stmt, 0);
1494 arg1 = gimple_call_arg (stmt, 1);
1495 lhs = gimple_call_lhs (stmt);
1496 temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
1497 g = gimple_build_assign (temp, BIT_AND_EXPR, arg0, arg1);
1498 gimple_set_location (g, gimple_location (stmt));
1499 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1500 g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
1501 gimple_set_location (g, gimple_location (stmt));
1502 gsi_replace (gsi, g, true);
1503 return true;
1504 /* Flavors of vec_or. */
1505 case RS6000_BIF_VOR_V16QI_UNS:
1506 case RS6000_BIF_VOR_V16QI:
1507 case RS6000_BIF_VOR_V8HI_UNS:
1508 case RS6000_BIF_VOR_V8HI:
1509 case RS6000_BIF_VOR_V4SI_UNS:
1510 case RS6000_BIF_VOR_V4SI:
1511 case RS6000_BIF_VOR_V2DI_UNS:
1512 case RS6000_BIF_VOR_V2DI:
1513 case RS6000_BIF_VOR_V4SF:
1514 case RS6000_BIF_VOR_V2DF:
1515 arg0 = gimple_call_arg (stmt, 0);
1516 arg1 = gimple_call_arg (stmt, 1);
1517 lhs = gimple_call_lhs (stmt);
1518 g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, arg1);
1519 gimple_set_location (g, gimple_location (stmt));
1520 gsi_replace (gsi, g, true);
1521 return true;
1522 /* flavors of vec_orc. */
1523 case RS6000_BIF_ORC_V16QI_UNS:
1524 case RS6000_BIF_ORC_V16QI:
1525 case RS6000_BIF_ORC_V8HI_UNS:
1526 case RS6000_BIF_ORC_V8HI:
1527 case RS6000_BIF_ORC_V4SI_UNS:
1528 case RS6000_BIF_ORC_V4SI:
1529 case RS6000_BIF_ORC_V2DI_UNS:
1530 case RS6000_BIF_ORC_V2DI:
1531 case RS6000_BIF_ORC_V4SF:
1532 case RS6000_BIF_ORC_V2DF:
1533 arg0 = gimple_call_arg (stmt, 0);
1534 arg1 = gimple_call_arg (stmt, 1);
1535 lhs = gimple_call_lhs (stmt);
1536 temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
1537 g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1);
1538 gimple_set_location (g, gimple_location (stmt));
1539 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1540 g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, temp);
1541 gimple_set_location (g, gimple_location (stmt));
1542 gsi_replace (gsi, g, true);
1543 return true;
1544 /* Flavors of vec_xor. */
1545 case RS6000_BIF_VXOR_V16QI_UNS:
1546 case RS6000_BIF_VXOR_V16QI:
1547 case RS6000_BIF_VXOR_V8HI_UNS:
1548 case RS6000_BIF_VXOR_V8HI:
1549 case RS6000_BIF_VXOR_V4SI_UNS:
1550 case RS6000_BIF_VXOR_V4SI:
1551 case RS6000_BIF_VXOR_V2DI_UNS:
1552 case RS6000_BIF_VXOR_V2DI:
1553 case RS6000_BIF_VXOR_V4SF:
1554 case RS6000_BIF_VXOR_V2DF:
1555 arg0 = gimple_call_arg (stmt, 0);
1556 arg1 = gimple_call_arg (stmt, 1);
1557 lhs = gimple_call_lhs (stmt);
1558 g = gimple_build_assign (lhs, BIT_XOR_EXPR, arg0, arg1);
1559 gimple_set_location (g, gimple_location (stmt));
1560 gsi_replace (gsi, g, true);
1561 return true;
1562 /* Flavors of vec_nor. */
1563 case RS6000_BIF_VNOR_V16QI_UNS:
1564 case RS6000_BIF_VNOR_V16QI:
1565 case RS6000_BIF_VNOR_V8HI_UNS:
1566 case RS6000_BIF_VNOR_V8HI:
1567 case RS6000_BIF_VNOR_V4SI_UNS:
1568 case RS6000_BIF_VNOR_V4SI:
1569 case RS6000_BIF_VNOR_V2DI_UNS:
1570 case RS6000_BIF_VNOR_V2DI:
1571 case RS6000_BIF_VNOR_V4SF:
1572 case RS6000_BIF_VNOR_V2DF:
1573 arg0 = gimple_call_arg (stmt, 0);
1574 arg1 = gimple_call_arg (stmt, 1);
1575 lhs = gimple_call_lhs (stmt);
1576 temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
1577 g = gimple_build_assign (temp, BIT_IOR_EXPR, arg0, arg1);
1578 gimple_set_location (g, gimple_location (stmt));
1579 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1580 g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
1581 gimple_set_location (g, gimple_location (stmt));
1582 gsi_replace (gsi, g, true);
1583 return true;
1584 /* flavors of vec_abs. */
1585 case RS6000_BIF_ABS_V16QI:
1586 case RS6000_BIF_ABS_V8HI:
1587 case RS6000_BIF_ABS_V4SI:
1588 case RS6000_BIF_ABS_V4SF:
1589 case RS6000_BIF_ABS_V2DI:
1590 case RS6000_BIF_XVABSDP:
1591 case RS6000_BIF_XVABSSP:
1592 arg0 = gimple_call_arg (stmt, 0);
1593 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
1594 && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0))))
1595 return false;
1596 lhs = gimple_call_lhs (stmt);
1597 g = gimple_build_assign (lhs, ABS_EXPR, arg0);
1598 gimple_set_location (g, gimple_location (stmt));
1599 gsi_replace (gsi, g, true);
1600 return true;
1601 /* flavors of vec_min. */
1602 case RS6000_BIF_XVMINDP:
1603 case RS6000_BIF_XVMINSP:
1604 case RS6000_BIF_VMINFP:
1605 {
1606 lhs = gimple_call_lhs (stmt);
1607 tree type = TREE_TYPE (lhs);
1608 if (HONOR_NANS (type))
1609 return false;
1610 gcc_fallthrough ();
1611 }
1612 case RS6000_BIF_VMINSD:
1613 case RS6000_BIF_VMINUD:
1614 case RS6000_BIF_VMINSB:
1615 case RS6000_BIF_VMINSH:
1616 case RS6000_BIF_VMINSW:
1617 case RS6000_BIF_VMINUB:
1618 case RS6000_BIF_VMINUH:
1619 case RS6000_BIF_VMINUW:
1620 arg0 = gimple_call_arg (stmt, 0);
1621 arg1 = gimple_call_arg (stmt, 1);
1622 lhs = gimple_call_lhs (stmt);
1623 g = gimple_build_assign (lhs, MIN_EXPR, arg0, arg1);
1624 gimple_set_location (g, gimple_location (stmt));
1625 gsi_replace (gsi, g, true);
1626 return true;
1627 /* flavors of vec_max. */
1628 case RS6000_BIF_XVMAXDP:
1629 case RS6000_BIF_XVMAXSP:
1630 case RS6000_BIF_VMAXFP:
1631 {
1632 lhs = gimple_call_lhs (stmt);
1633 tree type = TREE_TYPE (lhs);
1634 if (HONOR_NANS (type))
1635 return false;
1636 gcc_fallthrough ();
1637 }
1638 case RS6000_BIF_VMAXSD:
1639 case RS6000_BIF_VMAXUD:
1640 case RS6000_BIF_VMAXSB:
1641 case RS6000_BIF_VMAXSH:
1642 case RS6000_BIF_VMAXSW:
1643 case RS6000_BIF_VMAXUB:
1644 case RS6000_BIF_VMAXUH:
1645 case RS6000_BIF_VMAXUW:
1646 arg0 = gimple_call_arg (stmt, 0);
1647 arg1 = gimple_call_arg (stmt, 1);
1648 lhs = gimple_call_lhs (stmt);
1649 g = gimple_build_assign (lhs, MAX_EXPR, arg0, arg1);
1650 gimple_set_location (g, gimple_location (stmt));
1651 gsi_replace (gsi, g, true);
1652 return true;
1653 /* Flavors of vec_eqv. */
1654 case RS6000_BIF_EQV_V16QI:
1655 case RS6000_BIF_EQV_V8HI:
1656 case RS6000_BIF_EQV_V4SI:
1657 case RS6000_BIF_EQV_V4SF:
1658 case RS6000_BIF_EQV_V2DF:
1659 case RS6000_BIF_EQV_V2DI:
1660 arg0 = gimple_call_arg (stmt, 0);
1661 arg1 = gimple_call_arg (stmt, 1);
1662 lhs = gimple_call_lhs (stmt);
1663 temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
1664 g = gimple_build_assign (temp, BIT_XOR_EXPR, arg0, arg1);
1665 gimple_set_location (g, gimple_location (stmt));
1666 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1667 g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
1668 gimple_set_location (g, gimple_location (stmt));
1669 gsi_replace (gsi, g, true);
1670 return true;
1671 /* Flavors of vec_rotate_left. */
1672 case RS6000_BIF_VRLB:
1673 case RS6000_BIF_VRLH:
1674 case RS6000_BIF_VRLW:
1675 case RS6000_BIF_VRLD:
1676 arg0 = gimple_call_arg (stmt, 0);
1677 arg1 = gimple_call_arg (stmt, 1);
1678 lhs = gimple_call_lhs (stmt);
1679 g = gimple_build_assign (lhs, LROTATE_EXPR, arg0, arg1);
1680 gimple_set_location (g, gimple_location (stmt));
1681 gsi_replace (gsi, g, true);
1682 return true;
1683 /* Flavors of vector shift right algebraic.
1684 vec_sra{b,h,w} -> vsra{b,h,w}. */
1685 case RS6000_BIF_VSRAB:
1686 case RS6000_BIF_VSRAH:
1687 case RS6000_BIF_VSRAW:
1688 case RS6000_BIF_VSRAD:
1689 {
1690 arg0 = gimple_call_arg (stmt, 0);
1691 arg1 = gimple_call_arg (stmt, 1);
1692 lhs = gimple_call_lhs (stmt);
1693 tree arg1_type = TREE_TYPE (arg1);
1694 tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
1695 tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
1696 location_t loc = gimple_location (stmt);
1697 /* Force arg1 into the range valid matching the arg0 type. */
1698 /* Build a vector consisting of the max valid bit-size values. */
1699 int n_elts = VECTOR_CST_NELTS (arg1);
1700 tree element_size = build_int_cst (unsigned_element_type,
1701 128 / n_elts);
1702 tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
1703 for (int i = 0; i < n_elts; i++)
1704 elts.safe_push (element_size);
1705 tree modulo_tree = elts.build ();
1706 /* Modulo the provided shift value against that vector. */
1707 gimple_seq stmts = NULL;
1708 tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1709 unsigned_arg1_type, arg1);
1710 tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
1711 unsigned_arg1_type, unsigned_arg1,
1712 modulo_tree);
1713 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1714 /* And finally, do the shift. */
1715 g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1);
1716 gimple_set_location (g, loc);
1717 gsi_replace (gsi, g, true);
1718 return true;
1719 }
1720 /* Flavors of vector shift left.
1721 builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}. */
1722 case RS6000_BIF_VSLB:
1723 case RS6000_BIF_VSLH:
1724 case RS6000_BIF_VSLW:
1725 case RS6000_BIF_VSLD:
1726 {
1727 location_t loc;
1728 gimple_seq stmts = NULL;
1729 arg0 = gimple_call_arg (stmt, 0);
1730 tree arg0_type = TREE_TYPE (arg0);
1731 if (INTEGRAL_TYPE_P (TREE_TYPE (arg0_type))
1732 && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0_type)))
1733 return false;
1734 arg1 = gimple_call_arg (stmt, 1);
1735 tree arg1_type = TREE_TYPE (arg1);
1736 tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
1737 tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
1738 loc = gimple_location (stmt);
1739 lhs = gimple_call_lhs (stmt);
1740 /* Force arg1 into the range valid matching the arg0 type. */
1741 /* Build a vector consisting of the max valid bit-size values. */
1742 int n_elts = VECTOR_CST_NELTS (arg1);
1743 int tree_size_in_bits = TREE_INT_CST_LOW (size_in_bytes (arg1_type))
1744 * BITS_PER_UNIT;
1745 tree element_size = build_int_cst (unsigned_element_type,
1746 tree_size_in_bits / n_elts);
1747 tree_vector_builder elts (unsigned_type_for (arg1_type), n_elts, 1);
1748 for (int i = 0; i < n_elts; i++)
1749 elts.safe_push (element_size);
1750 tree modulo_tree = elts.build ();
1751 /* Modulo the provided shift value against that vector. */
1752 tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1753 unsigned_arg1_type, arg1);
1754 tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
1755 unsigned_arg1_type, unsigned_arg1,
1756 modulo_tree);
1757 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1758 /* And finally, do the shift. */
1759 g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, new_arg1);
1760 gimple_set_location (g, gimple_location (stmt));
1761 gsi_replace (gsi, g, true);
1762 return true;
1763 }
1764 /* Flavors of vector shift right. */
1765 case RS6000_BIF_VSRB:
1766 case RS6000_BIF_VSRH:
1767 case RS6000_BIF_VSRW:
1768 case RS6000_BIF_VSRD:
1769 {
1770 arg0 = gimple_call_arg (stmt, 0);
1771 arg1 = gimple_call_arg (stmt, 1);
1772 lhs = gimple_call_lhs (stmt);
1773 tree arg1_type = TREE_TYPE (arg1);
1774 tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
1775 tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
1776 location_t loc = gimple_location (stmt);
1777 gimple_seq stmts = NULL;
1778 /* Convert arg0 to unsigned. */
1779 tree arg0_unsigned
1780 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1781 unsigned_type_for (TREE_TYPE (arg0)), arg0);
1782 /* Force arg1 into the range valid matching the arg0 type. */
1783 /* Build a vector consisting of the max valid bit-size values. */
1784 int n_elts = VECTOR_CST_NELTS (arg1);
1785 tree element_size = build_int_cst (unsigned_element_type,
1786 128 / n_elts);
1787 tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
1788 for (int i = 0; i < n_elts; i++)
1789 elts.safe_push (element_size);
1790 tree modulo_tree = elts.build ();
1791 /* Modulo the provided shift value against that vector. */
1792 tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
1793 unsigned_arg1_type, arg1);
1794 tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
1795 unsigned_arg1_type, unsigned_arg1,
1796 modulo_tree);
1797 /* Do the shift. */
1798 tree res
1799 = gimple_build (&stmts, RSHIFT_EXPR,
1800 TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1);
1801 /* Convert result back to the lhs type. */
1802 res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
1803 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1804 replace_call_with_value (gsi, res);
1805 return true;
1806 }
1807 /* Vector loads. */
1808 case RS6000_BIF_LVX_V16QI:
1809 case RS6000_BIF_LVX_V8HI:
1810 case RS6000_BIF_LVX_V4SI:
1811 case RS6000_BIF_LVX_V4SF:
1812 case RS6000_BIF_LVX_V2DI:
1813 case RS6000_BIF_LVX_V2DF:
1814 case RS6000_BIF_LVX_V1TI:
1815 {
1816 arg0 = gimple_call_arg (stmt, 0); // offset
1817 arg1 = gimple_call_arg (stmt, 1); // address
1818 lhs = gimple_call_lhs (stmt);
1819 location_t loc = gimple_location (stmt);
1820 /* Since arg1 may be cast to a different type, just use ptr_type_node
1821 here instead of trying to enforce TBAA on pointer types. */
1822 tree arg1_type = ptr_type_node;
1823 tree lhs_type = TREE_TYPE (lhs);
1824 /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
1825 the tree using the value from arg0. The resulting type will match
1826 the type of arg1. */
1827 gimple_seq stmts = NULL;
1828 tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
1829 tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
1830 arg1_type, arg1, temp_offset);
1831 /* Mask off any lower bits from the address. */
1832 tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR,
1833 arg1_type, temp_addr,
1834 build_int_cst (arg1_type, -16));
1835 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1836 if (!is_gimple_mem_ref_addr (aligned_addr))
1837 {
1838 tree t = make_ssa_name (TREE_TYPE (aligned_addr));
1839 gimple *g = gimple_build_assign (t, aligned_addr);
1840 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1841 aligned_addr = t;
1842 }
1843 /* Use the build2 helper to set up the mem_ref. The MEM_REF could also
1844 take an offset, but since we've already incorporated the offset
1845 above, here we just pass in a zero. */
1846 gimple *g
1847 = gimple_build_assign (lhs, build2 (MEM_REF, lhs_type, aligned_addr,
1848 build_int_cst (arg1_type, 0)));
1849 gimple_set_location (g, loc);
1850 gsi_replace (gsi, g, true);
1851 return true;
1852 }
1853 /* Vector stores. */
1854 case RS6000_BIF_STVX_V16QI:
1855 case RS6000_BIF_STVX_V8HI:
1856 case RS6000_BIF_STVX_V4SI:
1857 case RS6000_BIF_STVX_V4SF:
1858 case RS6000_BIF_STVX_V2DI:
1859 case RS6000_BIF_STVX_V2DF:
1860 {
1861 arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */
1862 arg1 = gimple_call_arg (stmt, 1); /* Offset. */
1863 tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */
1864 location_t loc = gimple_location (stmt);
1865 tree arg0_type = TREE_TYPE (arg0);
1866 /* Use ptr_type_node (no TBAA) for the arg2_type.
1867 FIXME: (Richard) "A proper fix would be to transition this type as
1868 seen from the frontend to GIMPLE, for example in a similar way we
1869 do for MEM_REFs by piggy-backing that on an extra argument, a
1870 constant zero pointer of the alias pointer type to use (which would
1871 also serve as a type indicator of the store itself). I'd use a
1872 target specific internal function for this (not sure if we can have
1873 those target specific, but I guess if it's folded away then that's
1874 fine) and get away with the overload set." */
1875 tree arg2_type = ptr_type_node;
1876 /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
1877 the tree using the value from arg0. The resulting type will match
1878 the type of arg2. */
1879 gimple_seq stmts = NULL;
1880 tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
1881 tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
1882 arg2_type, arg2, temp_offset);
1883 /* Mask off any lower bits from the address. */
1884 tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR,
1885 arg2_type, temp_addr,
1886 build_int_cst (arg2_type, -16));
1887 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1888 if (!is_gimple_mem_ref_addr (aligned_addr))
1889 {
1890 tree t = make_ssa_name (TREE_TYPE (aligned_addr));
1891 gimple *g = gimple_build_assign (t, aligned_addr);
1892 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1893 aligned_addr = t;
1894 }
1895 /* The desired gimple result should be similar to:
1896 MEM[(__vector floatD.1407 *)_1] = vf1D.2697; */
1897 gimple *g
1898 = gimple_build_assign (build2 (MEM_REF, arg0_type, aligned_addr,
1899 build_int_cst (arg2_type, 0)), arg0);
1900 gimple_set_location (g, loc);
1901 gsi_replace (gsi, g, true);
1902 return true;
1903 }
1904
1905 /* unaligned Vector loads. */
1906 case RS6000_BIF_LXVW4X_V16QI:
1907 case RS6000_BIF_LXVW4X_V8HI:
1908 case RS6000_BIF_LXVW4X_V4SF:
1909 case RS6000_BIF_LXVW4X_V4SI:
1910 case RS6000_BIF_LXVD2X_V2DF:
1911 case RS6000_BIF_LXVD2X_V2DI:
1912 {
1913 arg0 = gimple_call_arg (stmt, 0); // offset
1914 arg1 = gimple_call_arg (stmt, 1); // address
1915 lhs = gimple_call_lhs (stmt);
1916 location_t loc = gimple_location (stmt);
1917 /* Since arg1 may be cast to a different type, just use ptr_type_node
1918 here instead of trying to enforce TBAA on pointer types. */
1919 tree arg1_type = ptr_type_node;
1920 tree lhs_type = TREE_TYPE (lhs);
1921 /* In GIMPLE the type of the MEM_REF specifies the alignment. The
1922 required alignment (power) is 4 bytes regardless of data type. */
1923 tree align_ltype = build_aligned_type (lhs_type, 32);
1924 /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
1925 the tree using the value from arg0. The resulting type will match
1926 the type of arg1. */
1927 gimple_seq stmts = NULL;
1928 tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
1929 tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
1930 arg1_type, arg1, temp_offset);
1931 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1932 if (!is_gimple_mem_ref_addr (temp_addr))
1933 {
1934 tree t = make_ssa_name (TREE_TYPE (temp_addr));
1935 gimple *g = gimple_build_assign (t, temp_addr);
1936 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1937 temp_addr = t;
1938 }
1939 /* Use the build2 helper to set up the mem_ref. The MEM_REF could also
1940 take an offset, but since we've already incorporated the offset
1941 above, here we just pass in a zero. */
1942 gimple *g;
1943 g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr,
1944 build_int_cst (arg1_type, 0)));
1945 gimple_set_location (g, loc);
1946 gsi_replace (gsi, g, true);
1947 return true;
1948 }
1949
1950 /* unaligned Vector stores. */
1951 case RS6000_BIF_STXVW4X_V16QI:
1952 case RS6000_BIF_STXVW4X_V8HI:
1953 case RS6000_BIF_STXVW4X_V4SF:
1954 case RS6000_BIF_STXVW4X_V4SI:
1955 case RS6000_BIF_STXVD2X_V2DF:
1956 case RS6000_BIF_STXVD2X_V2DI:
1957 {
1958 arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */
1959 arg1 = gimple_call_arg (stmt, 1); /* Offset. */
1960 tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */
1961 location_t loc = gimple_location (stmt);
1962 tree arg0_type = TREE_TYPE (arg0);
1963 /* Use ptr_type_node (no TBAA) for the arg2_type. */
1964 tree arg2_type = ptr_type_node;
1965 /* In GIMPLE the type of the MEM_REF specifies the alignment. The
1966 required alignment (power) is 4 bytes regardless of data type. */
1967 tree align_stype = build_aligned_type (arg0_type, 32);
1968 /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
1969 the tree using the value from arg1. */
1970 gimple_seq stmts = NULL;
1971 tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
1972 tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
1973 arg2_type, arg2, temp_offset);
1974 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1975 if (!is_gimple_mem_ref_addr (temp_addr))
1976 {
1977 tree t = make_ssa_name (TREE_TYPE (temp_addr));
1978 gimple *g = gimple_build_assign (t, temp_addr);
1979 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1980 temp_addr = t;
1981 }
1982 gimple *g;
1983 g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr,
1984 build_int_cst (arg2_type, 0)), arg0);
1985 gimple_set_location (g, loc);
1986 gsi_replace (gsi, g, true);
1987 return true;
1988 }
1989
1990 /* Vector Fused multiply-add (fma). */
1991 case RS6000_BIF_VMADDFP:
1992 case RS6000_BIF_XVMADDDP:
1993 case RS6000_BIF_XVMADDSP:
1994 case RS6000_BIF_VMLADDUHM:
1995 {
1996 arg0 = gimple_call_arg (stmt, 0);
1997 arg1 = gimple_call_arg (stmt, 1);
1998 tree arg2 = gimple_call_arg (stmt, 2);
1999 lhs = gimple_call_lhs (stmt);
2000 gcall *g = gimple_build_call_internal (IFN_FMA, 3, arg0, arg1, arg2);
2001 gimple_call_set_lhs (g, lhs);
2002 gimple_call_set_nothrow (g, true);
2003 gimple_set_location (g, gimple_location (stmt));
2004 gsi_replace (gsi, g, true);
2005 return true;
2006 }
2007
2008 /* Vector compares; EQ, NE, GE, GT, LE. */
2009 case RS6000_BIF_VCMPEQUB:
2010 case RS6000_BIF_VCMPEQUH:
2011 case RS6000_BIF_VCMPEQUW:
2012 case RS6000_BIF_VCMPEQUD:
2013 /* We deliberately omit RS6000_BIF_VCMPEQUT for now, because gimple
2014 folding produces worse code for 128-bit compares. */
2015 fold_compare_helper (gsi, EQ_EXPR, stmt);
2016 return true;
2017
2018 case RS6000_BIF_VCMPNEB:
2019 case RS6000_BIF_VCMPNEH:
2020 case RS6000_BIF_VCMPNEW:
2021 /* We deliberately omit RS6000_BIF_VCMPNET for now, because gimple
2022 folding produces worse code for 128-bit compares. */
2023 fold_compare_helper (gsi, NE_EXPR, stmt);
2024 return true;
2025
2026 case RS6000_BIF_CMPGE_16QI:
2027 case RS6000_BIF_CMPGE_U16QI:
2028 case RS6000_BIF_CMPGE_8HI:
2029 case RS6000_BIF_CMPGE_U8HI:
2030 case RS6000_BIF_CMPGE_4SI:
2031 case RS6000_BIF_CMPGE_U4SI:
2032 case RS6000_BIF_CMPGE_2DI:
2033 case RS6000_BIF_CMPGE_U2DI:
2034 /* We deliberately omit RS6000_BIF_CMPGE_1TI and RS6000_BIF_CMPGE_U1TI
2035 for now, because gimple folding produces worse code for 128-bit
2036 compares. */
2037 fold_compare_helper (gsi, GE_EXPR, stmt);
2038 return true;
2039
2040 case RS6000_BIF_VCMPGTSB:
2041 case RS6000_BIF_VCMPGTUB:
2042 case RS6000_BIF_VCMPGTSH:
2043 case RS6000_BIF_VCMPGTUH:
2044 case RS6000_BIF_VCMPGTSW:
2045 case RS6000_BIF_VCMPGTUW:
2046 case RS6000_BIF_VCMPGTUD:
2047 case RS6000_BIF_VCMPGTSD:
2048 /* We deliberately omit RS6000_BIF_VCMPGTUT and RS6000_BIF_VCMPGTST
2049 for now, because gimple folding produces worse code for 128-bit
2050 compares. */
2051 fold_compare_helper (gsi, GT_EXPR, stmt);
2052 return true;
2053
2054 case RS6000_BIF_CMPLE_16QI:
2055 case RS6000_BIF_CMPLE_U16QI:
2056 case RS6000_BIF_CMPLE_8HI:
2057 case RS6000_BIF_CMPLE_U8HI:
2058 case RS6000_BIF_CMPLE_4SI:
2059 case RS6000_BIF_CMPLE_U4SI:
2060 case RS6000_BIF_CMPLE_2DI:
2061 case RS6000_BIF_CMPLE_U2DI:
2062 /* We deliberately omit RS6000_BIF_CMPLE_1TI and RS6000_BIF_CMPLE_U1TI
2063 for now, because gimple folding produces worse code for 128-bit
2064 compares. */
2065 fold_compare_helper (gsi, LE_EXPR, stmt);
2066 return true;
2067
2068 /* flavors of vec_splat_[us]{8,16,32}. */
2069 case RS6000_BIF_VSPLTISB:
2070 case RS6000_BIF_VSPLTISH:
2071 case RS6000_BIF_VSPLTISW:
2072 {
2073 arg0 = gimple_call_arg (stmt, 0);
2074 lhs = gimple_call_lhs (stmt);
2075
2076 /* Only fold the vec_splat_*() if the lower bits of arg 0 is a
2077 5-bit signed constant in range -16 to +15. */
2078 if (TREE_CODE (arg0) != INTEGER_CST
2079 || !IN_RANGE (TREE_INT_CST_LOW (arg0), -16, 15))
2080 return false;
2081 gimple_seq stmts = NULL;
2082 location_t loc = gimple_location (stmt);
2083 tree splat_value = gimple_convert (&stmts, loc,
2084 TREE_TYPE (TREE_TYPE (lhs)), arg0);
2085 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
2086 tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value);
2087 g = gimple_build_assign (lhs, splat_tree);
2088 gimple_set_location (g, gimple_location (stmt));
2089 gsi_replace (gsi, g, true);
2090 return true;
2091 }
2092
2093 /* Flavors of vec_splat. */
2094 /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */
2095 case RS6000_BIF_VSPLTB:
2096 case RS6000_BIF_VSPLTH:
2097 case RS6000_BIF_VSPLTW:
2098 case RS6000_BIF_XXSPLTD_V2DI:
2099 case RS6000_BIF_XXSPLTD_V2DF:
2100 {
2101 arg0 = gimple_call_arg (stmt, 0); /* input vector. */
2102 arg1 = gimple_call_arg (stmt, 1); /* index into arg0. */
2103 /* Only fold the vec_splat_*() if arg1 is both a constant value and
2104 is a valid index into the arg0 vector. */
2105 unsigned int n_elts = VECTOR_CST_NELTS (arg0);
2106 if (TREE_CODE (arg1) != INTEGER_CST
2107 || TREE_INT_CST_LOW (arg1) > (n_elts -1))
2108 return false;
2109 lhs = gimple_call_lhs (stmt);
2110 tree lhs_type = TREE_TYPE (lhs);
2111 tree arg0_type = TREE_TYPE (arg0);
2112 tree splat;
2113 if (TREE_CODE (arg0) == VECTOR_CST)
2114 splat = VECTOR_CST_ELT (arg0, TREE_INT_CST_LOW (arg1));
2115 else
2116 {
2117 /* Determine (in bits) the length and start location of the
2118 splat value for a call to the tree_vec_extract helper. */
2119 int splat_elem_size = TREE_INT_CST_LOW (size_in_bytes (arg0_type))
2120 * BITS_PER_UNIT / n_elts;
2121 int splat_start_bit = TREE_INT_CST_LOW (arg1) * splat_elem_size;
2122 tree len = build_int_cst (bitsizetype, splat_elem_size);
2123 tree start = build_int_cst (bitsizetype, splat_start_bit);
2124 splat = tree_vec_extract (gsi, TREE_TYPE (lhs_type), arg0,
2125 len, start);
2126 }
2127 /* And finally, build the new vector. */
2128 tree splat_tree = build_vector_from_val (lhs_type, splat);
2129 g = gimple_build_assign (lhs, splat_tree);
2130 gimple_set_location (g, gimple_location (stmt));
2131 gsi_replace (gsi, g, true);
2132 return true;
2133 }
2134
2135 /* vec_mergel (integrals). */
2136 case RS6000_BIF_VMRGLH:
2137 case RS6000_BIF_VMRGLW:
2138 case RS6000_BIF_XXMRGLW_4SI:
2139 case RS6000_BIF_VMRGLB:
2140 case RS6000_BIF_VEC_MERGEL_V2DI:
2141 case RS6000_BIF_XXMRGLW_4SF:
2142 case RS6000_BIF_VEC_MERGEL_V2DF:
2143 fold_mergehl_helper (gsi, stmt, 1);
2144 return true;
2145 /* vec_mergeh (integrals). */
2146 case RS6000_BIF_VMRGHH:
2147 case RS6000_BIF_VMRGHW:
2148 case RS6000_BIF_XXMRGHW_4SI:
2149 case RS6000_BIF_VMRGHB:
2150 case RS6000_BIF_VEC_MERGEH_V2DI:
2151 case RS6000_BIF_XXMRGHW_4SF:
2152 case RS6000_BIF_VEC_MERGEH_V2DF:
2153 fold_mergehl_helper (gsi, stmt, 0);
2154 return true;
2155
2156 /* Flavors of vec_mergee. */
2157 case RS6000_BIF_VMRGEW_V4SI:
2158 case RS6000_BIF_VMRGEW_V2DI:
2159 case RS6000_BIF_VMRGEW_V4SF:
2160 case RS6000_BIF_VMRGEW_V2DF:
2161 fold_mergeeo_helper (gsi, stmt, 0);
2162 return true;
2163 /* Flavors of vec_mergeo. */
2164 case RS6000_BIF_VMRGOW_V4SI:
2165 case RS6000_BIF_VMRGOW_V2DI:
2166 case RS6000_BIF_VMRGOW_V4SF:
2167 case RS6000_BIF_VMRGOW_V2DF:
2168 fold_mergeeo_helper (gsi, stmt, 1);
2169 return true;
2170
2171 /* d = vec_pack (a, b) */
2172 case RS6000_BIF_VPKUDUM:
2173 case RS6000_BIF_VPKUHUM:
2174 case RS6000_BIF_VPKUWUM:
2175 {
2176 arg0 = gimple_call_arg (stmt, 0);
2177 arg1 = gimple_call_arg (stmt, 1);
2178 lhs = gimple_call_lhs (stmt);
2179 gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1);
2180 gimple_set_location (g, gimple_location (stmt));
2181 gsi_replace (gsi, g, true);
2182 return true;
2183 }
2184
2185 /* d = vec_unpackh (a) */
2186 /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call
2187 in this code is sensitive to endian-ness, and needs to be inverted to
2188 handle both LE and BE targets. */
2189 case RS6000_BIF_VUPKHSB:
2190 case RS6000_BIF_VUPKHSH:
2191 case RS6000_BIF_VUPKHSW:
2192 {
2193 arg0 = gimple_call_arg (stmt, 0);
2194 lhs = gimple_call_lhs (stmt);
2195 if (BYTES_BIG_ENDIAN)
2196 g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
2197 else
2198 g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
2199 gimple_set_location (g, gimple_location (stmt));
2200 gsi_replace (gsi, g, true);
2201 return true;
2202 }
2203 /* d = vec_unpackl (a) */
2204 case RS6000_BIF_VUPKLSB:
2205 case RS6000_BIF_VUPKLSH:
2206 case RS6000_BIF_VUPKLSW:
2207 {
2208 arg0 = gimple_call_arg (stmt, 0);
2209 lhs = gimple_call_lhs (stmt);
2210 if (BYTES_BIG_ENDIAN)
2211 g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
2212 else
2213 g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
2214 gimple_set_location (g, gimple_location (stmt));
2215 gsi_replace (gsi, g, true);
2216 return true;
2217 }
2218 /* There is no gimple type corresponding with pixel, so just return. */
2219 case RS6000_BIF_VUPKHPX:
2220 case RS6000_BIF_VUPKLPX:
2221 return false;
2222
2223 /* vec_perm. */
2224 case RS6000_BIF_VPERM_16QI:
2225 case RS6000_BIF_VPERM_8HI:
2226 case RS6000_BIF_VPERM_4SI:
2227 case RS6000_BIF_VPERM_2DI:
2228 case RS6000_BIF_VPERM_4SF:
2229 case RS6000_BIF_VPERM_2DF:
2230 case RS6000_BIF_VPERM_16QI_UNS:
2231 case RS6000_BIF_VPERM_8HI_UNS:
2232 case RS6000_BIF_VPERM_4SI_UNS:
2233 case RS6000_BIF_VPERM_2DI_UNS:
2234 {
2235 arg0 = gimple_call_arg (stmt, 0);
2236 arg1 = gimple_call_arg (stmt, 1);
2237 tree permute = gimple_call_arg (stmt, 2);
2238 lhs = gimple_call_lhs (stmt);
2239 location_t loc = gimple_location (stmt);
2240 gimple_seq stmts = NULL;
2241 // convert arg0 and arg1 to match the type of the permute
2242 // for the VEC_PERM_EXPR operation.
2243 tree permute_type = (TREE_TYPE (permute));
2244 tree arg0_ptype = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
2245 permute_type, arg0);
2246 tree arg1_ptype = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
2247 permute_type, arg1);
2248 tree lhs_ptype = gimple_build (&stmts, loc, VEC_PERM_EXPR,
2249 permute_type, arg0_ptype, arg1_ptype,
2250 permute);
2251 // Convert the result back to the desired lhs type upon completion.
2252 tree temp = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
2253 TREE_TYPE (lhs), lhs_ptype);
2254 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
2255 g = gimple_build_assign (lhs, temp);
2256 gimple_set_location (g, loc);
2257 gsi_replace (gsi, g, true);
2258 return true;
2259 }
2260
2261 default:
2262 if (TARGET_DEBUG_BUILTIN)
2263 fprintf (stderr, "gimple builtin intrinsic not matched:%d %s %s\n",
2264 fn_code, fn_name1, fn_name2);
2265 break;
2266 }
2267
2268 return false;
2269 }
2270
2271 /* **** Expansion support **** */
2272
2273 static rtx
altivec_expand_predicate_builtin(enum insn_code icode,tree exp,rtx target)2274 altivec_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target)
2275 {
2276 rtx pat, scratch;
2277 tree cr6_form = CALL_EXPR_ARG (exp, 0);
2278 tree arg0 = CALL_EXPR_ARG (exp, 1);
2279 tree arg1 = CALL_EXPR_ARG (exp, 2);
2280 rtx op0 = expand_normal (arg0);
2281 rtx op1 = expand_normal (arg1);
2282 machine_mode tmode = SImode;
2283 machine_mode mode0 = insn_data[icode].operand[1].mode;
2284 machine_mode mode1 = insn_data[icode].operand[2].mode;
2285 int cr6_form_int;
2286
2287 if (TREE_CODE (cr6_form) != INTEGER_CST)
2288 {
2289 error ("argument 1 of %qs must be a constant",
2290 "__builtin_altivec_predicate");
2291 return const0_rtx;
2292 }
2293 else
2294 cr6_form_int = TREE_INT_CST_LOW (cr6_form);
2295
2296 gcc_assert (mode0 == mode1);
2297
2298 /* If we have invalid arguments, bail out before generating bad rtl. */
2299 if (arg0 == error_mark_node || arg1 == error_mark_node)
2300 return const0_rtx;
2301
2302 if (target == 0
2303 || GET_MODE (target) != tmode
2304 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2305 target = gen_reg_rtx (tmode);
2306
2307 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2308 op0 = copy_to_mode_reg (mode0, op0);
2309 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2310 op1 = copy_to_mode_reg (mode1, op1);
2311
2312 /* Note that for many of the relevant operations (e.g. cmpne or
2313 cmpeq) with float or double operands, it makes more sense for the
2314 mode of the allocated scratch register to select a vector of
2315 integer. But the choice to copy the mode of operand 0 was made
2316 long ago and there are no plans to change it. */
2317 scratch = gen_reg_rtx (mode0);
2318
2319 pat = GEN_FCN (icode) (scratch, op0, op1);
2320 if (! pat)
2321 return 0;
2322 emit_insn (pat);
2323
2324 /* The vec_any* and vec_all* predicates use the same opcodes for two
2325 different operations, but the bits in CR6 will be different
2326 depending on what information we want. So we have to play tricks
2327 with CR6 to get the right bits out.
2328
2329 If you think this is disgusting, look at the specs for the
2330 AltiVec predicates. */
2331
2332 switch (cr6_form_int)
2333 {
2334 case 0:
2335 emit_insn (gen_cr6_test_for_zero (target));
2336 break;
2337 case 1:
2338 emit_insn (gen_cr6_test_for_zero_reverse (target));
2339 break;
2340 case 2:
2341 emit_insn (gen_cr6_test_for_lt (target));
2342 break;
2343 case 3:
2344 emit_insn (gen_cr6_test_for_lt_reverse (target));
2345 break;
2346 default:
2347 error ("argument 1 of %qs is out of range",
2348 "__builtin_altivec_predicate");
2349 break;
2350 }
2351
2352 return target;
2353 }
2354
2355 /* Expand vec_init builtin. */
2356 static rtx
altivec_expand_vec_init_builtin(tree type,tree exp,rtx target)2357 altivec_expand_vec_init_builtin (tree type, tree exp, rtx target)
2358 {
2359 machine_mode tmode = TYPE_MODE (type);
2360 machine_mode inner_mode = GET_MODE_INNER (tmode);
2361 int i, n_elt = GET_MODE_NUNITS (tmode);
2362
2363 gcc_assert (VECTOR_MODE_P (tmode));
2364 gcc_assert (n_elt == call_expr_nargs (exp));
2365
2366 if (!target || !register_operand (target, tmode))
2367 target = gen_reg_rtx (tmode);
2368
2369 /* If we have a vector compromised of a single element, such as V1TImode, do
2370 the initialization directly. */
2371 if (n_elt == 1 && GET_MODE_SIZE (tmode) == GET_MODE_SIZE (inner_mode))
2372 {
2373 rtx x = expand_normal (CALL_EXPR_ARG (exp, 0));
2374 emit_move_insn (target, gen_lowpart (tmode, x));
2375 }
2376 else
2377 {
2378 rtvec v = rtvec_alloc (n_elt);
2379
2380 for (i = 0; i < n_elt; ++i)
2381 {
2382 rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
2383 RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
2384 }
2385
2386 rs6000_expand_vector_init (target, gen_rtx_PARALLEL (tmode, v));
2387 }
2388
2389 return target;
2390 }
2391
2392 /* Return the integer constant in ARG. Constrain it to be in the range
2393 of the subparts of VEC_TYPE; issue an error if not. */
2394
2395 static int
get_element_number(tree vec_type,tree arg)2396 get_element_number (tree vec_type, tree arg)
2397 {
2398 unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
2399
2400 if (!tree_fits_uhwi_p (arg)
2401 || (elt = tree_to_uhwi (arg), elt > max))
2402 {
2403 error ("selector must be an integer constant in the range [0, %wi]", max);
2404 return 0;
2405 }
2406
2407 return elt;
2408 }
2409
2410 /* Expand vec_set builtin. */
2411 static rtx
altivec_expand_vec_set_builtin(tree exp)2412 altivec_expand_vec_set_builtin (tree exp)
2413 {
2414 machine_mode tmode, mode1;
2415 tree arg0, arg1, arg2;
2416 int elt;
2417 rtx op0, op1;
2418
2419 arg0 = CALL_EXPR_ARG (exp, 0);
2420 arg1 = CALL_EXPR_ARG (exp, 1);
2421 arg2 = CALL_EXPR_ARG (exp, 2);
2422
2423 tmode = TYPE_MODE (TREE_TYPE (arg0));
2424 mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
2425 gcc_assert (VECTOR_MODE_P (tmode));
2426
2427 op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
2428 op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
2429 elt = get_element_number (TREE_TYPE (arg0), arg2);
2430
2431 if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode)
2432 op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
2433
2434 op0 = force_reg (tmode, op0);
2435 op1 = force_reg (mode1, op1);
2436
2437 rs6000_expand_vector_set (op0, op1, GEN_INT (elt));
2438
2439 return op0;
2440 }
2441
2442 /* Expand vec_ext builtin. */
2443 static rtx
altivec_expand_vec_ext_builtin(tree exp,rtx target)2444 altivec_expand_vec_ext_builtin (tree exp, rtx target)
2445 {
2446 machine_mode tmode, mode0;
2447 tree arg0, arg1;
2448 rtx op0;
2449 rtx op1;
2450
2451 arg0 = CALL_EXPR_ARG (exp, 0);
2452 arg1 = CALL_EXPR_ARG (exp, 1);
2453
2454 op0 = expand_normal (arg0);
2455 op1 = expand_normal (arg1);
2456
2457 if (TREE_CODE (arg1) == INTEGER_CST)
2458 {
2459 unsigned HOST_WIDE_INT elt;
2460 unsigned HOST_WIDE_INT size = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2461 unsigned int truncated_selector;
2462 /* Even if !tree_fits_uhwi_p (arg1)), TREE_INT_CST_LOW (arg0)
2463 returns low-order bits of INTEGER_CST for modulo indexing. */
2464 elt = TREE_INT_CST_LOW (arg1);
2465 truncated_selector = elt % size;
2466 op1 = GEN_INT (truncated_selector);
2467 }
2468
2469 tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
2470 mode0 = TYPE_MODE (TREE_TYPE (arg0));
2471 gcc_assert (VECTOR_MODE_P (mode0));
2472
2473 op0 = force_reg (mode0, op0);
2474
2475 if (optimize || !target || !register_operand (target, tmode))
2476 target = gen_reg_rtx (tmode);
2477
2478 rs6000_expand_vector_extract (target, op0, op1);
2479
2480 return target;
2481 }
2482
2483 /* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
2484 rtx
rs6000_expand_ldst_mask(rtx target,tree arg0)2485 rs6000_expand_ldst_mask (rtx target, tree arg0)
2486 {
2487 int icode2 = BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr_direct
2488 : (int) CODE_FOR_altivec_lvsl_direct;
2489 machine_mode tmode = insn_data[icode2].operand[0].mode;
2490 machine_mode mode = insn_data[icode2].operand[1].mode;
2491
2492 gcc_assert (TARGET_ALTIVEC);
2493
2494 gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg0)));
2495 rtx op = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
2496 rtx addr = memory_address (mode, op);
2497 /* We need to negate the address. */
2498 op = gen_reg_rtx (GET_MODE (addr));
2499 emit_insn (gen_rtx_SET (op, gen_rtx_NEG (GET_MODE (addr), addr)));
2500 op = gen_rtx_MEM (mode, op);
2501
2502 if (target == 0
2503 || GET_MODE (target) != tmode
2504 || !insn_data[icode2].operand[0].predicate (target, tmode))
2505 target = gen_reg_rtx (tmode);
2506
2507 rtx pat = GEN_FCN (icode2) (target, op);
2508 if (!pat)
2509 return 0;
2510 emit_insn (pat);
2511
2512 return target;
2513 }
2514
2515 /* Used by __builtin_cpu_is(), mapping from PLATFORM names to values. */
2516 static const struct
2517 {
2518 const char *cpu;
2519 unsigned int cpuid;
2520 } cpu_is_info[] = {
2521 { "power10", PPC_PLATFORM_POWER10 },
2522 { "power9", PPC_PLATFORM_POWER9 },
2523 { "power8", PPC_PLATFORM_POWER8 },
2524 { "power7", PPC_PLATFORM_POWER7 },
2525 { "power6x", PPC_PLATFORM_POWER6X },
2526 { "power6", PPC_PLATFORM_POWER6 },
2527 { "power5+", PPC_PLATFORM_POWER5_PLUS },
2528 { "power5", PPC_PLATFORM_POWER5 },
2529 { "ppc970", PPC_PLATFORM_PPC970 },
2530 { "power4", PPC_PLATFORM_POWER4 },
2531 { "ppca2", PPC_PLATFORM_PPCA2 },
2532 { "ppc476", PPC_PLATFORM_PPC476 },
2533 { "ppc464", PPC_PLATFORM_PPC464 },
2534 { "ppc440", PPC_PLATFORM_PPC440 },
2535 { "ppc405", PPC_PLATFORM_PPC405 },
2536 { "ppc-cell-be", PPC_PLATFORM_CELL_BE }
2537 };
2538
2539 /* Used by __builtin_cpu_supports(), mapping from HWCAP names to masks. */
2540 static const struct
2541 {
2542 const char *hwcap;
2543 int mask;
2544 unsigned int id;
2545 } cpu_supports_info[] = {
2546 /* AT_HWCAP masks. */
2547 { "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0 },
2548 { "altivec", PPC_FEATURE_HAS_ALTIVEC, 0 },
2549 { "arch_2_05", PPC_FEATURE_ARCH_2_05, 0 },
2550 { "arch_2_06", PPC_FEATURE_ARCH_2_06, 0 },
2551 { "archpmu", PPC_FEATURE_PERFMON_COMPAT, 0 },
2552 { "booke", PPC_FEATURE_BOOKE, 0 },
2553 { "cellbe", PPC_FEATURE_CELL_BE, 0 },
2554 { "dfp", PPC_FEATURE_HAS_DFP, 0 },
2555 { "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, 0 },
2556 { "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, 0 },
2557 { "fpu", PPC_FEATURE_HAS_FPU, 0 },
2558 { "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0 },
2559 { "mmu", PPC_FEATURE_HAS_MMU, 0 },
2560 { "notb", PPC_FEATURE_NO_TB, 0 },
2561 { "pa6t", PPC_FEATURE_PA6T, 0 },
2562 { "power4", PPC_FEATURE_POWER4, 0 },
2563 { "power5", PPC_FEATURE_POWER5, 0 },
2564 { "power5+", PPC_FEATURE_POWER5_PLUS, 0 },
2565 { "power6x", PPC_FEATURE_POWER6_EXT, 0 },
2566 { "ppc32", PPC_FEATURE_32, 0 },
2567 { "ppc601", PPC_FEATURE_601_INSTR, 0 },
2568 { "ppc64", PPC_FEATURE_64, 0 },
2569 { "ppcle", PPC_FEATURE_PPC_LE, 0 },
2570 { "smt", PPC_FEATURE_SMT, 0 },
2571 { "spe", PPC_FEATURE_HAS_SPE, 0 },
2572 { "true_le", PPC_FEATURE_TRUE_LE, 0 },
2573 { "ucache", PPC_FEATURE_UNIFIED_CACHE, 0 },
2574 { "vsx", PPC_FEATURE_HAS_VSX, 0 },
2575
2576 /* AT_HWCAP2 masks. */
2577 { "arch_2_07", PPC_FEATURE2_ARCH_2_07, 1 },
2578 { "dscr", PPC_FEATURE2_HAS_DSCR, 1 },
2579 { "ebb", PPC_FEATURE2_HAS_EBB, 1 },
2580 { "htm", PPC_FEATURE2_HAS_HTM, 1 },
2581 { "htm-nosc", PPC_FEATURE2_HTM_NOSC, 1 },
2582 { "htm-no-suspend", PPC_FEATURE2_HTM_NO_SUSPEND, 1 },
2583 { "isel", PPC_FEATURE2_HAS_ISEL, 1 },
2584 { "tar", PPC_FEATURE2_HAS_TAR, 1 },
2585 { "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 },
2586 { "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 },
2587 { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 },
2588 { "darn", PPC_FEATURE2_DARN, 1 },
2589 { "scv", PPC_FEATURE2_SCV, 1 },
2590 { "arch_3_1", PPC_FEATURE2_ARCH_3_1, 1 },
2591 { "mma", PPC_FEATURE2_MMA, 1 },
2592 };
2593
2594 /* Expand the CPU builtin in FCODE and store the result in TARGET. */
2595 static rtx
cpu_expand_builtin(enum rs6000_gen_builtins fcode,tree exp ATTRIBUTE_UNUSED,rtx target)2596 cpu_expand_builtin (enum rs6000_gen_builtins fcode,
2597 tree exp ATTRIBUTE_UNUSED, rtx target)
2598 {
2599 /* __builtin_cpu_init () is a nop, so expand to nothing. */
2600 if (fcode == RS6000_BIF_CPU_INIT)
2601 return const0_rtx;
2602
2603 if (target == 0 || GET_MODE (target) != SImode)
2604 target = gen_reg_rtx (SImode);
2605
2606 /* TODO: Factor the #ifdef'd code into a separate function. */
2607 #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
2608 tree arg = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2609 /* Target clones creates an ARRAY_REF instead of STRING_CST, convert it back
2610 to a STRING_CST. */
2611 if (TREE_CODE (arg) == ARRAY_REF
2612 && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST
2613 && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST
2614 && compare_tree_int (TREE_OPERAND (arg, 1), 0) == 0)
2615 arg = TREE_OPERAND (arg, 0);
2616
2617 if (TREE_CODE (arg) != STRING_CST)
2618 {
2619 error ("builtin %qs only accepts a string argument",
2620 rs6000_builtin_info[(size_t) fcode].bifname);
2621 return const0_rtx;
2622 }
2623
2624 if (fcode == RS6000_BIF_CPU_IS)
2625 {
2626 const char *cpu = TREE_STRING_POINTER (arg);
2627 rtx cpuid = NULL_RTX;
2628 for (size_t i = 0; i < ARRAY_SIZE (cpu_is_info); i++)
2629 if (strcmp (cpu, cpu_is_info[i].cpu) == 0)
2630 {
2631 /* The CPUID value in the TCB is offset by _DL_FIRST_PLATFORM. */
2632 cpuid = GEN_INT (cpu_is_info[i].cpuid + _DL_FIRST_PLATFORM);
2633 break;
2634 }
2635 if (cpuid == NULL_RTX)
2636 {
2637 /* Invalid CPU argument. */
2638 error ("cpu %qs is an invalid argument to builtin %qs",
2639 cpu, rs6000_builtin_info[(size_t) fcode].bifname);
2640 return const0_rtx;
2641 }
2642
2643 rtx platform = gen_reg_rtx (SImode);
2644 rtx address = gen_rtx_PLUS (Pmode,
2645 gen_rtx_REG (Pmode, TLS_REGNUM),
2646 GEN_INT (TCB_PLATFORM_OFFSET));
2647 rtx tcbmem = gen_const_mem (SImode, address);
2648 emit_move_insn (platform, tcbmem);
2649 emit_insn (gen_eqsi3 (target, platform, cpuid));
2650 }
2651 else if (fcode == RS6000_BIF_CPU_SUPPORTS)
2652 {
2653 const char *hwcap = TREE_STRING_POINTER (arg);
2654 rtx mask = NULL_RTX;
2655 int hwcap_offset;
2656 for (size_t i = 0; i < ARRAY_SIZE (cpu_supports_info); i++)
2657 if (strcmp (hwcap, cpu_supports_info[i].hwcap) == 0)
2658 {
2659 mask = GEN_INT (cpu_supports_info[i].mask);
2660 hwcap_offset = TCB_HWCAP_OFFSET (cpu_supports_info[i].id);
2661 break;
2662 }
2663 if (mask == NULL_RTX)
2664 {
2665 /* Invalid HWCAP argument. */
2666 error ("%s %qs is an invalid argument to builtin %qs",
2667 "hwcap", hwcap,
2668 rs6000_builtin_info[(size_t) fcode].bifname);
2669 return const0_rtx;
2670 }
2671
2672 rtx tcb_hwcap = gen_reg_rtx (SImode);
2673 rtx address = gen_rtx_PLUS (Pmode,
2674 gen_rtx_REG (Pmode, TLS_REGNUM),
2675 GEN_INT (hwcap_offset));
2676 rtx tcbmem = gen_const_mem (SImode, address);
2677 emit_move_insn (tcb_hwcap, tcbmem);
2678 rtx scratch1 = gen_reg_rtx (SImode);
2679 emit_insn (gen_rtx_SET (scratch1,
2680 gen_rtx_AND (SImode, tcb_hwcap, mask)));
2681 rtx scratch2 = gen_reg_rtx (SImode);
2682 emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx));
2683 emit_insn (gen_rtx_SET (target,
2684 gen_rtx_XOR (SImode, scratch2, const1_rtx)));
2685 }
2686 else
2687 gcc_unreachable ();
2688
2689 /* Record that we have expanded a CPU builtin, so that we can later
2690 emit a reference to the special symbol exported by LIBC to ensure we
2691 do not link against an old LIBC that doesn't support this feature. */
2692 cpu_builtin_p = true;
2693
2694 #else
2695 warning (0, "builtin %qs needs GLIBC (2.23 and newer) that exports hardware "
2696 "capability bits", rs6000_builtin_info[(size_t) fcode].bifname);
2697
2698 /* For old LIBCs, always return FALSE. */
2699 emit_move_insn (target, GEN_INT (0));
2700 #endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */
2701
2702 return target;
2703 }
2704
2705 /* For the element-reversing load/store built-ins, produce the correct
2706 insn_code depending on the target endianness. */
2707 static insn_code
elemrev_icode(rs6000_gen_builtins fcode)2708 elemrev_icode (rs6000_gen_builtins fcode)
2709 {
2710 switch (fcode)
2711 {
2712 case RS6000_BIF_ST_ELEMREV_V1TI:
2713 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v1ti
2714 : CODE_FOR_vsx_st_elemrev_v1ti;
2715
2716 case RS6000_BIF_ST_ELEMREV_V2DF:
2717 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2df
2718 : CODE_FOR_vsx_st_elemrev_v2df;
2719
2720 case RS6000_BIF_ST_ELEMREV_V2DI:
2721 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2di
2722 : CODE_FOR_vsx_st_elemrev_v2di;
2723
2724 case RS6000_BIF_ST_ELEMREV_V4SF:
2725 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4sf
2726 : CODE_FOR_vsx_st_elemrev_v4sf;
2727
2728 case RS6000_BIF_ST_ELEMREV_V4SI:
2729 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4si
2730 : CODE_FOR_vsx_st_elemrev_v4si;
2731
2732 case RS6000_BIF_ST_ELEMREV_V8HI:
2733 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v8hi
2734 : CODE_FOR_vsx_st_elemrev_v8hi;
2735
2736 case RS6000_BIF_ST_ELEMREV_V16QI:
2737 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v16qi
2738 : CODE_FOR_vsx_st_elemrev_v16qi;
2739
2740 case RS6000_BIF_LD_ELEMREV_V2DF:
2741 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2df
2742 : CODE_FOR_vsx_ld_elemrev_v2df;
2743
2744 case RS6000_BIF_LD_ELEMREV_V1TI:
2745 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v1ti
2746 : CODE_FOR_vsx_ld_elemrev_v1ti;
2747
2748 case RS6000_BIF_LD_ELEMREV_V2DI:
2749 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2di
2750 : CODE_FOR_vsx_ld_elemrev_v2di;
2751
2752 case RS6000_BIF_LD_ELEMREV_V4SF:
2753 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4sf
2754 : CODE_FOR_vsx_ld_elemrev_v4sf;
2755
2756 case RS6000_BIF_LD_ELEMREV_V4SI:
2757 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4si
2758 : CODE_FOR_vsx_ld_elemrev_v4si;
2759
2760 case RS6000_BIF_LD_ELEMREV_V8HI:
2761 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v8hi
2762 : CODE_FOR_vsx_ld_elemrev_v8hi;
2763
2764 case RS6000_BIF_LD_ELEMREV_V16QI:
2765 return BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v16qi
2766 : CODE_FOR_vsx_ld_elemrev_v16qi;
2767 default:
2768 ;
2769 }
2770
2771 gcc_unreachable ();
2772 }
2773
2774 /* Expand an AltiVec vector load builtin, and return the expanded rtx. */
2775 static rtx
ldv_expand_builtin(rtx target,insn_code icode,rtx * op,machine_mode tmode)2776 ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
2777 {
2778 if (target == 0
2779 || GET_MODE (target) != tmode
2780 || !insn_data[icode].operand[0].predicate (target, tmode))
2781 target = gen_reg_rtx (tmode);
2782
2783 op[1] = copy_to_mode_reg (Pmode, op[1]);
2784
2785 /* These CELL built-ins use BLKmode instead of tmode for historical
2786 (i.e., unknown) reasons. TODO: Is this necessary? */
2787 bool blk = (icode == CODE_FOR_altivec_lvlx
2788 || icode == CODE_FOR_altivec_lvlxl
2789 || icode == CODE_FOR_altivec_lvrx
2790 || icode == CODE_FOR_altivec_lvrxl);
2791
2792 /* For LVX, express the RTL accurately by ANDing the address with -16.
2793 LVXL and LVE*X expand to use UNSPECs to hide their special behavior,
2794 so the raw address is fine. */
2795 /* TODO: That statement seems wrong, as the UNSPECs don't surround the
2796 memory expression, so a latent bug may lie here. The &-16 is likely
2797 needed for all VMX-style loads. */
2798 if (icode == CODE_FOR_altivec_lvx_v1ti
2799 || icode == CODE_FOR_altivec_lvx_v2df
2800 || icode == CODE_FOR_altivec_lvx_v2di
2801 || icode == CODE_FOR_altivec_lvx_v4sf
2802 || icode == CODE_FOR_altivec_lvx_v4si
2803 || icode == CODE_FOR_altivec_lvx_v8hi
2804 || icode == CODE_FOR_altivec_lvx_v16qi)
2805 {
2806 rtx rawaddr;
2807 if (op[0] == const0_rtx)
2808 rawaddr = op[1];
2809 else
2810 {
2811 op[0] = copy_to_mode_reg (Pmode, op[0]);
2812 rawaddr = gen_rtx_PLUS (Pmode, op[1], op[0]);
2813 }
2814 rtx addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16));
2815 addr = gen_rtx_MEM (blk ? BLKmode : tmode, addr);
2816
2817 emit_insn (gen_rtx_SET (target, addr));
2818 }
2819 else
2820 {
2821 rtx addr;
2822 if (op[0] == const0_rtx)
2823 addr = gen_rtx_MEM (blk ? BLKmode : tmode, op[1]);
2824 else
2825 {
2826 op[0] = copy_to_mode_reg (Pmode, op[0]);
2827 addr = gen_rtx_MEM (blk ? BLKmode : tmode,
2828 gen_rtx_PLUS (Pmode, op[1], op[0]));
2829 }
2830
2831 rtx pat = GEN_FCN (icode) (target, addr);
2832 if (!pat)
2833 return 0;
2834 emit_insn (pat);
2835 }
2836
2837 return target;
2838 }
2839
2840 /* Expand a builtin function that loads a scalar into a vector register
2841 with sign extension, and return the expanded rtx. */
2842 static rtx
lxvrse_expand_builtin(rtx target,insn_code icode,rtx * op,machine_mode tmode,machine_mode smode)2843 lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
2844 machine_mode tmode, machine_mode smode)
2845 {
2846 rtx pat, addr;
2847 op[1] = copy_to_mode_reg (Pmode, op[1]);
2848
2849 if (op[0] == const0_rtx)
2850 addr = gen_rtx_MEM (tmode, op[1]);
2851 else
2852 {
2853 op[0] = copy_to_mode_reg (Pmode, op[0]);
2854 addr = gen_rtx_MEM (smode,
2855 gen_rtx_PLUS (Pmode, op[1], op[0]));
2856 }
2857
2858 rtx discratch = gen_reg_rtx (V2DImode);
2859 rtx tiscratch = gen_reg_rtx (TImode);
2860
2861 /* Emit the lxvr*x insn. */
2862 pat = GEN_FCN (icode) (tiscratch, addr);
2863 if (!pat)
2864 return 0;
2865 emit_insn (pat);
2866
2867 /* Emit a sign extension from V16QI,V8HI,V4SI to V2DI. */
2868 rtx temp1;
2869 if (icode == CODE_FOR_vsx_lxvrbx)
2870 {
2871 temp1 = simplify_gen_subreg (V16QImode, tiscratch, TImode, 0);
2872 emit_insn (gen_vsx_sign_extend_v16qi_v2di (discratch, temp1));
2873 }
2874 else if (icode == CODE_FOR_vsx_lxvrhx)
2875 {
2876 temp1 = simplify_gen_subreg (V8HImode, tiscratch, TImode, 0);
2877 emit_insn (gen_vsx_sign_extend_v8hi_v2di (discratch, temp1));
2878 }
2879 else if (icode == CODE_FOR_vsx_lxvrwx)
2880 {
2881 temp1 = simplify_gen_subreg (V4SImode, tiscratch, TImode, 0);
2882 emit_insn (gen_vsx_sign_extend_v4si_v2di (discratch, temp1));
2883 }
2884 else if (icode == CODE_FOR_vsx_lxvrdx)
2885 discratch = simplify_gen_subreg (V2DImode, tiscratch, TImode, 0);
2886 else
2887 gcc_unreachable ();
2888
2889 /* Emit the sign extension from V2DI (double) to TI (quad). */
2890 rtx temp2 = simplify_gen_subreg (TImode, discratch, V2DImode, 0);
2891 emit_insn (gen_extendditi2_vector (target, temp2));
2892
2893 return target;
2894 }
2895
2896 /* Expand a builtin function that loads a scalar into a vector register
2897 with zero extension, and return the expanded rtx. */
2898 static rtx
lxvrze_expand_builtin(rtx target,insn_code icode,rtx * op,machine_mode tmode,machine_mode smode)2899 lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
2900 machine_mode tmode, machine_mode smode)
2901 {
2902 rtx pat, addr;
2903 op[1] = copy_to_mode_reg (Pmode, op[1]);
2904
2905 if (op[0] == const0_rtx)
2906 addr = gen_rtx_MEM (tmode, op[1]);
2907 else
2908 {
2909 op[0] = copy_to_mode_reg (Pmode, op[0]);
2910 addr = gen_rtx_MEM (smode,
2911 gen_rtx_PLUS (Pmode, op[1], op[0]));
2912 }
2913
2914 pat = GEN_FCN (icode) (target, addr);
2915 if (!pat)
2916 return 0;
2917 emit_insn (pat);
2918 return target;
2919 }
2920
2921 /* Expand an AltiVec vector store builtin, and return the expanded rtx. */
2922 static rtx
stv_expand_builtin(insn_code icode,rtx * op,machine_mode tmode,machine_mode smode)2923 stv_expand_builtin (insn_code icode, rtx *op,
2924 machine_mode tmode, machine_mode smode)
2925 {
2926 op[2] = copy_to_mode_reg (Pmode, op[2]);
2927
2928 /* For STVX, express the RTL accurately by ANDing the address with -16.
2929 STVXL and STVE*X expand to use UNSPECs to hide their special behavior,
2930 so the raw address is fine. */
2931 /* TODO: That statement seems wrong, as the UNSPECs don't surround the
2932 memory expression, so a latent bug may lie here. The &-16 is likely
2933 needed for all VMX-style stores. */
2934 if (icode == CODE_FOR_altivec_stvx_v2df
2935 || icode == CODE_FOR_altivec_stvx_v2di
2936 || icode == CODE_FOR_altivec_stvx_v4sf
2937 || icode == CODE_FOR_altivec_stvx_v4si
2938 || icode == CODE_FOR_altivec_stvx_v8hi
2939 || icode == CODE_FOR_altivec_stvx_v16qi)
2940 {
2941 rtx rawaddr;
2942 if (op[1] == const0_rtx)
2943 rawaddr = op[2];
2944 else
2945 {
2946 op[1] = copy_to_mode_reg (Pmode, op[1]);
2947 rawaddr = gen_rtx_PLUS (Pmode, op[2], op[1]);
2948 }
2949
2950 rtx addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16));
2951 addr = gen_rtx_MEM (tmode, addr);
2952 op[0] = copy_to_mode_reg (tmode, op[0]);
2953 emit_insn (gen_rtx_SET (addr, op[0]));
2954 }
2955 else if (icode == CODE_FOR_vsx_stxvrbx
2956 || icode == CODE_FOR_vsx_stxvrhx
2957 || icode == CODE_FOR_vsx_stxvrwx
2958 || icode == CODE_FOR_vsx_stxvrdx)
2959 {
2960 rtx truncrtx = gen_rtx_TRUNCATE (tmode, op[0]);
2961 op[0] = copy_to_mode_reg (E_TImode, truncrtx);
2962
2963 rtx addr;
2964 if (op[1] == const0_rtx)
2965 addr = gen_rtx_MEM (tmode, op[2]);
2966 else
2967 {
2968 op[1] = copy_to_mode_reg (Pmode, op[1]);
2969 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op[2], op[1]));
2970 }
2971 rtx pat = GEN_FCN (icode) (addr, op[0]);
2972 if (pat)
2973 emit_insn (pat);
2974 }
2975 else
2976 {
2977 if (!insn_data[icode].operand[1].predicate (op[0], smode))
2978 op[0] = copy_to_mode_reg (smode, op[0]);
2979
2980 rtx addr;
2981 if (op[1] == const0_rtx)
2982 addr = gen_rtx_MEM (tmode, op[2]);
2983 else
2984 {
2985 op[1] = copy_to_mode_reg (Pmode, op[1]);
2986 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op[2], op[1]));
2987 }
2988
2989 rtx pat = GEN_FCN (icode) (addr, op[0]);
2990 if (pat)
2991 emit_insn (pat);
2992 }
2993
2994 return NULL_RTX;
2995 }
2996
2997 /* Expand the MMA built-in in EXP, and return it. */
2998 static rtx
mma_expand_builtin(tree exp,rtx target,insn_code icode,rs6000_gen_builtins fcode)2999 mma_expand_builtin (tree exp, rtx target, insn_code icode,
3000 rs6000_gen_builtins fcode)
3001 {
3002 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3003 bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
3004 machine_mode tmode = VOIDmode;
3005 rtx op[MAX_MMA_OPERANDS];
3006 unsigned nopnds = 0;
3007
3008 if (!void_func)
3009 {
3010 tmode = insn_data[icode].operand[0].mode;
3011 if (!(target
3012 && GET_MODE (target) == tmode
3013 && insn_data[icode].operand[0].predicate (target, tmode)))
3014 target = gen_reg_rtx (tmode);
3015 op[nopnds++] = target;
3016 }
3017 else
3018 target = const0_rtx;
3019
3020 call_expr_arg_iterator iter;
3021 tree arg;
3022 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
3023 {
3024 if (arg == error_mark_node)
3025 return const0_rtx;
3026
3027 rtx opnd;
3028 const struct insn_operand_data *insn_op;
3029 insn_op = &insn_data[icode].operand[nopnds];
3030 if (TREE_CODE (arg) == ADDR_EXPR
3031 && MEM_P (DECL_RTL (TREE_OPERAND (arg, 0))))
3032 opnd = DECL_RTL (TREE_OPERAND (arg, 0));
3033 else
3034 opnd = expand_normal (arg);
3035
3036 if (!insn_op->predicate (opnd, insn_op->mode))
3037 {
3038 /* TODO: This use of constraints needs explanation. */
3039 if (!strcmp (insn_op->constraint, "n"))
3040 {
3041 if (!CONST_INT_P (opnd))
3042 error ("argument %d must be an unsigned literal", nopnds);
3043 else
3044 error ("argument %d is an unsigned literal that is "
3045 "out of range", nopnds);
3046 return const0_rtx;
3047 }
3048 opnd = copy_to_mode_reg (insn_op->mode, opnd);
3049 }
3050
3051 /* Some MMA instructions have INOUT accumulator operands, so force
3052 their target register to be the same as their input register. */
3053 if (!void_func
3054 && nopnds == 1
3055 && !strcmp (insn_op->constraint, "0")
3056 && insn_op->mode == tmode
3057 && REG_P (opnd)
3058 && insn_data[icode].operand[0].predicate (opnd, tmode))
3059 target = op[0] = opnd;
3060
3061 op[nopnds++] = opnd;
3062 }
3063
3064 rtx pat;
3065 switch (nopnds)
3066 {
3067 case 1:
3068 pat = GEN_FCN (icode) (op[0]);
3069 break;
3070 case 2:
3071 pat = GEN_FCN (icode) (op[0], op[1]);
3072 break;
3073 case 3:
3074 /* The ASSEMBLE builtin source operands are reversed in little-endian
3075 mode, so reorder them. */
3076 if (fcode == RS6000_BIF_ASSEMBLE_PAIR_V_INTERNAL && !WORDS_BIG_ENDIAN)
3077 std::swap (op[1], op[2]);
3078 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
3079 break;
3080 case 4:
3081 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
3082 break;
3083 case 5:
3084 /* The ASSEMBLE builtin source operands are reversed in little-endian
3085 mode, so reorder them. */
3086 if (fcode == RS6000_BIF_ASSEMBLE_ACC_INTERNAL && !WORDS_BIG_ENDIAN)
3087 {
3088 std::swap (op[1], op[4]);
3089 std::swap (op[2], op[3]);
3090 }
3091 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
3092 break;
3093 case 6:
3094 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
3095 break;
3096 case 7:
3097 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5], op[6]);
3098 break;
3099 default:
3100 gcc_unreachable ();
3101 }
3102
3103 if (!pat)
3104 return NULL_RTX;
3105
3106 emit_insn (pat);
3107 return target;
3108 }
3109
3110 /* Return the correct ICODE value depending on whether we are
3111 setting or reading the HTM SPRs. */
3112 static inline enum insn_code
rs6000_htm_spr_icode(bool nonvoid)3113 rs6000_htm_spr_icode (bool nonvoid)
3114 {
3115 if (nonvoid)
3116 return (TARGET_POWERPC64) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si;
3117 else
3118 return (TARGET_POWERPC64) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si;
3119 }
3120
3121 /* Return the appropriate SPR number associated with the given builtin. */
3122 static inline HOST_WIDE_INT
htm_spr_num(enum rs6000_gen_builtins code)3123 htm_spr_num (enum rs6000_gen_builtins code)
3124 {
3125 if (code == RS6000_BIF_GET_TFHAR
3126 || code == RS6000_BIF_SET_TFHAR)
3127 return TFHAR_SPR;
3128 else if (code == RS6000_BIF_GET_TFIAR
3129 || code == RS6000_BIF_SET_TFIAR)
3130 return TFIAR_SPR;
3131 else if (code == RS6000_BIF_GET_TEXASR
3132 || code == RS6000_BIF_SET_TEXASR)
3133 return TEXASR_SPR;
3134 gcc_assert (code == RS6000_BIF_GET_TEXASRU
3135 || code == RS6000_BIF_SET_TEXASRU);
3136 return TEXASRU_SPR;
3137 }
3138
3139 /* Expand the HTM builtin in EXP and store the result in TARGET.
3140 Return the expanded rtx. */
3141 static rtx
htm_expand_builtin(bifdata * bifaddr,rs6000_gen_builtins fcode,tree exp,rtx target)3142 htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
3143 tree exp, rtx target)
3144 {
3145 if (!TARGET_POWERPC64
3146 && (fcode == RS6000_BIF_TABORTDC
3147 || fcode == RS6000_BIF_TABORTDCI))
3148 {
3149 error ("builtin %qs is only valid in 64-bit mode", bifaddr->bifname);
3150 return const0_rtx;
3151 }
3152
3153 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3154 bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
3155 bool uses_spr = bif_is_htmspr (*bifaddr);
3156 insn_code icode = bifaddr->icode;
3157
3158 if (uses_spr)
3159 icode = rs6000_htm_spr_icode (nonvoid);
3160
3161 rtx op[MAX_HTM_OPERANDS];
3162 int nopnds = 0;
3163 const insn_operand_data *insn_op = &insn_data[icode].operand[0];
3164
3165 if (nonvoid)
3166 {
3167 machine_mode tmode = (uses_spr) ? insn_op->mode : E_SImode;
3168 if (!target
3169 || GET_MODE (target) != tmode
3170 || (uses_spr && !insn_op->predicate (target, tmode)))
3171 target = gen_reg_rtx (tmode);
3172 if (uses_spr)
3173 op[nopnds++] = target;
3174 }
3175
3176 tree arg;
3177 call_expr_arg_iterator iter;
3178
3179 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
3180 {
3181 if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS)
3182 return const0_rtx;
3183
3184 insn_op = &insn_data[icode].operand[nopnds];
3185 op[nopnds] = expand_normal (arg);
3186
3187 if (!insn_op->predicate (op[nopnds], insn_op->mode))
3188 {
3189 /* TODO: This use of constraints could use explanation.
3190 This happens a couple of places, perhaps make that a
3191 function to document what's happening. */
3192 if (!strcmp (insn_op->constraint, "n"))
3193 {
3194 int arg_num = nonvoid ? nopnds : nopnds + 1;
3195 if (!CONST_INT_P (op[nopnds]))
3196 error ("argument %d must be an unsigned literal", arg_num);
3197 else
3198 error ("argument %d is an unsigned literal that is "
3199 "out of range", arg_num);
3200 return const0_rtx;
3201 }
3202 op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]);
3203 }
3204
3205 nopnds++;
3206 }
3207
3208 /* Handle the builtins for extended mnemonics. These accept
3209 no arguments, but map to builtins that take arguments. */
3210 switch (fcode)
3211 {
3212 case RS6000_BIF_TENDALL: /* Alias for: tend. 1 */
3213 case RS6000_BIF_TRESUME: /* Alias for: tsr. 1 */
3214 op[nopnds++] = GEN_INT (1);
3215 break;
3216 case RS6000_BIF_TSUSPEND: /* Alias for: tsr. 0 */
3217 op[nopnds++] = GEN_INT (0);
3218 break;
3219 default:
3220 break;
3221 }
3222
3223 /* If this builtin accesses SPRs, then pass in the appropriate
3224 SPR number and SPR regno as the last two operands. */
3225 rtx cr = NULL_RTX;
3226 if (uses_spr)
3227 {
3228 machine_mode mode = TARGET_POWERPC64 ? DImode : SImode;
3229 op[nopnds++] = gen_rtx_CONST_INT (mode, htm_spr_num (fcode));
3230 }
3231 /* If this builtin accesses a CR field, then pass in a scratch
3232 CR field as the last operand. */
3233 else if (bif_is_htmcr (*bifaddr))
3234 {
3235 cr = gen_reg_rtx (CCmode);
3236 op[nopnds++] = cr;
3237 }
3238
3239 rtx pat;
3240 switch (nopnds)
3241 {
3242 case 1:
3243 pat = GEN_FCN (icode) (op[0]);
3244 break;
3245 case 2:
3246 pat = GEN_FCN (icode) (op[0], op[1]);
3247 break;
3248 case 3:
3249 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
3250 break;
3251 case 4:
3252 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
3253 break;
3254 default:
3255 gcc_unreachable ();
3256 }
3257 if (!pat)
3258 return NULL_RTX;
3259 emit_insn (pat);
3260
3261 if (bif_is_htmcr (*bifaddr))
3262 {
3263 if (fcode == RS6000_BIF_TBEGIN)
3264 {
3265 /* Emit code to set TARGET to true or false depending on
3266 whether the tbegin. instruction succeeded or failed
3267 to start a transaction. We do this by placing the 1's
3268 complement of CR's EQ bit into TARGET. */
3269 rtx scratch = gen_reg_rtx (SImode);
3270 emit_insn (gen_rtx_SET (scratch,
3271 gen_rtx_EQ (SImode, cr,
3272 const0_rtx)));
3273 emit_insn (gen_rtx_SET (target,
3274 gen_rtx_XOR (SImode, scratch,
3275 GEN_INT (1))));
3276 }
3277 else
3278 {
3279 /* Emit code to copy the 4-bit condition register field
3280 CR into the least significant end of register TARGET. */
3281 rtx scratch1 = gen_reg_rtx (SImode);
3282 rtx scratch2 = gen_reg_rtx (SImode);
3283 rtx subreg = simplify_gen_subreg (CCmode, scratch1, SImode, 0);
3284 emit_insn (gen_movcc (subreg, cr));
3285 emit_insn (gen_lshrsi3 (scratch2, scratch1, GEN_INT (28)));
3286 emit_insn (gen_andsi3 (target, scratch2, GEN_INT (0xf)));
3287 }
3288 }
3289
3290 if (nonvoid)
3291 return target;
3292 return const0_rtx;
3293 }
3294
3295 /* Expand an expression EXP that calls a built-in function,
3296 with result going to TARGET if that's convenient
3297 (and in mode MODE if that's convenient).
3298 SUBTARGET may be used as the target for computing one of EXP's operands.
3299 IGNORE is nonzero if the value is to be ignored.
3300 Use the new builtin infrastructure. */
3301 rtx
rs6000_expand_builtin(tree exp,rtx target,rtx,machine_mode,int ignore)3302 rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
3303 machine_mode /* mode */, int ignore)
3304 {
3305 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3306 enum rs6000_gen_builtins fcode
3307 = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
3308
3309 /* Emit error message if it's an unresolved overloaded builtin. */
3310 if (fcode > RS6000_OVLD_NONE)
3311 {
3312 error ("unresolved overload for builtin %qF", fndecl);
3313 return const0_rtx;
3314 }
3315
3316 size_t uns_fcode = (size_t)fcode;
3317 enum insn_code icode = rs6000_builtin_info[uns_fcode].icode;
3318
3319 /* TODO: The following commentary and code is inherited from the original
3320 builtin processing code. The commentary is a bit confusing, with the
3321 intent being that KFmode is always IEEE-128, IFmode is always IBM
3322 double-double, and TFmode is the current long double. The code is
3323 confusing in that it converts from KFmode to TFmode pattern names,
3324 when the other direction is more intuitive. Try to address this. */
3325
3326 /* We have two different modes (KFmode, TFmode) that are the IEEE
3327 128-bit floating point type, depending on whether long double is the
3328 IBM extended double (KFmode) or long double is IEEE 128-bit (TFmode).
3329 It is simpler if we only define one variant of the built-in function,
3330 and switch the code when defining it, rather than defining two built-
3331 ins and using the overload table in rs6000-c.cc to switch between the
3332 two. If we don't have the proper assembler, don't do this switch
3333 because CODE_FOR_*kf* and CODE_FOR_*tf* will be CODE_FOR_nothing. */
3334 if (FLOAT128_IEEE_P (TFmode))
3335 switch (icode)
3336 {
3337 case CODE_FOR_sqrtkf2_odd:
3338 icode = CODE_FOR_sqrttf2_odd;
3339 break;
3340 case CODE_FOR_trunckfdf2_odd:
3341 icode = CODE_FOR_trunctfdf2_odd;
3342 break;
3343 case CODE_FOR_addkf3_odd:
3344 icode = CODE_FOR_addtf3_odd;
3345 break;
3346 case CODE_FOR_subkf3_odd:
3347 icode = CODE_FOR_subtf3_odd;
3348 break;
3349 case CODE_FOR_mulkf3_odd:
3350 icode = CODE_FOR_multf3_odd;
3351 break;
3352 case CODE_FOR_divkf3_odd:
3353 icode = CODE_FOR_divtf3_odd;
3354 break;
3355 case CODE_FOR_fmakf4_odd:
3356 icode = CODE_FOR_fmatf4_odd;
3357 break;
3358 case CODE_FOR_xsxexpqp_kf:
3359 icode = CODE_FOR_xsxexpqp_tf;
3360 break;
3361 case CODE_FOR_xsxsigqp_kf:
3362 icode = CODE_FOR_xsxsigqp_tf;
3363 break;
3364 case CODE_FOR_xststdcnegqp_kf:
3365 icode = CODE_FOR_xststdcnegqp_tf;
3366 break;
3367 case CODE_FOR_xsiexpqp_kf:
3368 icode = CODE_FOR_xsiexpqp_tf;
3369 break;
3370 case CODE_FOR_xsiexpqpf_kf:
3371 icode = CODE_FOR_xsiexpqpf_tf;
3372 break;
3373 case CODE_FOR_xststdcqp_kf:
3374 icode = CODE_FOR_xststdcqp_tf;
3375 break;
3376 case CODE_FOR_xscmpexpqp_eq_kf:
3377 icode = CODE_FOR_xscmpexpqp_eq_tf;
3378 break;
3379 case CODE_FOR_xscmpexpqp_lt_kf:
3380 icode = CODE_FOR_xscmpexpqp_lt_tf;
3381 break;
3382 case CODE_FOR_xscmpexpqp_gt_kf:
3383 icode = CODE_FOR_xscmpexpqp_gt_tf;
3384 break;
3385 case CODE_FOR_xscmpexpqp_unordered_kf:
3386 icode = CODE_FOR_xscmpexpqp_unordered_tf;
3387 break;
3388 default:
3389 break;
3390 }
3391
3392 /* In case of "#pragma target" changes, we initialize all builtins
3393 but check for actual availability now, during expand time. For
3394 invalid builtins, generate a normal call. */
3395 bifdata *bifaddr = &rs6000_builtin_info[uns_fcode];
3396 bif_enable e = bifaddr->enable;
3397
3398 if (!(e == ENB_ALWAYS
3399 || (e == ENB_P5 && TARGET_POPCNTB)
3400 || (e == ENB_P6 && TARGET_CMPB)
3401 || (e == ENB_P6_64 && TARGET_CMPB && TARGET_POWERPC64)
3402 || (e == ENB_ALTIVEC && TARGET_ALTIVEC)
3403 || (e == ENB_CELL && TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL)
3404 || (e == ENB_VSX && TARGET_VSX)
3405 || (e == ENB_P7 && TARGET_POPCNTD)
3406 || (e == ENB_P7_64 && TARGET_POPCNTD && TARGET_POWERPC64)
3407 || (e == ENB_P8 && TARGET_DIRECT_MOVE)
3408 || (e == ENB_P8V && TARGET_P8_VECTOR)
3409 || (e == ENB_P9 && TARGET_MODULO)
3410 || (e == ENB_P9_64 && TARGET_MODULO && TARGET_POWERPC64)
3411 || (e == ENB_P9V && TARGET_P9_VECTOR)
3412 || (e == ENB_IEEE128_HW && TARGET_FLOAT128_HW)
3413 || (e == ENB_DFP && TARGET_DFP)
3414 || (e == ENB_CRYPTO && TARGET_CRYPTO)
3415 || (e == ENB_HTM && TARGET_HTM)
3416 || (e == ENB_P10 && TARGET_POWER10)
3417 || (e == ENB_P10_64 && TARGET_POWER10 && TARGET_POWERPC64)
3418 || (e == ENB_MMA && TARGET_MMA)))
3419 {
3420 rs6000_invalid_builtin (fcode);
3421 return expand_call (exp, target, ignore);
3422 }
3423
3424 if (bif_is_nosoft (*bifaddr)
3425 && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
3426 {
3427 error ("%qs not supported with %<-msoft-float%>",
3428 bifaddr->bifname);
3429 return const0_rtx;
3430 }
3431
3432 if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
3433 {
3434 error ("%qs is not supported in 32-bit mode", bifaddr->bifname);
3435 return const0_rtx;
3436 }
3437
3438 if (bif_is_ibmld (*bifaddr) && !FLOAT128_2REG_P (TFmode))
3439 {
3440 error ("%qs requires %<long double%> to be IBM 128-bit format",
3441 bifaddr->bifname);
3442 return const0_rtx;
3443 }
3444
3445 if (bif_is_ibm128 (*bifaddr) && !ibm128_float_type_node)
3446 {
3447 error ("%qs requires %<__ibm128%> type support",
3448 bifaddr->bifname);
3449 return const0_rtx;
3450 }
3451
3452 if (bif_is_cpu (*bifaddr))
3453 return cpu_expand_builtin (fcode, exp, target);
3454
3455 if (bif_is_init (*bifaddr))
3456 return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
3457
3458 if (bif_is_set (*bifaddr))
3459 return altivec_expand_vec_set_builtin (exp);
3460
3461 if (bif_is_extract (*bifaddr))
3462 return altivec_expand_vec_ext_builtin (exp, target);
3463
3464 if (bif_is_predicate (*bifaddr))
3465 return altivec_expand_predicate_builtin (icode, exp, target);
3466
3467 if (bif_is_htm (*bifaddr))
3468 return htm_expand_builtin (bifaddr, fcode, exp, target);
3469
3470 if (bif_is_32bit (*bifaddr) && TARGET_32BIT)
3471 {
3472 if (fcode == RS6000_BIF_MFTB)
3473 icode = CODE_FOR_rs6000_mftb_si;
3474 else if (fcode == RS6000_BIF_BPERMD)
3475 icode = CODE_FOR_bpermd_si;
3476 else if (fcode == RS6000_BIF_DARN)
3477 icode = CODE_FOR_darn_64_si;
3478 else if (fcode == RS6000_BIF_DARN_32)
3479 icode = CODE_FOR_darn_32_si;
3480 else if (fcode == RS6000_BIF_DARN_RAW)
3481 icode = CODE_FOR_darn_raw_si;
3482 else
3483 gcc_unreachable ();
3484 }
3485
3486 if (bif_is_endian (*bifaddr) && BYTES_BIG_ENDIAN)
3487 {
3488 if (fcode == RS6000_BIF_LD_ELEMREV_V1TI)
3489 icode = CODE_FOR_vsx_load_v1ti;
3490 else if (fcode == RS6000_BIF_LD_ELEMREV_V2DF)
3491 icode = CODE_FOR_vsx_load_v2df;
3492 else if (fcode == RS6000_BIF_LD_ELEMREV_V2DI)
3493 icode = CODE_FOR_vsx_load_v2di;
3494 else if (fcode == RS6000_BIF_LD_ELEMREV_V4SF)
3495 icode = CODE_FOR_vsx_load_v4sf;
3496 else if (fcode == RS6000_BIF_LD_ELEMREV_V4SI)
3497 icode = CODE_FOR_vsx_load_v4si;
3498 else if (fcode == RS6000_BIF_LD_ELEMREV_V8HI)
3499 icode = CODE_FOR_vsx_load_v8hi;
3500 else if (fcode == RS6000_BIF_LD_ELEMREV_V16QI)
3501 icode = CODE_FOR_vsx_load_v16qi;
3502 else if (fcode == RS6000_BIF_ST_ELEMREV_V1TI)
3503 icode = CODE_FOR_vsx_store_v1ti;
3504 else if (fcode == RS6000_BIF_ST_ELEMREV_V2DF)
3505 icode = CODE_FOR_vsx_store_v2df;
3506 else if (fcode == RS6000_BIF_ST_ELEMREV_V2DI)
3507 icode = CODE_FOR_vsx_store_v2di;
3508 else if (fcode == RS6000_BIF_ST_ELEMREV_V4SF)
3509 icode = CODE_FOR_vsx_store_v4sf;
3510 else if (fcode == RS6000_BIF_ST_ELEMREV_V4SI)
3511 icode = CODE_FOR_vsx_store_v4si;
3512 else if (fcode == RS6000_BIF_ST_ELEMREV_V8HI)
3513 icode = CODE_FOR_vsx_store_v8hi;
3514 else if (fcode == RS6000_BIF_ST_ELEMREV_V16QI)
3515 icode = CODE_FOR_vsx_store_v16qi;
3516 else if (fcode == RS6000_BIF_VCLZLSBB_V16QI)
3517 icode = CODE_FOR_vclzlsbb_v16qi;
3518 else if (fcode == RS6000_BIF_VCLZLSBB_V4SI)
3519 icode = CODE_FOR_vclzlsbb_v4si;
3520 else if (fcode == RS6000_BIF_VCLZLSBB_V8HI)
3521 icode = CODE_FOR_vclzlsbb_v8hi;
3522 else if (fcode == RS6000_BIF_VCTZLSBB_V16QI)
3523 icode = CODE_FOR_vctzlsbb_v16qi;
3524 else if (fcode == RS6000_BIF_VCTZLSBB_V4SI)
3525 icode = CODE_FOR_vctzlsbb_v4si;
3526 else if (fcode == RS6000_BIF_VCTZLSBB_V8HI)
3527 icode = CODE_FOR_vctzlsbb_v8hi;
3528 else
3529 gcc_unreachable ();
3530 }
3531
3532 if (bif_is_ibm128 (*bifaddr) && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
3533 {
3534 if (fcode == RS6000_BIF_PACK_IF)
3535 {
3536 icode = CODE_FOR_packtf;
3537 fcode = RS6000_BIF_PACK_TF;
3538 uns_fcode = (size_t) fcode;
3539 }
3540 else if (fcode == RS6000_BIF_UNPACK_IF)
3541 {
3542 icode = CODE_FOR_unpacktf;
3543 fcode = RS6000_BIF_UNPACK_TF;
3544 uns_fcode = (size_t) fcode;
3545 }
3546 }
3547
3548 /* TRUE iff the built-in function returns void. */
3549 bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
3550 /* Position of first argument (0 for void-returning functions, else 1). */
3551 int k;
3552 /* Modes for the return value, if any, and arguments. */
3553 const int MAX_BUILTIN_ARGS = 6;
3554 machine_mode mode[MAX_BUILTIN_ARGS + 1];
3555
3556 if (void_func)
3557 k = 0;
3558 else
3559 {
3560 k = 1;
3561 mode[0] = insn_data[icode].operand[0].mode;
3562 }
3563
3564 /* Tree expressions for each argument. */
3565 tree arg[MAX_BUILTIN_ARGS];
3566 /* RTL expressions for each argument. */
3567 rtx op[MAX_BUILTIN_ARGS];
3568
3569 int nargs = bifaddr->nargs;
3570 gcc_assert (nargs <= MAX_BUILTIN_ARGS);
3571
3572
3573 for (int i = 0; i < nargs; i++)
3574 {
3575 arg[i] = CALL_EXPR_ARG (exp, i);
3576 if (arg[i] == error_mark_node)
3577 return const0_rtx;
3578 STRIP_NOPS (arg[i]);
3579 op[i] = expand_normal (arg[i]);
3580 /* We have a couple of pesky patterns that don't specify the mode... */
3581 mode[i+k] = insn_data[icode].operand[i+k].mode;
3582 if (!mode[i+k])
3583 mode[i+k] = Pmode;
3584 }
3585
3586 /* Check for restricted constant arguments. */
3587 for (int i = 0; i < 2; i++)
3588 {
3589 switch (bifaddr->restr[i])
3590 {
3591 case RES_BITS:
3592 {
3593 size_t mask = 1;
3594 mask <<= bifaddr->restr_val1[i];
3595 mask--;
3596 tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
3597 STRIP_NOPS (restr_arg);
3598 if (!(TREE_CODE (restr_arg) == INTEGER_CST
3599 && (TREE_INT_CST_LOW (restr_arg) & ~mask) == 0))
3600 {
3601 unsigned p = (1U << bifaddr->restr_val1[i]) - 1;
3602 error ("argument %d must be a literal between 0 and %d,"
3603 " inclusive",
3604 bifaddr->restr_opnd[i], p);
3605 return CONST0_RTX (mode[0]);
3606 }
3607 break;
3608 }
3609 case RES_RANGE:
3610 {
3611 tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
3612 STRIP_NOPS (restr_arg);
3613 if (!(TREE_CODE (restr_arg) == INTEGER_CST
3614 && IN_RANGE (tree_to_shwi (restr_arg),
3615 bifaddr->restr_val1[i],
3616 bifaddr->restr_val2[i])))
3617 {
3618 error ("argument %d must be a literal between %d and %d,"
3619 " inclusive",
3620 bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
3621 bifaddr->restr_val2[i]);
3622 return CONST0_RTX (mode[0]);
3623 }
3624 break;
3625 }
3626 case RES_VAR_RANGE:
3627 {
3628 tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
3629 STRIP_NOPS (restr_arg);
3630 if (TREE_CODE (restr_arg) == INTEGER_CST
3631 && !IN_RANGE (tree_to_shwi (restr_arg),
3632 bifaddr->restr_val1[i],
3633 bifaddr->restr_val2[i]))
3634 {
3635 error ("argument %d must be a variable or a literal "
3636 "between %d and %d, inclusive",
3637 bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
3638 bifaddr->restr_val2[i]);
3639 return CONST0_RTX (mode[0]);
3640 }
3641 break;
3642 }
3643 case RES_VALUES:
3644 {
3645 tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
3646 STRIP_NOPS (restr_arg);
3647 if (!(TREE_CODE (restr_arg) == INTEGER_CST
3648 && (tree_to_shwi (restr_arg) == bifaddr->restr_val1[i]
3649 || tree_to_shwi (restr_arg) == bifaddr->restr_val2[i])))
3650 {
3651 error ("argument %d must be either a literal %d or a "
3652 "literal %d",
3653 bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
3654 bifaddr->restr_val2[i]);
3655 return CONST0_RTX (mode[0]);
3656 }
3657 break;
3658 }
3659 default:
3660 case RES_NONE:
3661 break;
3662 }
3663 }
3664
3665 if (bif_is_ldstmask (*bifaddr))
3666 return rs6000_expand_ldst_mask (target, arg[0]);
3667
3668 if (bif_is_stvec (*bifaddr))
3669 {
3670 if (bif_is_reve (*bifaddr))
3671 icode = elemrev_icode (fcode);
3672 return stv_expand_builtin (icode, op, mode[0], mode[1]);
3673 }
3674
3675 if (bif_is_ldvec (*bifaddr))
3676 {
3677 if (bif_is_reve (*bifaddr))
3678 icode = elemrev_icode (fcode);
3679 return ldv_expand_builtin (target, icode, op, mode[0]);
3680 }
3681
3682 if (bif_is_lxvrse (*bifaddr))
3683 return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
3684
3685 if (bif_is_lxvrze (*bifaddr))
3686 return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
3687
3688 if (bif_is_mma (*bifaddr))
3689 return mma_expand_builtin (exp, target, icode, fcode);
3690
3691 if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
3692 target = NULL_RTX;
3693 else if (target == 0
3694 || GET_MODE (target) != mode[0]
3695 || !insn_data[icode].operand[0].predicate (target, mode[0]))
3696 target = gen_reg_rtx (mode[0]);
3697
3698 for (int i = 0; i < nargs; i++)
3699 if (!insn_data[icode].operand[i+k].predicate (op[i], mode[i+k]))
3700 op[i] = copy_to_mode_reg (mode[i+k], op[i]);
3701
3702 rtx pat;
3703
3704 switch (nargs)
3705 {
3706 case 0:
3707 pat = (void_func
3708 ? GEN_FCN (icode) ()
3709 : GEN_FCN (icode) (target));
3710 break;
3711 case 1:
3712 pat = (void_func
3713 ? GEN_FCN (icode) (op[0])
3714 : GEN_FCN (icode) (target, op[0]));
3715 break;
3716 case 2:
3717 pat = (void_func
3718 ? GEN_FCN (icode) (op[0], op[1])
3719 : GEN_FCN (icode) (target, op[0], op[1]));
3720 break;
3721 case 3:
3722 pat = (void_func
3723 ? GEN_FCN (icode) (op[0], op[1], op[2])
3724 : GEN_FCN (icode) (target, op[0], op[1], op[2]));
3725 break;
3726 case 4:
3727 pat = (void_func
3728 ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
3729 : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
3730 break;
3731 case 5:
3732 pat = (void_func
3733 ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
3734 : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
3735 break;
3736 case 6:
3737 pat = (void_func
3738 ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
3739 : GEN_FCN (icode) (target, op[0], op[1],
3740 op[2], op[3], op[4], op[5]));
3741 break;
3742 default:
3743 gcc_assert (MAX_BUILTIN_ARGS == 6);
3744 gcc_unreachable ();
3745 }
3746
3747 if (!pat)
3748 return 0;
3749
3750 emit_insn (pat);
3751 return target;
3752 }
3753