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