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