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