[AArch64] Improve scheduling model for X-Gene
[official-gcc.git] / gcc / config / s390 / s390-c.c
blob07224ad7f394e5f815a750cbca48360143390aaf
1 /* Language specific subroutines used for code generation on IBM S/390
2 and zSeries
3 Copyright (C) 2015-2017 Free Software Foundation, Inc.
5 Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
23 Based on gcc/config/rs6000/rs6000-c.c.
25 In GCC terms this file belongs to the frontend. It will be
26 compiled with -DIN_GCC_FRONTEND. With that rtl.h cannot be
27 included anymore - a mechanism supposed to avoid adding frontend -
28 backend dependencies. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "target.h"
34 #include "tree.h"
35 #include "c-family/c-common.h"
36 #include "c/c-tree.h"
37 #include "memmodel.h"
38 #include "tm_p.h"
39 #include "stringpool.h"
40 #include "c-family/c-pragma.h"
41 #include "langhooks.h"
42 #include "tree-pretty-print.h"
44 #include "s390-builtins.h"
46 static GTY(()) tree __vector_keyword;
47 static GTY(()) tree vector_keyword;
48 static GTY(()) tree __bool_keyword;
49 static GTY(()) tree bool_keyword;
50 static GTY(()) tree _Bool_keyword;
53 /* Generate an array holding all the descriptions of variants of
54 overloaded builtins defined with OB_DEF_VAR in
55 s390-builtins.def. */
56 static enum s390_builtin_ov_type_index
57 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
59 #undef B_DEF
60 #undef OB_DEF
61 #undef OB_DEF_VAR
62 #define B_DEF(...)
63 #define OB_DEF(...)
64 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, OPFLAGS, FNTYPE) FNTYPE,
65 #include "s390-builtins.def"
66 BT_OV_MAX
70 /* Generate an array indexed by an overloaded builtin index returning
71 the first index in desc_for_overloaded_builtin_var where the
72 variants for the builtin can be found. */
73 static enum s390_overloaded_builtin_vars
74 desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
76 #undef B_DEF
77 #undef OB_DEF
78 #undef OB_DEF_VAR
79 #define B_DEF(...)
80 #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
81 S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
82 #define OB_DEF_VAR(...)
83 #include "s390-builtins.def"
84 S390_OVERLOADED_BUILTIN_VAR_MAX
87 /* Generate an array indexed by an overloaded builtin index returning
88 the last index in desc_for_overloaded_builtin_var where the
89 variants for the builtin can be found. */
90 static enum s390_overloaded_builtin_vars
91 desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
93 #undef B_DEF
94 #undef OB_DEF
95 #undef OB_DEF_VAR
96 #define B_DEF(...)
97 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
98 S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
99 #define OB_DEF_VAR(...)
100 #include "s390-builtins.def"
101 S390_OVERLOADED_BUILTIN_VAR_MAX
104 static enum s390_builtin_type_index
105 s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
107 #undef DEF_TYPE
108 #undef DEF_POINTER_TYPE
109 #undef DEF_DISTINCT_TYPE
110 #undef DEF_VECTOR_TYPE
111 #undef DEF_OPAQUE_VECTOR_TYPE
112 #undef DEF_FN_TYPE
113 #undef DEF_OV_TYPE
114 #define DEF_TYPE(...)
115 #define DEF_POINTER_TYPE(...)
116 #define DEF_DISTINCT_TYPE(...)
117 #define DEF_VECTOR_TYPE(...)
118 #define DEF_OPAQUE_VECTOR_TYPE(...)
119 #define DEF_FN_TYPE(...)
120 #define DEF_OV_TYPE(INDEX, args...) { args },
121 #include "s390-builtin-types.def"
124 static const enum s390_builtins
125 bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
126 #undef B_DEF
127 #undef OB_DEF
128 #undef OB_DEF_VAR
129 #define B_DEF(...)
130 #define OB_DEF(...)
131 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
133 #include "s390-builtins.def"
136 /* In addition to calling fold_convert for EXPR of type TYPE, also
137 call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
138 hiding there (PR47197). */
139 tree
140 fully_fold_convert (tree type, tree expr)
142 tree result = fold_convert (type, expr);
143 bool maybe_const = true;
145 if (!c_dialect_cxx ())
146 result = c_fully_fold (result, false, &maybe_const);
148 return result;
151 /* Unify the different variants to the same nodes in order to keep the
152 code working with it simple. */
153 static cpp_hashnode *
154 s390_categorize_keyword (const cpp_token *tok)
156 if (tok->type == CPP_NAME)
158 cpp_hashnode *ident = tok->val.node.node;
160 if (ident == C_CPP_HASHNODE (vector_keyword))
161 return C_CPP_HASHNODE (__vector_keyword);
163 if (ident == C_CPP_HASHNODE (bool_keyword))
164 return C_CPP_HASHNODE (__bool_keyword);
166 if (ident == C_CPP_HASHNODE (_Bool_keyword))
167 return C_CPP_HASHNODE (__bool_keyword);
168 return ident;
171 return 0;
175 /* Called to decide whether a conditional macro should be expanded.
176 Since we have exactly one such macro (i.e, 'vector'), we do not
177 need to examine the 'tok' parameter. */
179 static cpp_hashnode *
180 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
182 cpp_hashnode *expand_this = tok->val.node.node;
183 cpp_hashnode *ident;
184 static bool expand_bool_p = false;
185 int idx = 0;
186 enum rid rid_code;
188 /* The vector keyword is only expanded if the machine actually
189 provides hardware support. */
190 if (!TARGET_ZVECTOR)
191 return NULL;
193 ident = s390_categorize_keyword (tok);
195 /* Triggered when we picked a different variant in
196 s390_categorize_keyword. */
197 if (ident != expand_this)
198 expand_this = NULL;
200 /* The vector keyword has been found already and we remembered to
201 expand the next bool. */
202 if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
204 expand_bool_p = false;
205 return ident;
208 if (ident != C_CPP_HASHNODE (__vector_keyword))
209 return expand_this;
212 tok = cpp_peek_token (pfile, idx++);
213 while (tok->type == CPP_PADDING);
214 ident = s390_categorize_keyword (tok);
216 if (!ident)
217 return expand_this;
219 /* vector bool - remember to expand the next bool. */
220 if (ident == C_CPP_HASHNODE (__bool_keyword))
222 expand_bool_p = true;
223 return C_CPP_HASHNODE (__vector_keyword);
226 /* The boost libraries have code with Iterator::vector vector in it.
227 If we allow the normal handling, this module will be called
228 recursively, and the vector will be skipped.; */
229 if (ident == C_CPP_HASHNODE (__vector_keyword))
230 return expand_this;
232 rid_code = (enum rid)(ident->rid_code);
234 if (ident->type == NT_MACRO)
236 /* Now actually fetch the tokens we "peeked" before and do a
237 lookahead for the next. */
239 (void) cpp_get_token (pfile);
240 while (--idx > 0);
242 tok = cpp_peek_token (pfile, idx++);
243 while (tok->type == CPP_PADDING);
244 ident = s390_categorize_keyword (tok);
246 if (ident == C_CPP_HASHNODE (__bool_keyword))
248 expand_bool_p = true;
249 return C_CPP_HASHNODE (__vector_keyword);
251 else if (ident)
252 rid_code = (enum rid)(ident->rid_code);
255 /* vector keyword followed by type identifier: vector unsigned,
256 vector long, ...
257 Types consisting of more than one identifier are not supported by
258 zvector e.g. long long, long double, unsigned long int. */
259 if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
260 || rid_code == RID_SHORT || rid_code == RID_SIGNED
261 || rid_code == RID_INT || rid_code == RID_CHAR
262 || (rid_code == RID_FLOAT && TARGET_VXE)
263 || rid_code == RID_DOUBLE)
265 expand_this = C_CPP_HASHNODE (__vector_keyword);
266 /* If the next keyword is bool, it will need to be expanded as
267 well. */
269 tok = cpp_peek_token (pfile, idx++);
270 while (tok->type == CPP_PADDING);
271 ident = s390_categorize_keyword (tok);
273 /* __vector long __bool a; */
274 if (ident == C_CPP_HASHNODE (__bool_keyword))
275 expand_bool_p = true;
276 else
278 /* Triggered with: __vector long long __bool a; */
280 tok = cpp_peek_token (pfile, idx++);
281 while (tok->type == CPP_PADDING);
282 ident = s390_categorize_keyword (tok);
284 if (ident == C_CPP_HASHNODE (__bool_keyword))
285 expand_bool_p = true;
289 return expand_this;
292 /* Helper function that defines or undefines macros. If SET is true, the macro
293 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
294 Nothing is done if SET and WAS_SET have the same value. */
295 static void
296 s390_def_or_undef_macro (cpp_reader *pfile,
297 unsigned int mask,
298 const struct cl_target_option *old_opts,
299 const struct cl_target_option *new_opts,
300 const char *macro_def, const char *macro_undef)
302 bool was_set;
303 bool set;
305 was_set = (!old_opts) ? false : old_opts->x_target_flags & mask;
306 set = new_opts->x_target_flags & mask;
307 if (was_set == set)
308 return;
309 if (set)
310 cpp_define (pfile, macro_def);
311 else
312 cpp_undef (pfile, macro_undef);
315 /* Internal function to either define or undef the appropriate system
316 macros. */
317 static void
318 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
319 struct cl_target_option *opts,
320 const struct cl_target_option *old_opts)
322 s390_def_or_undef_macro (pfile, MASK_OPT_HTM, old_opts, opts,
323 "__HTM__", "__HTM__");
324 s390_def_or_undef_macro (pfile, MASK_OPT_VX, old_opts, opts,
325 "__VX__", "__VX__");
326 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
327 "__VEC__=10302", "__VEC__");
328 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
329 "__vector=__attribute__((vector_size(16)))",
330 "__vector__");
331 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
332 "__bool=__attribute__((s390_vector_bool)) unsigned",
333 "__bool");
335 char macro_def[64];
336 int arch_level;
337 gcc_assert (s390_arch != PROCESSOR_NATIVE);
338 arch_level = (int)s390_arch + 3;
339 if (s390_arch >= PROCESSOR_2094_Z9_EC)
340 /* Z9_EC has the same level as Z9_109. */
341 arch_level--;
342 /* Review when a new arch is added and increase the value. */
343 char dummy[(PROCESSOR_max > 12) ? -1 : 1] __attribute__((unused));
344 sprintf (macro_def, "__ARCH__=%d", arch_level);
345 cpp_undef (pfile, "__ARCH__");
346 cpp_define (pfile, macro_def);
349 if (!flag_iso)
351 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
352 "__VECTOR_KEYWORD_SUPPORTED__",
353 "__VECTOR_KEYWORD_SUPPORTED__");
354 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
355 "vector=vector", "vector");
356 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
357 "bool=bool", "bool");
358 if (TARGET_ZVECTOR_P (opts->x_target_flags) && __vector_keyword == NULL)
360 __vector_keyword = get_identifier ("__vector");
361 C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
363 vector_keyword = get_identifier ("vector");
364 C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
366 __bool_keyword = get_identifier ("__bool");
367 C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
369 bool_keyword = get_identifier ("bool");
370 C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
372 _Bool_keyword = get_identifier ("_Bool");
373 C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
375 /* Enable context-sensitive macros. */
376 cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
381 /* Define platform dependent macros. */
382 void
383 s390_cpu_cpp_builtins (cpp_reader *pfile)
385 struct cl_target_option opts;
387 cpp_assert (pfile, "cpu=s390");
388 cpp_assert (pfile, "machine=s390");
389 cpp_define (pfile, "__s390__");
390 if (TARGET_ZARCH)
391 cpp_define (pfile, "__zarch__");
392 if (TARGET_64BIT)
393 cpp_define (pfile, "__s390x__");
394 if (TARGET_LONG_DOUBLE_128)
395 cpp_define (pfile, "__LONG_DOUBLE_128__");
396 cl_target_option_save (&opts, &global_options);
397 s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
400 #if S390_USE_TARGET_ATTRIBUTE
401 /* Hook to validate the current #pragma GCC target and set the state, and
402 update the macros based on what was changed. If ARGS is NULL, then
403 POP_TARGET is used to reset the options. */
405 static bool
406 s390_pragma_target_parse (tree args, tree pop_target)
408 tree prev_tree = build_target_option_node (&global_options);
409 tree cur_tree;
411 if (! args)
412 cur_tree = pop_target;
413 else
415 cur_tree = s390_valid_target_attribute_tree (args, &global_options,
416 &global_options_set, true);
417 if (!cur_tree || cur_tree == error_mark_node)
419 cl_target_option_restore (&global_options,
420 TREE_TARGET_OPTION (prev_tree));
421 return false;
425 target_option_current_node = cur_tree;
426 s390_activate_target_options (target_option_current_node);
429 struct cl_target_option *prev_opt;
430 struct cl_target_option *cur_opt;
432 /* Figure out the previous/current differences. */
433 prev_opt = TREE_TARGET_OPTION (prev_tree);
434 cur_opt = TREE_TARGET_OPTION (cur_tree);
436 /* For the definitions, ensure all newly defined macros are considered
437 as used for -Wunused-macros. There is no point warning about the
438 compiler predefined macros. */
439 cpp_options *cpp_opts = cpp_get_options (parse_in);
440 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
442 cpp_opts->warn_unused_macros = 0;
444 /* Define all of the macros for new options that were just turned on. */
445 s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
447 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
450 return true;
452 #endif
454 /* Expand builtins which can directly be mapped to tree expressions.
455 LOC - location information
456 FCODE - function code of the builtin
457 ARGLIST - value supposed to be passed as arguments
458 RETURN-TYPE - expected return type of the builtin */
459 static tree
460 s390_expand_overloaded_builtin (location_t loc,
461 unsigned fcode,
462 vec<tree, va_gc> *arglist,
463 tree return_type)
465 switch (fcode)
467 case S390_OVERLOADED_BUILTIN_s390_vec_step:
468 if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
470 error_at (loc, "builtin vec_step can only be used on vector types.");
471 return error_mark_node;
473 return build_int_cst (NULL_TREE,
474 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
475 case S390_OVERLOADED_BUILTIN_s390_vec_xl:
476 case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
477 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
478 return build2 (MEM_REF, return_type,
479 fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
480 build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
481 case S390_OVERLOADED_BUILTIN_s390_vec_xst:
482 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
483 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
484 return build2 (MODIFY_EXPR, TREE_TYPE((*arglist)[0]),
485 build1 (INDIRECT_REF, TREE_TYPE((*arglist)[0]),
486 fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
487 (*arglist)[0]);
488 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
489 return build_constructor_va (return_type, 2,
490 NULL_TREE, (*arglist)[0],
491 NULL_TREE, (*arglist)[1]);
492 default:
493 gcc_unreachable ();
497 /* invert result */
498 #define __VSTRING_FLAG_IN 8
499 /* result type */
500 #define __VSTRING_FLAG_RT 4
501 /* zero search */
502 #define __VSTRING_FLAG_ZS 2
503 /* set condition code */
504 #define __VSTRING_FLAG_CS 1
506 /* Return the flags value to be used for string low-level builtins
507 when expanded from overloaded builtin OB_FCODE. */
508 static unsigned int
509 s390_get_vstring_flags (int ob_fcode)
511 unsigned int flags = 0;
513 switch (ob_fcode)
515 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
516 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
517 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
518 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
519 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
520 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
521 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
522 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
523 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
524 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
525 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
526 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
527 flags |= __VSTRING_FLAG_IN;
528 break;
529 default:
530 break;
532 switch (ob_fcode)
535 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
536 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
537 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
538 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
539 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
540 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
541 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
542 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
543 flags |= __VSTRING_FLAG_RT;
544 break;
545 default:
546 break;
548 switch (ob_fcode)
551 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
552 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
553 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
554 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
555 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
556 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
557 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
558 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
559 flags |= __VSTRING_FLAG_ZS;
560 break;
561 default:
562 break;
564 switch (ob_fcode)
566 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
567 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
568 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
569 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
570 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
571 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
572 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
573 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
574 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
575 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
576 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
577 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
578 flags |= __VSTRING_FLAG_CS;
579 break;
580 default:
581 break;
583 return flags;
585 #undef __VSTRING_FLAG_IN
586 #undef __VSTRING_FLAG_RT
587 #undef __VSTRING_FLAG_ZS
588 #undef __VSTRING_FLAG_CS
590 /* For several overloaded builtins the argument lists do not match
591 exactly the signature of a low-level builtin. This function
592 adjusts the argument list ARGLIST for the overloaded builtin
593 OB_FCODE to the signature of the low-level builtin given by
594 DECL. */
595 static void
596 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
597 vec<tree, va_gc> **arglist)
599 tree arg_chain;
600 int src_arg_index, dest_arg_index;
601 vec<tree, va_gc> *folded_args = NULL;
603 /* We at most add one more operand to the list. */
604 vec_alloc (folded_args, (*arglist)->allocated () + 1);
605 for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
606 src_arg_index = 0, dest_arg_index = 0;
607 !VOID_TYPE_P (TREE_VALUE (arg_chain));
608 arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
610 bool arg_assigned_p = false;
611 switch (ob_fcode)
613 /* For all these the low level builtin needs an additional flags parameter. */
614 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
615 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
616 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
617 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
618 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
619 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
620 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
621 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
622 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
623 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
624 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
625 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
626 if (dest_arg_index == 2)
628 folded_args->quick_push (build_int_cst (integer_type_node,
629 s390_get_vstring_flags (ob_fcode)));
630 arg_assigned_p = true;
632 break;
633 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
634 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
635 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
636 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
637 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
638 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
639 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
640 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
641 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
642 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
643 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
644 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
645 if (dest_arg_index == 3)
647 folded_args->quick_push (build_int_cst (integer_type_node,
648 s390_get_vstring_flags (ob_fcode)));
649 arg_assigned_p = true;
651 break;
652 case S390_OVERLOADED_BUILTIN_s390_vec_sel:
653 case S390_OVERLOADED_BUILTIN_s390_vec_insert:
654 case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
655 /* Swap the first to arguments. It is better to do it here
656 instead of the header file to avoid operand checking
657 throwing error messages for a weird operand index. */
658 if (dest_arg_index < 2)
660 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
661 (**arglist)[1 - dest_arg_index]));
662 src_arg_index++;
663 arg_assigned_p = true;
665 break;
666 case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
667 if (dest_arg_index == 1 || dest_arg_index == 2)
669 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
670 (**arglist)[3 - dest_arg_index]));
671 src_arg_index++;
672 arg_assigned_p = true;
674 break;
676 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
678 int code;
679 if (dest_arg_index == 1)
681 tree arg = (**arglist)[src_arg_index];
683 if (TREE_CODE (arg) != INTEGER_CST)
685 error ("constant value required for builtin %qF argument %d",
686 decl, src_arg_index + 1);
687 return;
690 switch (tree_to_uhwi (arg))
692 case 64: code = 0; break;
693 case 128: code = 1; break;
694 case 256: code = 2; break;
695 case 512: code = 3; break;
696 case 1024: code = 4; break;
697 case 2048: code = 5; break;
698 case 4096: code = 6; break;
699 default:
700 error ("valid values for builtin %qF argument %d are 64, "
701 "128, 256, 512, 1024, 2048, and 4096", decl,
702 src_arg_index + 1);
703 return;
705 folded_args->quick_push (build_int_cst (integer_type_node,
706 code));
707 src_arg_index++;
708 arg_assigned_p = true;
711 break;
712 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
713 /* Duplicate the first src arg. */
714 if (dest_arg_index == 0)
716 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
717 (**arglist)[src_arg_index]));
718 arg_assigned_p = true;
720 break;
721 default:
722 break;
724 if (!arg_assigned_p)
726 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
727 (**arglist)[src_arg_index]));
728 src_arg_index++;
731 *arglist = folded_args;
734 /* Check whether the arguments in ARGLIST match the function type
735 DEF_TYPE. Return the number of argument types which required
736 conversion/promotion in order to make it match.
737 0 stands for a perfect match - all operand types match without changes
738 INT_MAX stands for a mismatch. */
739 static int
740 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
741 vec<tree, va_gc> *arglist)
743 unsigned int i;
744 int match_type = 0;
746 for (i = 0; i < vec_safe_length (arglist); i++)
748 tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
749 tree in_arg = (*arglist)[i];
750 tree in_type = TREE_TYPE (in_arg);
752 if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
754 /* Vector types have to match precisely. */
755 if (b_arg_type != in_type
756 && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
757 goto mismatch;
760 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
761 continue;
763 if (lang_hooks.types_compatible_p (
764 lang_hooks.types.type_promotes_to (in_type),
765 lang_hooks.types.type_promotes_to (b_arg_type)))
767 match_type++;
768 continue;
771 /* In this stage the C++ frontend would go ahead trying to find
772 implicit conversion chains for the argument to match the
773 target type. We will mimic this here only for our limited
774 subset of argument types. */
775 if (TREE_CODE (b_arg_type) == INTEGER_TYPE
776 && TREE_CODE (in_type) == INTEGER_TYPE)
778 match_type++;
779 continue;
782 /* If the incoming pointer argument has more qualifiers than the
783 argument type it can still be an imperfect match. */
784 if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
785 && !(TYPE_QUALS (TREE_TYPE (in_type))
786 & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
787 && (TYPE_QUALS (TREE_TYPE (b_arg_type))
788 & ~TYPE_QUALS (TREE_TYPE (in_type))))
790 tree qual_in_type =
791 build_qualified_type (TREE_TYPE (in_type),
792 TYPE_QUALS (TREE_TYPE (b_arg_type)));
794 if (lang_hooks.types_compatible_p (qual_in_type,
795 TREE_TYPE (b_arg_type)))
797 match_type++;
798 continue;
802 mismatch:
803 if (TARGET_DEBUG_ARG)
804 fprintf (stderr, " mismatch in operand: %d\n", i + 1);
805 return INT_MAX;
808 return match_type;
811 /* Return the number of elements in the vector arguments of FNDECL in
812 case all it matches for all vector arguments, -1 otherwise. */
813 static int
814 s390_vec_n_elem (tree fndecl)
816 tree b_arg_chain;
817 int n_elem = -1;
819 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
820 n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
822 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
823 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
824 b_arg_chain = TREE_CHAIN (b_arg_chain))
826 int tmp_n_elem;
827 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
828 continue;
829 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
830 if (n_elem != -1 && n_elem != tmp_n_elem)
831 return -1;
832 n_elem = tmp_n_elem;
834 return n_elem;
838 /* Return a tree expression for a call to the overloaded builtin
839 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
840 tree
841 s390_resolve_overloaded_builtin (location_t loc,
842 tree ob_fndecl,
843 void *passed_arglist)
845 vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
846 unsigned int in_args_num = vec_safe_length (arglist);
847 unsigned int ob_args_num = 0;
848 unsigned int ob_fcode = DECL_FUNCTION_CODE (ob_fndecl);
849 enum s390_overloaded_builtin_vars bindex;
850 unsigned int i;
851 int last_match_type = INT_MAX;
852 int last_match_index = -1;
853 unsigned int all_op_flags;
854 const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
855 int num_matches = 0;
856 tree target_builtin_decl, b_arg_chain, return_type;
857 enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
859 if (TARGET_DEBUG_ARG)
860 fprintf (stderr,
861 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
862 (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
863 ob_fcode < S390_BUILTIN_MAX ? "not" : "");
865 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
866 if (ob_fcode < S390_BUILTIN_MAX)
868 if (ob_flags & B_INT)
870 error_at (loc,
871 "builtin %qF is for GCC internal use only.",
872 ob_fndecl);
873 return error_mark_node;
875 return NULL_TREE;
878 if (ob_flags & B_DEP)
879 warning_at (loc, 0, "builtin %qF is deprecated.", ob_fndecl);
881 if (!TARGET_VX && (ob_flags & B_VX))
883 error_at (loc, "%qF requires -mvx", ob_fndecl);
884 return error_mark_node;
887 if (!TARGET_VXE && (ob_flags & B_VXE))
889 error_at (loc, "%qF requires z14 or higher", ob_fndecl);
890 return error_mark_node;
893 ob_fcode -= S390_BUILTIN_MAX;
895 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
896 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
897 b_arg_chain = TREE_CHAIN (b_arg_chain))
898 ob_args_num++;
900 if (ob_args_num != in_args_num)
902 error_at (loc,
903 "mismatch in number of arguments for builtin %qF. "
904 "Expected: %d got %d", ob_fndecl,
905 ob_args_num, in_args_num);
906 return error_mark_node;
909 for (i = 0; i < in_args_num; i++)
910 if ((*arglist)[i] == error_mark_node)
911 return error_mark_node;
913 /* Overloaded builtins without any variants are directly expanded here. */
914 if (desc_start_for_overloaded_builtin[ob_fcode] ==
915 S390_OVERLOADED_BUILTIN_VAR_MAX)
916 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
918 for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
919 bindex <= desc_end_for_overloaded_builtin[ob_fcode];
920 bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
922 int match_type;
923 enum s390_builtin_ov_type_index type_index =
924 type_for_overloaded_builtin_var[bindex];
926 if (TARGET_DEBUG_ARG)
927 fprintf (stderr, "checking variant number: %d", (int)bindex);
929 match_type = s390_fn_types_compatible (type_index, arglist);
931 if (match_type == INT_MAX)
932 continue;
934 if (TARGET_DEBUG_ARG)
935 fprintf (stderr,
936 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
937 match_type);
939 if (match_type < last_match_type)
941 num_matches = 1;
942 last_match_type = match_type;
943 last_match_fntype_index = type_index;
944 last_match_index = bindex;
946 else if (match_type == last_match_type)
947 num_matches++;
950 if (last_match_type == INT_MAX)
952 error_at (loc, "invalid parameter combination for intrinsic %qs",
953 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
954 return error_mark_node;
956 else if (num_matches > 1)
958 error_at (loc, "ambiguous overload for intrinsic %qs",
959 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
960 return error_mark_node;
963 if (!TARGET_VXE
964 && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
966 error_at (loc, "%qs matching variant requires z14 or higher",
967 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
968 return error_mark_node;
971 if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
972 warning_at (loc, 0, "%qs matching variant is deprecated.",
973 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
975 /* Overloaded variants which have MAX set as low level builtin are
976 supposed to be replaced during expansion with something else. */
977 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
978 target_builtin_decl = ob_fndecl;
979 else
980 target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
982 all_op_flags = opflags_overloaded_builtin_var[last_match_index];
983 return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
985 /* Check for the operand flags in the overloaded builtin variant. */
986 for (i = 0; i < ob_args_num; i++)
988 unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
989 tree arg = (*arglist)[i];
990 tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
992 all_op_flags = all_op_flags >> O_SHIFT;
994 if (op_flags == O_ELEM)
996 int n_elem = s390_vec_n_elem (target_builtin_decl);
997 gcc_assert (n_elem > 0);
998 gcc_assert (type == integer_type_node);
999 (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
1000 fold_convert (integer_type_node, arg),
1001 build_int_cst (NULL_TREE, n_elem - 1));
1004 if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
1005 continue;
1007 if ((TYPE_UNSIGNED (type)
1008 && !int_fits_type_p (arg, c_common_unsigned_type (type)))
1009 || (!TYPE_UNSIGNED (type)
1010 && !int_fits_type_p (arg, c_common_signed_type (type))))
1012 error("constant argument %d for builtin %qF is out "
1013 "of range for target type",
1014 i + 1, target_builtin_decl);
1015 return error_mark_node;
1018 if (TREE_CODE (arg) == INTEGER_CST
1019 && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
1020 return error_mark_node;
1023 /* Handle builtins we expand directly - without mapping it to a low
1024 level builtin. */
1025 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1026 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
1028 s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
1030 if (VOID_TYPE_P (return_type))
1031 return build_function_call_vec (loc, vNULL, target_builtin_decl,
1032 arglist, NULL);
1033 else
1034 return fully_fold_convert (return_type,
1035 build_function_call_vec (loc, vNULL, target_builtin_decl,
1036 arglist, NULL));
1039 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
1040 void
1041 s390_register_target_pragmas (void)
1043 targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
1044 #if S390_USE_TARGET_ATTRIBUTE
1045 /* Update pragma hook to allow parsing #pragma GCC target. */
1046 targetm.target_option.pragma_parse = s390_pragma_target_parse;
1047 #endif