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