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