xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/rs6000/rs6000-builtin.cc (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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