Line data Source code
1 : /* Mapping from optabs to underlying library functions
2 : Copyright (C) 1987-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "target.h"
25 : #include "insn-codes.h"
26 : #include "optabs-libfuncs.h"
27 : #include "libfuncs.h"
28 : #include "optabs-query.h"
29 : #include "tree.h"
30 : #include "stringpool.h"
31 : #include "varasm.h"
32 : #include "stor-layout.h"
33 : #include "rtl.h"
34 :
35 : struct target_libfuncs default_target_libfuncs;
36 : #if SWITCHABLE_TARGET
37 : struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
38 : #endif
39 :
40 : #define libfunc_hash \
41 : (this_target_libfuncs->x_libfunc_hash)
42 :
43 : /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
44 : #if ENABLE_DECIMAL_BID_FORMAT
45 : #define DECIMAL_PREFIX "bid_"
46 : #else
47 : #define DECIMAL_PREFIX "dpd_"
48 : #endif
49 :
50 : /* Used for libfunc_hash. */
51 :
52 : hashval_t
53 33559262 : libfunc_hasher::hash (libfunc_entry *e)
54 : {
55 33559262 : return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
56 : }
57 :
58 : /* Used for libfunc_hash. */
59 :
60 : bool
61 27259854 : libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
62 : {
63 27259854 : return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
64 : }
65 :
66 : /* Return libfunc corresponding operation defined by OPTAB converting
67 : from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
68 : if no libfunc is available. */
69 : rtx
70 42242 : convert_optab_libfunc (convert_optab optab, machine_mode mode1,
71 : machine_mode mode2)
72 : {
73 42242 : struct libfunc_entry e;
74 42242 : struct libfunc_entry **slot;
75 :
76 : /* ??? This ought to be an assert, but not all of the places
77 : that we expand optabs know about the optabs that got moved
78 : to being direct. */
79 42242 : if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
80 : return NULL_RTX;
81 :
82 42242 : e.op = optab;
83 42242 : e.mode1 = mode1;
84 42242 : e.mode2 = mode2;
85 42242 : slot = libfunc_hash->find_slot (&e, NO_INSERT);
86 42242 : if (!slot)
87 : {
88 3406 : const struct convert_optab_libcall_d *d
89 3406 : = &convlib_def[optab - FIRST_CONV_OPTAB];
90 :
91 3406 : if (d->libcall_gen == NULL)
92 : return NULL;
93 :
94 3406 : d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
95 3406 : slot = libfunc_hash->find_slot (&e, NO_INSERT);
96 3406 : if (!slot)
97 : return NULL;
98 : }
99 42242 : return (*slot)->libfunc;
100 : }
101 :
102 : /* Return libfunc corresponding operation defined by OPTAB in MODE.
103 : Trigger lazy initialization if needed, return NULL if no libfunc is
104 : available. */
105 : rtx
106 2523900 : optab_libfunc (optab optab, machine_mode mode)
107 : {
108 2523900 : struct libfunc_entry e;
109 2523900 : struct libfunc_entry **slot;
110 :
111 : /* ??? This ought to be an assert, but not all of the places
112 : that we expand optabs know about the optabs that got moved
113 : to being direct. */
114 2523900 : if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
115 : return NULL_RTX;
116 :
117 1852403 : e.op = optab;
118 1852403 : e.mode1 = mode;
119 1852403 : e.mode2 = VOIDmode;
120 1852403 : slot = libfunc_hash->find_slot (&e, NO_INSERT);
121 1852403 : if (!slot)
122 : {
123 1688097 : const struct optab_libcall_d *d
124 1688097 : = &normlib_def[optab - FIRST_NORM_OPTAB];
125 :
126 1688097 : if (d->libcall_gen == NULL)
127 : return NULL;
128 :
129 1352147 : d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
130 1352147 : slot = libfunc_hash->find_slot (&e, NO_INSERT);
131 1352147 : if (!slot)
132 : return NULL;
133 : }
134 182306 : return (*slot)->libfunc;
135 : }
136 :
137 : /* Initialize the libfunc fields of an entire group of entries in some
138 : optab. Each entry is set equal to a string consisting of a leading
139 : pair of underscores followed by a generic operation name followed by
140 : a mode name (downshifted to lowercase) followed by a single character
141 : representing the number of operands for the given operation (which is
142 : usually one of the characters '2', '3', or '4').
143 :
144 : OPTABLE is the table in which libfunc fields are to be initialized.
145 : OPNAME is the generic (string) name of the operation.
146 : SUFFIX is the character which specifies the number of operands for
147 : the given generic operation.
148 : MODE is the mode to generate for. */
149 :
150 : static void
151 17916 : gen_libfunc (optab optable, const char *opname, int suffix,
152 : machine_mode mode)
153 : {
154 17916 : unsigned opname_len = strlen (opname);
155 17916 : const char *mname = GET_MODE_NAME (mode);
156 17916 : unsigned mname_len = strlen (mname);
157 17916 : int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
158 17916 : int len = prefix_len + opname_len + mname_len + 1 + 1;
159 17916 : char *libfunc_name = XALLOCAVEC (char, len);
160 17916 : char *p;
161 17916 : const char *q;
162 :
163 17916 : p = libfunc_name;
164 17916 : *p++ = '_';
165 17916 : *p++ = '_';
166 17916 : if (targetm.libfunc_gnu_prefix)
167 : {
168 0 : *p++ = 'g';
169 0 : *p++ = 'n';
170 0 : *p++ = 'u';
171 0 : *p++ = '_';
172 : }
173 84307 : for (q = opname; *q;)
174 66391 : *p++ = *q++;
175 53748 : for (q = mname; *q; q++)
176 35832 : *p++ = TOLOWER (*q);
177 17916 : *p++ = suffix;
178 17916 : *p = '\0';
179 :
180 17916 : set_optab_libfunc (optable, mode,
181 17916 : ggc_alloc_string (libfunc_name, p - libfunc_name));
182 17916 : }
183 :
184 : /* Like gen_libfunc, but verify that integer operation is involved. */
185 :
186 : void
187 1345086 : gen_int_libfunc (optab optable, const char *opname, char suffix,
188 : machine_mode mode)
189 : {
190 1345086 : int maxsize = 2 * BITS_PER_WORD;
191 1345086 : int minsize = BITS_PER_WORD;
192 1345086 : scalar_int_mode int_mode;
193 :
194 1345086 : if (!is_int_mode (mode, &int_mode))
195 1345086 : return;
196 41461 : if (maxsize < LONG_LONG_TYPE_SIZE)
197 : maxsize = LONG_LONG_TYPE_SIZE;
198 41461 : if (minsize > INT_TYPE_SIZE
199 80690 : && (trapv_binoptab_p (optable)
200 39229 : || trapv_unoptab_p (optable)))
201 : minsize = INT_TYPE_SIZE;
202 55087 : if (GET_MODE_BITSIZE (int_mode) < minsize
203 55087 : || GET_MODE_BITSIZE (int_mode) > maxsize)
204 : return;
205 12506 : gen_libfunc (optable, opname, suffix, int_mode);
206 : }
207 :
208 : /* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
209 :
210 : void
211 5410 : gen_fp_libfunc (optab optable, const char *opname, char suffix,
212 : machine_mode mode)
213 : {
214 5410 : char *dec_opname;
215 :
216 5410 : if (GET_MODE_CLASS (mode) == MODE_FLOAT)
217 3707 : gen_libfunc (optable, opname, suffix, mode);
218 5410 : if (DECIMAL_FLOAT_MODE_P (mode))
219 : {
220 1703 : dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
221 : /* For BID support, change the name to have either a bid_ or dpd_ prefix
222 : depending on the low level floating format used. */
223 1703 : memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
224 1703 : strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
225 1703 : gen_libfunc (optable, dec_opname, suffix, mode);
226 : }
227 5410 : }
228 :
229 : /* Like gen_libfunc, but verify that fixed-point operation is involved. */
230 :
231 : void
232 0 : gen_fixed_libfunc (optab optable, const char *opname, char suffix,
233 : machine_mode mode)
234 : {
235 0 : if (!ALL_FIXED_POINT_MODE_P (mode))
236 : return;
237 0 : gen_libfunc (optable, opname, suffix, mode);
238 : }
239 :
240 : /* Like gen_libfunc, but verify that signed fixed-point operation is
241 : involved. */
242 :
243 : void
244 0 : gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
245 : machine_mode mode)
246 : {
247 0 : if (!SIGNED_FIXED_POINT_MODE_P (mode))
248 : return;
249 0 : gen_libfunc (optable, opname, suffix, mode);
250 : }
251 :
252 : /* Like gen_libfunc, but verify that unsigned fixed-point operation is
253 : involved. */
254 :
255 : void
256 0 : gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
257 : machine_mode mode)
258 : {
259 0 : if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
260 : return;
261 0 : gen_libfunc (optable, opname, suffix, mode);
262 : }
263 :
264 : /* Like gen_libfunc, but verify that FP or INT operation is involved. */
265 :
266 : void
267 9986 : gen_int_fp_libfunc (optab optable, const char *name, char suffix,
268 : machine_mode mode)
269 : {
270 9986 : if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
271 27 : gen_fp_libfunc (optable, name, suffix, mode);
272 9986 : if (INTEGRAL_MODE_P (mode))
273 9943 : gen_int_libfunc (optable, name, suffix, mode);
274 9986 : }
275 :
276 : /* Like gen_libfunc, but verify that FP or INT operation is involved
277 : and add 'v' suffix for integer operation. */
278 :
279 : void
280 125 : gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
281 : machine_mode mode)
282 : {
283 125 : if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
284 0 : gen_fp_libfunc (optable, name, suffix, mode);
285 125 : if (GET_MODE_CLASS (mode) == MODE_INT)
286 : {
287 125 : int len = strlen (name);
288 125 : char *v_name = XALLOCAVEC (char, len + 2);
289 125 : strcpy (v_name, name);
290 125 : v_name[len] = 'v';
291 125 : v_name[len + 1] = 0;
292 125 : gen_int_libfunc (optable, v_name, suffix, mode);
293 : }
294 125 : }
295 :
296 : /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
297 : involved. */
298 :
299 : void
300 912698 : gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
301 : machine_mode mode)
302 : {
303 912698 : if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
304 1753 : gen_fp_libfunc (optable, name, suffix, mode);
305 912698 : if (INTEGRAL_MODE_P (mode))
306 909676 : gen_int_libfunc (optable, name, suffix, mode);
307 912698 : if (ALL_FIXED_POINT_MODE_P (mode))
308 0 : gen_fixed_libfunc (optable, name, suffix, mode);
309 912698 : }
310 :
311 : /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
312 : involved. */
313 :
314 : void
315 46526 : gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
316 : machine_mode mode)
317 : {
318 46526 : if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
319 357 : gen_fp_libfunc (optable, name, suffix, mode);
320 46526 : if (INTEGRAL_MODE_P (mode))
321 46153 : gen_int_libfunc (optable, name, suffix, mode);
322 46526 : if (SIGNED_FIXED_POINT_MODE_P (mode))
323 0 : gen_signed_fixed_libfunc (optable, name, suffix, mode);
324 46526 : }
325 :
326 : /* Like gen_libfunc, but verify that INT or FIXED operation is
327 : involved. */
328 :
329 : void
330 271220 : gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
331 : machine_mode mode)
332 : {
333 271220 : if (INTEGRAL_MODE_P (mode))
334 271220 : gen_int_libfunc (optable, name, suffix, mode);
335 271220 : if (ALL_FIXED_POINT_MODE_P (mode))
336 0 : gen_fixed_libfunc (optable, name, suffix, mode);
337 271220 : }
338 :
339 : /* Like gen_libfunc, but verify that INT or signed FIXED operation is
340 : involved. */
341 :
342 : void
343 480 : gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
344 : machine_mode mode)
345 : {
346 480 : if (INTEGRAL_MODE_P (mode))
347 256 : gen_int_libfunc (optable, name, suffix, mode);
348 480 : if (SIGNED_FIXED_POINT_MODE_P (mode))
349 0 : gen_signed_fixed_libfunc (optable, name, suffix, mode);
350 480 : }
351 :
352 : /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
353 : involved. */
354 :
355 : void
356 36984 : gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
357 : machine_mode mode)
358 : {
359 36984 : if (INTEGRAL_MODE_P (mode))
360 36942 : gen_int_libfunc (optable, name, suffix, mode);
361 36984 : if (UNSIGNED_FIXED_POINT_MODE_P (mode))
362 0 : gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
363 36984 : }
364 :
365 : /* Helper function for gen_interclass_conv_libfunc and gen_bitint_fp_libfunc.
366 : Return name for interclass conversion function. */
367 :
368 : static const char *
369 2214 : gen_interclass_conv_libfunc_name (const char *opname, bool decimal_p,
370 : const char *tname, const char *fname)
371 : {
372 2214 : size_t opname_len = strlen (opname);
373 2214 : size_t mname_len = 0;
374 :
375 2214 : const char *q;
376 2214 : int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
377 2214 : char *libfunc_name, *suffix;
378 2214 : char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
379 2214 : char *p;
380 :
381 : /* If this is a decimal conversion, add the current BID vs. DPD prefix that
382 : depends on which underlying decimal floating point format is used. */
383 2214 : const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
384 :
385 2214 : mname_len = strlen (tname) + strlen (fname);
386 :
387 2214 : nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
388 2214 : nondec_name[0] = '_';
389 2214 : nondec_name[1] = '_';
390 2214 : if (targetm.libfunc_gnu_prefix)
391 : {
392 0 : nondec_name[2] = 'g';
393 0 : nondec_name[3] = 'n';
394 0 : nondec_name[4] = 'u';
395 0 : nondec_name[5] = '_';
396 : }
397 :
398 2214 : memcpy (&nondec_name[prefix_len], opname, opname_len);
399 2214 : nondec_suffix = nondec_name + opname_len + prefix_len;
400 :
401 2214 : dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
402 2214 : dec_name[0] = '_';
403 2214 : dec_name[1] = '_';
404 2214 : memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
405 2214 : memcpy (&dec_name[2+dec_len], opname, opname_len);
406 2214 : dec_suffix = dec_name + dec_len + opname_len + 2;
407 :
408 2214 : if (decimal_p)
409 : {
410 : libfunc_name = dec_name;
411 : suffix = dec_suffix;
412 : }
413 : else
414 : {
415 1139 : libfunc_name = nondec_name;
416 1139 : suffix = nondec_suffix;
417 : }
418 :
419 2214 : p = suffix;
420 6818 : for (q = fname; *q; p++, q++)
421 4604 : *p = TOLOWER (*q);
422 6802 : for (q = tname; *q; p++, q++)
423 4588 : *p = TOLOWER (*q);
424 :
425 2214 : *p = '\0';
426 :
427 2214 : return ggc_alloc_string (libfunc_name, p - libfunc_name);
428 : }
429 :
430 : /* Initialize the libfunc fields of an entire group of entries of an
431 : inter-mode-class conversion optab. The string formation rules are
432 : similar to the ones for init_libfuncs, above, but instead of having
433 : a mode name and an operand count these functions have two mode names
434 : and no operand count. */
435 :
436 : void
437 2130 : gen_interclass_conv_libfunc (convert_optab tab,
438 : const char *opname,
439 : machine_mode tmode,
440 : machine_mode fmode)
441 : {
442 2130 : const char *name
443 2130 : = gen_interclass_conv_libfunc_name (opname,
444 2130 : DECIMAL_FLOAT_MODE_P (fmode)
445 1594 : || DECIMAL_FLOAT_MODE_P (tmode),
446 2130 : GET_MODE_NAME (tmode),
447 2130 : GET_MODE_NAME (fmode));
448 2130 : set_conv_libfunc (tab, tmode, fmode, name);
449 2130 : }
450 :
451 : /* Same as gen_interclass_conv_libfunc but verify that we are producing
452 : int->fp conversion. */
453 :
454 : void
455 757 : gen_int_to_fp_conv_libfunc (convert_optab tab,
456 : const char *opname,
457 : machine_mode tmode,
458 : machine_mode fmode)
459 : {
460 757 : if (GET_MODE_CLASS (fmode) != MODE_INT)
461 : return;
462 757 : if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
463 : return;
464 757 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
465 : }
466 :
467 : /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
468 : naming scheme. */
469 :
470 : void
471 277 : gen_ufloat_conv_libfunc (convert_optab tab,
472 : const char *opname ATTRIBUTE_UNUSED,
473 : machine_mode tmode,
474 : machine_mode fmode)
475 : {
476 277 : if (DECIMAL_FLOAT_MODE_P (tmode))
477 70 : gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
478 : else
479 207 : gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
480 277 : }
481 :
482 : /* Same as gen_interclass_conv_libfunc but verify that we are producing
483 : fp->int conversion. */
484 :
485 : void
486 0 : gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
487 : const char *opname,
488 : machine_mode tmode,
489 : machine_mode fmode)
490 : {
491 0 : if (GET_MODE_CLASS (fmode) != MODE_INT)
492 : return;
493 0 : if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
494 : return;
495 0 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
496 : }
497 :
498 : /* Same as gen_interclass_conv_libfunc but verify that we are producing
499 : fp->int conversion with no decimal floating point involved. */
500 :
501 : void
502 744 : gen_fp_to_int_conv_libfunc (convert_optab tab,
503 : const char *opname,
504 : machine_mode tmode,
505 : machine_mode fmode)
506 : {
507 744 : if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
508 : return;
509 744 : if (GET_MODE_CLASS (tmode) != MODE_INT)
510 : return;
511 744 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
512 : }
513 :
514 : /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
515 : The string formation rules are
516 : similar to the ones for init_libfunc, above. */
517 :
518 : void
519 1276 : gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
520 : machine_mode tmode, machine_mode fmode)
521 : {
522 1276 : size_t opname_len = strlen (opname);
523 1276 : size_t mname_len = 0;
524 :
525 1276 : const char *fname, *tname;
526 1276 : const char *q;
527 1276 : int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
528 1276 : char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
529 1276 : char *libfunc_name, *suffix;
530 1276 : char *p;
531 :
532 : /* If this is a decimal conversion, add the current BID vs. DPD prefix that
533 : depends on which underlying decimal floating point format is used. */
534 1276 : const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
535 :
536 1276 : mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
537 :
538 1276 : nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
539 1276 : nondec_name[0] = '_';
540 1276 : nondec_name[1] = '_';
541 1276 : if (targetm.libfunc_gnu_prefix)
542 : {
543 0 : nondec_name[2] = 'g';
544 0 : nondec_name[3] = 'n';
545 0 : nondec_name[4] = 'u';
546 0 : nondec_name[5] = '_';
547 : }
548 1276 : memcpy (&nondec_name[prefix_len], opname, opname_len);
549 1276 : nondec_suffix = nondec_name + opname_len + prefix_len;
550 :
551 1276 : dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
552 1276 : dec_name[0] = '_';
553 1276 : dec_name[1] = '_';
554 1276 : memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
555 1276 : memcpy (&dec_name[2 + dec_len], opname, opname_len);
556 1276 : dec_suffix = dec_name + dec_len + opname_len + 2;
557 :
558 1276 : fname = GET_MODE_NAME (fmode);
559 1276 : tname = GET_MODE_NAME (tmode);
560 :
561 1276 : if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
562 : {
563 : libfunc_name = dec_name;
564 : suffix = dec_suffix;
565 : }
566 : else
567 : {
568 1276 : libfunc_name = nondec_name;
569 1276 : suffix = nondec_suffix;
570 : }
571 :
572 1276 : p = suffix;
573 3828 : for (q = fname; *q; p++, q++)
574 2552 : *p = TOLOWER (*q);
575 3828 : for (q = tname; *q; p++, q++)
576 2552 : *p = TOLOWER (*q);
577 :
578 1276 : *p++ = '2';
579 1276 : *p = '\0';
580 :
581 1276 : set_conv_libfunc (tab, tmode, fmode,
582 1276 : ggc_alloc_string (libfunc_name, p - libfunc_name));
583 1276 : }
584 :
585 : /* Pick proper libcall for trunc_optab. We need to chose if we do
586 : truncation or extension and interclass or intraclass. */
587 :
588 : void
589 867 : gen_trunc_conv_libfunc (convert_optab tab,
590 : const char *opname,
591 : machine_mode tmode,
592 : machine_mode fmode)
593 : {
594 867 : scalar_float_mode float_tmode, float_fmode;
595 867 : if (!is_a <scalar_float_mode> (fmode, &float_fmode)
596 1734 : || !is_a <scalar_float_mode> (tmode, &float_tmode)
597 867 : || float_tmode == float_fmode)
598 : return;
599 :
600 867 : if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
601 329 : gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
602 :
603 867 : if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode)
604 87 : && (REAL_MODE_FORMAT (float_tmode) != &arm_bfloat_half_format
605 1 : || REAL_MODE_FORMAT (float_fmode) != &ieee_half_format)
606 953 : && (REAL_MODE_FORMAT (float_tmode) != &ieee_quad_format
607 0 : || REAL_MODE_FORMAT (float_fmode) != &ibm_extended_format))
608 : return;
609 :
610 781 : if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
611 538 : gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
612 : }
613 :
614 : /* Pick proper libcall for extend_optab. We need to chose if we do
615 : truncation or extension and interclass or intraclass. */
616 :
617 : void
618 1038 : gen_extend_conv_libfunc (convert_optab tab,
619 : const char *opname ATTRIBUTE_UNUSED,
620 : machine_mode tmode,
621 : machine_mode fmode)
622 : {
623 1038 : scalar_float_mode float_tmode, float_fmode;
624 1038 : if (!is_a <scalar_float_mode> (fmode, &float_fmode)
625 2076 : || !is_a <scalar_float_mode> (tmode, &float_tmode)
626 1038 : || float_tmode == float_fmode)
627 : return;
628 :
629 1038 : if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
630 300 : gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
631 :
632 1038 : if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
633 : return;
634 :
635 1038 : if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
636 738 : gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
637 : }
638 :
639 : /* Pick proper libcall for fract_optab. We need to chose if we do
640 : interclass or intraclass. */
641 :
642 : void
643 0 : gen_fract_conv_libfunc (convert_optab tab,
644 : const char *opname,
645 : machine_mode tmode,
646 : machine_mode fmode)
647 : {
648 0 : if (tmode == fmode)
649 : return;
650 0 : if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
651 : return;
652 :
653 0 : if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
654 0 : gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
655 : else
656 0 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
657 : }
658 :
659 : /* Pick proper libcall for fractuns_optab. */
660 :
661 : void
662 0 : gen_fractuns_conv_libfunc (convert_optab tab,
663 : const char *opname,
664 : machine_mode tmode,
665 : machine_mode fmode)
666 : {
667 0 : if (tmode == fmode)
668 : return;
669 : /* One mode must be a fixed-point mode, and the other must be an integer
670 : mode. */
671 0 : if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
672 0 : || (ALL_FIXED_POINT_MODE_P (fmode)
673 0 : && GET_MODE_CLASS (tmode) == MODE_INT)))
674 : return;
675 :
676 0 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
677 : }
678 :
679 : /* Pick proper libcall for satfract_optab. We need to chose if we do
680 : interclass or intraclass. */
681 :
682 : void
683 0 : gen_satfract_conv_libfunc (convert_optab tab,
684 : const char *opname,
685 : machine_mode tmode,
686 : machine_mode fmode)
687 : {
688 0 : if (tmode == fmode)
689 : return;
690 : /* TMODE must be a fixed-point mode. */
691 0 : if (!ALL_FIXED_POINT_MODE_P (tmode))
692 : return;
693 :
694 0 : if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
695 0 : gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
696 : else
697 0 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
698 : }
699 :
700 : /* Pick proper libcall for satfractuns_optab. */
701 :
702 : void
703 0 : gen_satfractuns_conv_libfunc (convert_optab tab,
704 : const char *opname,
705 : machine_mode tmode,
706 : machine_mode fmode)
707 : {
708 0 : if (tmode == fmode)
709 : return;
710 : /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
711 0 : if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
712 : return;
713 :
714 0 : gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
715 : }
716 :
717 : /* Pick proper libcall for bitinttofp_optab and bitintfromfp_optab. */
718 :
719 : void
720 84 : gen_bitint_fp_libfunc (optab optable, const char *opname, char suffix,
721 : machine_mode mode)
722 : {
723 84 : if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
724 : {
725 84 : const char *name;
726 84 : if (suffix == '0')
727 44 : name = gen_interclass_conv_libfunc_name (opname,
728 : DECIMAL_FLOAT_MODE_P (mode),
729 44 : GET_MODE_NAME (mode),
730 : "bitint");
731 : else
732 40 : name = gen_interclass_conv_libfunc_name (opname,
733 : DECIMAL_FLOAT_MODE_P (mode),
734 : "bitint",
735 40 : GET_MODE_NAME (mode));
736 84 : set_optab_libfunc (optable, mode, name);
737 : }
738 84 : }
739 :
740 : /* Hashtable callbacks for libfunc_decls. */
741 :
742 : struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
743 : {
744 : static hashval_t
745 4275737 : hash (tree entry)
746 : {
747 4275737 : return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
748 : }
749 :
750 : static bool
751 8599425 : equal (tree decl, tree name)
752 : {
753 8599425 : return DECL_NAME (decl) == name;
754 : }
755 : };
756 :
757 : /* A table of previously-created libfuncs, hashed by name. */
758 : static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
759 :
760 : /* Build a decl for a libfunc named NAME with visibility VIS. */
761 :
762 : tree
763 2312093 : build_libfunc_function_visibility (const char *name, symbol_visibility vis)
764 : {
765 : /* ??? We don't have any type information; pretend this is "int foo ()". */
766 2312093 : tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
767 : get_identifier (name),
768 : build_function_type (integer_type_node, NULL_TREE));
769 2312093 : DECL_EXTERNAL (decl) = 1;
770 2312093 : TREE_PUBLIC (decl) = 1;
771 2312093 : DECL_ARTIFICIAL (decl) = 1;
772 2312093 : DECL_VISIBILITY (decl) = vis;
773 2312093 : DECL_VISIBILITY_SPECIFIED (decl) = 1;
774 2312093 : gcc_assert (DECL_ASSEMBLER_NAME (decl));
775 :
776 2312093 : return decl;
777 : }
778 :
779 : /* Build a decl for a libfunc named NAME. */
780 :
781 : tree
782 0 : build_libfunc_function (const char *name)
783 : {
784 0 : return build_libfunc_function_visibility (name, VISIBILITY_DEFAULT);
785 : }
786 :
787 : /* Return a libfunc for NAME, creating one if we don't already have one.
788 : The decl is given visibility VIS. The returned rtx is a SYMBOL_REF. */
789 :
790 : rtx
791 6336886 : init_one_libfunc_visibility (const char *name, symbol_visibility vis)
792 : {
793 6336886 : tree id, decl;
794 6336886 : hashval_t hash;
795 :
796 6336886 : if (libfunc_decls == NULL)
797 286955 : libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
798 :
799 : /* See if we have already created a libfunc decl for this function. */
800 6336886 : id = get_identifier (name);
801 6336886 : hash = IDENTIFIER_HASH_VALUE (id);
802 6336886 : tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
803 6336886 : decl = *slot;
804 6336886 : if (decl == NULL)
805 : {
806 : /* Create a new decl, so that it can be passed to
807 : targetm.encode_section_info. */
808 2312093 : decl = build_libfunc_function_visibility (name, vis);
809 2312093 : *slot = decl;
810 : }
811 6336886 : return XEXP (DECL_RTL (decl), 0);
812 : }
813 :
814 : rtx
815 6336886 : init_one_libfunc (const char *name)
816 : {
817 6336886 : return init_one_libfunc_visibility (name, VISIBILITY_DEFAULT);
818 : }
819 :
820 : /* Adjust the assembler name of libfunc NAME to ASMSPEC. */
821 :
822 : rtx
823 1 : set_user_assembler_libfunc (const char *name, const char *asmspec)
824 : {
825 1 : tree id, decl;
826 1 : hashval_t hash;
827 :
828 1 : id = get_identifier (name);
829 1 : hash = IDENTIFIER_HASH_VALUE (id);
830 1 : tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
831 1 : gcc_assert (slot);
832 1 : decl = (tree) *slot;
833 1 : set_user_assembler_name (decl, asmspec);
834 1 : return XEXP (DECL_RTL (decl), 0);
835 : }
836 :
837 : /* Call this to reset the function entry for one optab (OPTABLE) in mode
838 : MODE to NAME, which should be either 0 or a string constant. */
839 :
840 : void
841 4747717 : set_optab_libfunc (optab op, machine_mode mode, const char *name)
842 : {
843 4747717 : rtx val;
844 4747717 : struct libfunc_entry e;
845 4747717 : struct libfunc_entry **slot;
846 :
847 4747717 : e.op = op;
848 4747717 : e.mode1 = mode;
849 4747717 : e.mode2 = VOIDmode;
850 :
851 4747717 : if (name)
852 4747717 : val = init_one_libfunc (name);
853 : else
854 : val = 0;
855 4747717 : slot = libfunc_hash->find_slot (&e, INSERT);
856 4747717 : if (*slot == NULL)
857 4747716 : *slot = ggc_alloc<libfunc_entry> ();
858 4747717 : (*slot)->op = op;
859 4747717 : (*slot)->mode1 = mode;
860 4747717 : (*slot)->mode2 = VOIDmode;
861 4747717 : (*slot)->libfunc = val;
862 4747717 : }
863 :
864 : /* Call this to reset the function entry for one conversion optab
865 : (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
866 : either 0 or a string constant. */
867 :
868 : void
869 3406 : set_conv_libfunc (convert_optab optab, machine_mode tmode,
870 : machine_mode fmode, const char *name)
871 : {
872 3406 : rtx val;
873 3406 : struct libfunc_entry e;
874 3406 : struct libfunc_entry **slot;
875 :
876 3406 : e.op = optab;
877 3406 : e.mode1 = tmode;
878 3406 : e.mode2 = fmode;
879 :
880 3406 : if (name)
881 3406 : val = init_one_libfunc (name);
882 : else
883 : val = 0;
884 3406 : slot = libfunc_hash->find_slot (&e, INSERT);
885 3406 : if (*slot == NULL)
886 3406 : *slot = ggc_alloc<libfunc_entry> ();
887 3406 : (*slot)->op = optab;
888 3406 : (*slot)->mode1 = tmode;
889 3406 : (*slot)->mode2 = fmode;
890 3406 : (*slot)->libfunc = val;
891 3406 : }
892 :
893 : /* Call this to initialize the contents of the optabs
894 : appropriately for the current target machine. */
895 :
896 : void
897 790793 : init_optabs (void)
898 : {
899 790793 : if (libfunc_hash)
900 0 : libfunc_hash->empty ();
901 : else
902 790793 : libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
903 :
904 : /* Fill in the optabs with the insns we support. */
905 790793 : init_all_optabs (this_fn_optabs);
906 :
907 : /* The ffs function operates on `int'. Fall back on it if we do not
908 : have a libgcc2 function for that width. */
909 790793 : if (INT_TYPE_SIZE < BITS_PER_WORD)
910 : {
911 775751 : scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
912 775751 : set_optab_libfunc (ffs_optab, mode, "ffs");
913 : }
914 :
915 : /* Explicitly initialize the bswap libfuncs since we need them to be
916 : valid for things other than word_mode. */
917 790793 : if (targetm.libfunc_gnu_prefix)
918 : {
919 0 : set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
920 0 : set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
921 : }
922 : else
923 : {
924 790793 : set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
925 790793 : set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
926 : }
927 :
928 : /* Use cabs for double complex abs, since systems generally have cabs.
929 : Don't define any libcall for float complex, so that cabs will be used. */
930 790793 : if (complex_double_type_node)
931 790793 : set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
932 : "cabs");
933 :
934 790793 : unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
935 790793 : unwind_sjlj_unregister_libfunc
936 790793 : = init_one_libfunc ("_Unwind_SjLj_Unregister");
937 :
938 : /* Allow the target to add more libcalls or rename some, etc. */
939 790793 : targetm.init_libfuncs ();
940 790793 : }
941 :
942 : /* A helper function for init_sync_libfuncs. Using the basename BASE,
943 : install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */
944 :
945 : static void
946 0 : init_sync_libfuncs_1 (optab tab, const char *base, int max)
947 : {
948 0 : machine_mode mode;
949 0 : char buf[64];
950 0 : size_t len = strlen (base);
951 0 : int i;
952 :
953 0 : gcc_assert (max <= 8);
954 0 : gcc_assert (len + 3 < sizeof (buf));
955 :
956 0 : memcpy (buf, base, len);
957 0 : buf[len] = '_';
958 0 : buf[len + 1] = '0';
959 0 : buf[len + 2] = '\0';
960 :
961 0 : mode = QImode;
962 0 : for (i = 1; i <= max; i *= 2)
963 : {
964 0 : if (i > 1)
965 0 : mode = GET_MODE_2XWIDER_MODE (mode).require ();
966 0 : buf[len + 1] = '0' + i;
967 0 : set_optab_libfunc (tab, mode, buf);
968 : }
969 0 : }
970 :
971 : void
972 0 : init_sync_libfuncs (int max)
973 : {
974 0 : if (!flag_sync_libcalls)
975 : return;
976 :
977 0 : init_sync_libfuncs_1 (sync_compare_and_swap_optab,
978 : "__sync_val_compare_and_swap", max);
979 0 : init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
980 : "__sync_lock_test_and_set", max);
981 :
982 0 : init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
983 0 : init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
984 0 : init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
985 0 : init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
986 0 : init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
987 0 : init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
988 :
989 0 : init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
990 0 : init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
991 0 : init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
992 0 : init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
993 0 : init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
994 0 : init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
995 : }
996 :
997 : #include "gt-optabs-libfuncs.h"
|