LCOV - code coverage report
Current view: top level - gcc - optabs-libfuncs.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 78.5 % 433 340
Test Date: 2026-10-17 16:30:31 Functions: 74.4 % 43 32
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.