Home | History | Annotate | Line # | Download | only in d
intrinsics.cc revision 1.1.1.2
      1 /* intrinsics.cc -- D language compiler intrinsics.
      2    Copyright (C) 2006-2020 Free Software Foundation, Inc.
      3 
      4 GCC is free software; you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation; either version 3, or (at your option)
      7 any later version.
      8 
      9 GCC is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with GCC; see the file COPYING3.  If not see
     16 <http://www.gnu.org/licenses/>.  */
     17 
     18 #include "config.h"
     19 #include "system.h"
     20 #include "coretypes.h"
     21 
     22 #include "dmd/declaration.h"
     23 #include "dmd/identifier.h"
     24 #include "dmd/mangle.h"
     25 #include "dmd/mangle.h"
     26 #include "dmd/module.h"
     27 #include "dmd/template.h"
     28 
     29 #include "tm.h"
     30 #include "function.h"
     31 #include "tree.h"
     32 #include "fold-const.h"
     33 #include "stringpool.h"
     34 #include "builtins.h"
     35 
     36 #include "d-tree.h"
     37 
     38 
     39 /* An internal struct used to hold information on D intrinsics.  */
     40 
     41 struct intrinsic_decl
     42 {
     43   /* The DECL_FUNCTION_CODE of this decl.  */
     44   intrinsic_code code;
     45 
     46   /* The name of the intrinsic.  */
     47   const char *name;
     48 
     49   /* The module where the intrinsic is located.  */
     50   const char *module;
     51 
     52   /* The mangled signature decoration of the intrinsic.  */
     53   const char *deco;
     54 
     55   /* True if the intrinsic is only handled in CTFE.  */
     56   bool ctfeonly;
     57 };
     58 
     59 static const intrinsic_decl intrinsic_decls[] =
     60 {
     61 #define DEF_D_INTRINSIC(CODE, ALIAS, NAME, MODULE, DECO, CTFE) \
     62     { INTRINSIC_ ## ALIAS, NAME, MODULE, DECO, CTFE },
     63 
     64 #include "intrinsics.def"
     65 
     66 #undef DEF_D_INTRINSIC
     67 };
     68 
     69 /* Checks if DECL is an intrinsic or run time library function that requires
     70    special processing.  Sets DECL_INTRINSIC_CODE so it can be identified
     71    later in maybe_expand_intrinsic.  */
     72 
     73 void
     74 maybe_set_intrinsic (FuncDeclaration *decl)
     75 {
     76   if (!decl->ident || decl->builtin != BUILTINunknown)
     77     return;
     78 
     79   /* The builtin flag is updated only if we can evaluate the intrinsic
     80      at compile-time.  Such as the math or bitop intrinsics.  */
     81   decl->builtin = BUILTINno;
     82 
     83   /* Check if it's a compiler intrinsic.  We only require that any
     84      internally recognised intrinsics are declared in a module with
     85      an explicit module declaration.  */
     86   Module *m = decl->getModule ();
     87 
     88   if (!m || !m->md)
     89     return;
     90 
     91   TemplateInstance *ti = decl->isInstantiated ();
     92   TemplateDeclaration *td = ti ? ti->tempdecl->isTemplateDeclaration () : NULL;
     93 
     94   const char *tname = decl->ident->toChars ();
     95   const char *tmodule = m->md->toChars ();
     96   const char *tdeco = (td == NULL) ? decl->type->deco : NULL;
     97 
     98   /* Look through all D intrinsics.  */
     99   for (size_t i = 0; i < (int) INTRINSIC_LAST; i++)
    100     {
    101       if (!intrinsic_decls[i].name)
    102 	continue;
    103 
    104       if (strcmp (intrinsic_decls[i].name, tname) != 0
    105 	  || strcmp (intrinsic_decls[i].module, tmodule) != 0)
    106 	continue;
    107 
    108       /* Instantiated functions would have the wrong type deco, get it from the
    109 	 template member instead.  */
    110       if (tdeco == NULL)
    111 	{
    112 	  if (!td || !td->onemember)
    113 	    return;
    114 
    115 	  FuncDeclaration *fd = td->onemember->isFuncDeclaration ();
    116 	  if (fd == NULL)
    117 	    return;
    118 
    119 	  OutBuffer buf;
    120 	  mangleToBuffer (fd->type, &buf);
    121 	  tdeco = buf.extractString ();
    122 	}
    123 
    124       /* Matching the type deco may be a bit too strict, as it means that all
    125 	 function attributes that end up in the signature must be kept aligned
    126 	 between the compiler and library declaration.  */
    127       if (strcmp (intrinsic_decls[i].deco, tdeco) == 0)
    128 	{
    129 	  intrinsic_code code = intrinsic_decls[i].code;
    130 
    131 	  if (decl->csym == NULL)
    132 	    get_symbol_decl (decl);
    133 
    134 	  /* If there is no function body, then the implementation is always
    135 	     provided by the compiler.  */
    136 	  if (!decl->fbody)
    137 	    set_decl_built_in_function (decl->csym, BUILT_IN_FRONTEND, code);
    138 
    139 	  /* Infer whether the intrinsic can be used for CTFE, let the
    140 	     front-end know that it can be evaluated at compile-time.  */
    141 	  switch (code)
    142 	    {
    143 	    case INTRINSIC_VA_ARG:
    144 	    case INTRINSIC_C_VA_ARG:
    145 	    case INTRINSIC_VASTART:
    146 	    case INTRINSIC_ADDS:
    147 	    case INTRINSIC_SUBS:
    148 	    case INTRINSIC_MULS:
    149 	    case INTRINSIC_NEGS:
    150 	    case INTRINSIC_VLOAD:
    151 	    case INTRINSIC_VSTORE:
    152 	      break;
    153 
    154 	    case INTRINSIC_POW:
    155 	    {
    156 	      /* Check that this overload of pow() is has an equivalent
    157 		 built-in function.  It could be `int pow(int, int)'.  */
    158 	      tree rettype = TREE_TYPE (TREE_TYPE (decl->csym));
    159 	      if (mathfn_built_in (rettype, BUILT_IN_POW) != NULL_TREE)
    160 		decl->builtin = BUILTINyes;
    161 	      break;
    162 	    }
    163 
    164 	    default:
    165 	      decl->builtin = BUILTINyes;
    166 	      break;
    167 	    }
    168 
    169 	  /* The intrinsic was marked as CTFE-only.  */
    170 	  if (intrinsic_decls[i].ctfeonly)
    171 	    DECL_BUILT_IN_CTFE (decl->csym) = 1;
    172 
    173 	  DECL_INTRINSIC_CODE (decl->csym) = code;
    174 	  break;
    175 	}
    176     }
    177 }
    178 
    179 /* Construct a function call to the built-in function CODE, N is the number of
    180    arguments, and the `...' parameters are the argument expressions.
    181    The original call expression is held in CALLEXP.  */
    182 
    183 static tree
    184 call_builtin_fn (tree callexp, built_in_function code, int n, ...)
    185 {
    186   tree *argarray = XALLOCAVEC (tree, n);
    187   va_list ap;
    188 
    189   va_start (ap, n);
    190   for (int i = 0; i < n; i++)
    191     argarray[i] = va_arg (ap, tree);
    192   va_end (ap);
    193 
    194   tree exp = build_call_expr_loc_array (EXPR_LOCATION (callexp),
    195 					builtin_decl_explicit (code),
    196 					n, argarray);
    197   return convert (TREE_TYPE (callexp), fold (exp));
    198 }
    199 
    200 /* Expand a front-end instrinsic call to bsf().  This takes one argument,
    201    the signature to which can be either:
    202 
    203 	int bsf (uint arg);
    204 	int bsf (ulong arg);
    205 
    206    This scans all bits in the given argument starting with the first,
    207    returning the bit number of the first bit set.  The original call
    208    expression is held in CALLEXP.  */
    209 
    210 static tree
    211 expand_intrinsic_bsf (tree callexp)
    212 {
    213   /* The bsr() intrinsic gets turned into __builtin_ctz(arg).
    214      The return value is supposed to be undefined if arg is zero.  */
    215   tree arg = CALL_EXPR_ARG (callexp, 0);
    216   int argsize = TYPE_PRECISION (TREE_TYPE (arg));
    217 
    218   /* Which variant of __builtin_ctz* should we call?  */
    219   built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CTZ
    220     : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CTZL
    221     : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CTZLL
    222     : END_BUILTINS;
    223 
    224   gcc_assert (code != END_BUILTINS);
    225 
    226   return call_builtin_fn (callexp, code, 1, arg);
    227 }
    228 
    229 /* Expand a front-end instrinsic call to bsr().  This takes one argument,
    230    the signature to which can be either:
    231 
    232 	int bsr (uint arg);
    233 	int bsr (ulong arg);
    234 
    235    This scans all bits in the given argument from the most significant bit
    236    to the least significant, returning the bit number of the first bit set.
    237    The original call expression is held in CALLEXP.  */
    238 
    239 static tree
    240 expand_intrinsic_bsr (tree callexp)
    241 {
    242   /* The bsr() intrinsic gets turned into (size - 1) - __builtin_clz(arg).
    243      The return value is supposed to be undefined if arg is zero.  */
    244   tree arg = CALL_EXPR_ARG (callexp, 0);
    245   tree type = TREE_TYPE (arg);
    246   int argsize = TYPE_PRECISION (type);
    247 
    248   /* Which variant of __builtin_clz* should we call?  */
    249   built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CLZ
    250     : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CLZL
    251     : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CLZLL
    252     : END_BUILTINS;
    253 
    254   gcc_assert (code != END_BUILTINS);
    255 
    256   tree result = call_builtin_fn (callexp, code, 1, arg);
    257 
    258   /* Handle int -> long conversions.  */
    259   if (TREE_TYPE (result) != type)
    260     result = fold_convert (type, result);
    261 
    262   result = fold_build2 (MINUS_EXPR, type,
    263 			build_integer_cst (argsize - 1, type), result);
    264   return fold_convert (TREE_TYPE (callexp), result);
    265 }
    266 
    267 /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to
    268    bt(), btc(), btr(), or bts().  These intrinsics expect to take two arguments,
    269    the signature to which is:
    270 
    271 	int bt (size_t* ptr, size_t bitnum);
    272 
    273    All intrinsics test if a bit is set and return the result of that condition.
    274    Variants of `bt' will then update that bit. `btc' compliments the bit, `bts'
    275    sets the bit, and `btr' resets the bit.  The original call expression is
    276    held in CALLEXP.  */
    277 
    278 static tree
    279 expand_intrinsic_bt (intrinsic_code intrinsic, tree callexp)
    280 {
    281   tree ptr = CALL_EXPR_ARG (callexp, 0);
    282   tree bitnum = CALL_EXPR_ARG (callexp, 1);
    283   tree type = TREE_TYPE (TREE_TYPE (ptr));
    284 
    285   /* size_t bitsize = sizeof(*ptr) * BITS_PER_UNIT;  */
    286   tree bitsize = fold_convert (type, TYPE_SIZE (type));
    287 
    288   /* ptr[bitnum / bitsize]  */
    289   ptr = build_array_index (ptr, fold_build2 (TRUNC_DIV_EXPR, type,
    290 					     bitnum, bitsize));
    291   ptr = indirect_ref (type, ptr);
    292 
    293   /* mask = 1 << (bitnum % bitsize);  */
    294   bitnum = fold_build2 (TRUNC_MOD_EXPR, type, bitnum, bitsize);
    295   bitnum = fold_build2 (LSHIFT_EXPR, type, size_one_node, bitnum);
    296 
    297   /* cond = ptr[bitnum / size] & mask;  */
    298   tree cond = fold_build2 (BIT_AND_EXPR, type, ptr, bitnum);
    299 
    300   /* cond ? -1 : 0;  */
    301   cond = build_condition (TREE_TYPE (callexp), d_truthvalue_conversion (cond),
    302 			 integer_minus_one_node, integer_zero_node);
    303 
    304   /* Update the bit as needed, only testing the bit for bt().  */
    305   if (intrinsic == INTRINSIC_BT)
    306     return cond;
    307 
    308   tree_code code = (intrinsic == INTRINSIC_BTC) ? BIT_XOR_EXPR
    309     : (intrinsic == INTRINSIC_BTR) ? BIT_AND_EXPR
    310     : (intrinsic == INTRINSIC_BTS) ? BIT_IOR_EXPR
    311     : ERROR_MARK;
    312   gcc_assert (code != ERROR_MARK);
    313 
    314   /* ptr[bitnum / size] op= mask;  */
    315   if (intrinsic == INTRINSIC_BTR)
    316     bitnum = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (bitnum), bitnum);
    317 
    318   ptr = modify_expr (ptr, fold_build2 (code, TREE_TYPE (ptr), ptr, bitnum));
    319 
    320   /* Store the condition result in a temporary, and return expressions in
    321      correct order of evaluation.  */
    322   tree tmp = build_local_temp (TREE_TYPE (callexp));
    323   cond = modify_expr (tmp, cond);
    324 
    325   return compound_expr (cond, compound_expr (ptr, tmp));
    326 }
    327 
    328 /* Expand a front-end intrinsic call to bswap().  This takes one argument, the
    329    signature to which can be either:
    330 
    331 	int bswap (uint arg);
    332 	int bswap (ulong arg);
    333 
    334    This swaps all bytes in an N byte type end-to-end.  The original call
    335    expression is held in CALLEXP.  */
    336 
    337 static tree
    338 expand_intrinsic_bswap (tree callexp)
    339 {
    340   tree arg = CALL_EXPR_ARG (callexp, 0);
    341   int argsize = TYPE_PRECISION (TREE_TYPE (arg));
    342 
    343   /* Which variant of __builtin_bswap* should we call?  */
    344   built_in_function code = (argsize == 32) ? BUILT_IN_BSWAP32
    345     : (argsize == 64) ? BUILT_IN_BSWAP64
    346     : END_BUILTINS;
    347 
    348   gcc_assert (code != END_BUILTINS);
    349 
    350   return call_builtin_fn (callexp, code, 1, arg);
    351 }
    352 
    353 /* Expand a front-end intrinsic call to popcnt().  This takes one argument, the
    354    signature to which can be either:
    355 
    356 	int popcnt (uint arg);
    357 	int popcnt (ulong arg);
    358 
    359    Calculates the number of set bits in an integer.  The original call
    360    expression is held in CALLEXP.  */
    361 
    362 static tree
    363 expand_intrinsic_popcnt (tree callexp)
    364 {
    365   tree arg = CALL_EXPR_ARG (callexp, 0);
    366   int argsize = TYPE_PRECISION (TREE_TYPE (arg));
    367 
    368   /* Which variant of __builtin_popcount* should we call?  */
    369   built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_POPCOUNT
    370     : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTL
    371     : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTLL
    372     : END_BUILTINS;
    373 
    374   gcc_assert (code != END_BUILTINS);
    375 
    376   return call_builtin_fn (callexp, code, 1, arg);
    377 }
    378 
    379 /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to
    380    sqrt(), sqrtf(), sqrtl().  These intrinsics expect to take one argument,
    381    the signature to which can be either:
    382 
    383 	float sqrt (float arg);
    384 	double sqrt (double arg);
    385 	real sqrt (real arg);
    386 
    387    This computes the square root of the given argument.  The original call
    388    expression is held in CALLEXP.  */
    389 
    390 static tree
    391 expand_intrinsic_sqrt (intrinsic_code intrinsic, tree callexp)
    392 {
    393   tree arg = CALL_EXPR_ARG (callexp, 0);
    394 
    395   /* Which variant of __builtin_sqrt* should we call?  */
    396   built_in_function code = (intrinsic == INTRINSIC_SQRT) ? BUILT_IN_SQRT
    397     : (intrinsic == INTRINSIC_SQRTF) ? BUILT_IN_SQRTF
    398     : (intrinsic == INTRINSIC_SQRTL) ? BUILT_IN_SQRTL
    399     : END_BUILTINS;
    400 
    401   gcc_assert (code != END_BUILTINS);
    402   return call_builtin_fn (callexp, code, 1, arg);
    403 }
    404 
    405 /* Expand a front-end intrinsic call to copysign().  This takes two arguments,
    406    the signature to which can be either:
    407 
    408 	float copysign (T to, float from);
    409 	double copysign (T to, double from);
    410 	real copysign (T to, real from);
    411 
    412    This computes a value composed of TO with the sign bit of FROM.  The original
    413    call expression is held in CALLEXP.  */
    414 
    415 static tree
    416 expand_intrinsic_copysign (tree callexp)
    417 {
    418   tree to = CALL_EXPR_ARG (callexp, 0);
    419   tree from = CALL_EXPR_ARG (callexp, 1);
    420   tree type = TREE_TYPE (to);
    421 
    422   /* Convert parameters to the same type.  Prefer the first parameter unless it
    423      is an integral type.  */
    424   if (INTEGRAL_TYPE_P (type))
    425     {
    426       to = fold_convert (TREE_TYPE (from), to);
    427       type = TREE_TYPE (to);
    428     }
    429   else
    430     from = fold_convert (type, from);
    431 
    432   /* Which variant of __builtin_copysign* should we call?  */
    433   built_in_function code = (type == float_type_node) ? BUILT_IN_COPYSIGNF
    434     : (type == double_type_node) ? BUILT_IN_COPYSIGN
    435     : (type == long_double_type_node) ? BUILT_IN_COPYSIGNL
    436     : END_BUILTINS;
    437 
    438   gcc_assert (code != END_BUILTINS);
    439 
    440   return call_builtin_fn (callexp, code, 2, to, from);
    441 }
    442 
    443 /* Expand a front-end intrinsic call to pow().  This takes two arguments, the
    444    signature to which can be either:
    445 
    446 	float pow (float base, T exponent);
    447 	double pow (double base, T exponent);
    448 	real pow (real base, T exponent);
    449 
    450    This computes the value of BASE raised to the power of EXPONENT.
    451    The original call expression is held in CALLEXP.  */
    452 
    453 static tree
    454 expand_intrinsic_pow (tree callexp)
    455 {
    456   tree base = CALL_EXPR_ARG (callexp, 0);
    457   tree exponent = CALL_EXPR_ARG (callexp, 1);
    458   tree exptype = TREE_TYPE (exponent);
    459 
    460   /* Which variant of __builtin_pow* should we call?  */
    461   built_in_function code = SCALAR_FLOAT_TYPE_P (exptype) ? BUILT_IN_POW
    462     : INTEGRAL_TYPE_P (exptype) ? BUILT_IN_POWI
    463     : END_BUILTINS;
    464   gcc_assert (code != END_BUILTINS);
    465 
    466   tree builtin = mathfn_built_in (TREE_TYPE (base), code);
    467   gcc_assert (builtin != NULL_TREE);
    468 
    469   return call_builtin_fn (callexp, DECL_FUNCTION_CODE (builtin), 2,
    470 			  base, exponent);
    471 }
    472 
    473 /* Expand a front-end intrinsic call to toPrec().  This takes one argument, the
    474    signature to which can be either:
    475 
    476 	T toPrec(T)(float f);
    477 	T toPrec(T)(double f);
    478 	T toPrec(T)(real f);
    479 
    480     This rounds the argument F to the precision of the specified floating
    481     point type T.  The original call expression is held in CALLEXP.  */
    482 
    483 static tree
    484 expand_intrinsic_toprec (tree callexp)
    485 {
    486   tree f = CALL_EXPR_ARG (callexp, 0);
    487   tree type = TREE_TYPE (callexp);
    488 
    489   return convert (type, f);
    490 }
    491 
    492 /* Expand a front-end intrinsic call to va_arg().  This takes either one or two
    493    arguments, the signature to which can be either:
    494 
    495 	T va_arg(T) (ref va_list ap);
    496 	void va_arg(T) (va_list ap, ref T parmn);
    497 
    498    This retrieves the next variadic parameter that is type T from the given
    499    va_list.  If also given, store the value into parmn, otherwise return it.
    500    The original call expression is held in CALLEXP.  */
    501 
    502 static tree
    503 expand_intrinsic_vaarg (tree callexp)
    504 {
    505   tree ap = CALL_EXPR_ARG (callexp, 0);
    506   tree parmn = NULL_TREE;
    507   tree type;
    508 
    509   STRIP_NOPS (ap);
    510 
    511   if (call_expr_nargs (callexp) == 1)
    512     type = TREE_TYPE (callexp);
    513   else
    514     {
    515       parmn = CALL_EXPR_ARG (callexp, 1);
    516       STRIP_NOPS (parmn);
    517 
    518       /* The `ref' argument to va_arg is either an address or reference,
    519 	 get the value of it.  */
    520       if (TREE_CODE (parmn) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (parmn)))
    521 	parmn = build_deref (parmn);
    522       else
    523 	{
    524 	  gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
    525 	  parmn = TREE_OPERAND (parmn, 0);
    526 	}
    527 
    528       type = TREE_TYPE (parmn);
    529     }
    530 
    531   /* (T) VA_ARG_EXP<ap>;  */
    532   tree exp = build1 (VA_ARG_EXPR, type, ap);
    533 
    534   /* parmn = (T) VA_ARG_EXP<ap>;  */
    535   if (parmn != NULL_TREE)
    536     exp = modify_expr (parmn, exp);
    537 
    538   return exp;
    539 }
    540 
    541 /* Expand a front-end intrinsic call to va_start(), which takes two arguments,
    542    the signature to which is:
    543 
    544 	void va_start(T) (out va_list ap, ref T parmn);
    545 
    546    This initializes the va_list type, where parmn should be the last named
    547    parameter.  The original call expression is held in CALLEXP.  */
    548 
    549 static tree
    550 expand_intrinsic_vastart (tree callexp)
    551 {
    552   tree ap = CALL_EXPR_ARG (callexp, 0);
    553   tree parmn = CALL_EXPR_ARG (callexp, 1);
    554 
    555   STRIP_NOPS (ap);
    556   STRIP_NOPS (parmn);
    557 
    558   /* The va_list argument should already have its address taken.  The second
    559      argument, however, is inout and that needs to be fixed to prevent a
    560      warning.  Could be casting, so need to check type too?  */
    561   gcc_assert (TREE_CODE (ap) == ADDR_EXPR
    562 	      || (TREE_CODE (ap) == PARM_DECL
    563 		  && POINTER_TYPE_P (TREE_TYPE (ap))));
    564 
    565   /* Assuming nobody tries to change the return type.  */
    566   if (TREE_CODE (parmn) != PARM_DECL)
    567     {
    568       gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
    569       parmn = TREE_OPERAND (parmn, 0);
    570     }
    571 
    572   return call_builtin_fn (callexp, BUILT_IN_VA_START, 2, ap, parmn);
    573 }
    574 
    575 /* Expand a front-end instrinsic call to INTRINSIC, which is either a call to
    576    adds(), addu(), subs(), subu(), negs(), muls(), or mulu().  These intrinsics
    577    expect to take two or three arguments, the signature to which can be either:
    578 
    579 	int adds (int x, int y, ref bool overflow);
    580 	long adds (long x, long y, ref bool overflow);
    581 	int negs (int x, ref bool overflow);
    582 	long negs (long x, ref bool overflow);
    583 
    584    This performs an operation on two signed or unsigned integers, checking for
    585    overflow.  The overflow is sticky, meaning that a sequence of operations
    586    can be done and overflow need only be checked at the end.  The original call
    587    expression is held in CALLEXP.  */
    588 
    589 static tree
    590 expand_intrinsic_checkedint (intrinsic_code intrinsic, tree callexp)
    591 {
    592   tree type = TREE_TYPE (callexp);
    593   tree x;
    594   tree y;
    595   tree overflow;
    596 
    597   /* The negs() intrinsic gets turned into SUB_OVERFLOW (0, y).  */
    598   if (intrinsic == INTRINSIC_NEGS)
    599     {
    600       x = fold_convert (type, integer_zero_node);
    601       y = CALL_EXPR_ARG (callexp, 0);
    602       overflow = CALL_EXPR_ARG (callexp, 1);
    603     }
    604   else
    605     {
    606       x = CALL_EXPR_ARG (callexp, 0);
    607       y = CALL_EXPR_ARG (callexp, 1);
    608       overflow = CALL_EXPR_ARG (callexp, 2);
    609     }
    610 
    611   /* Which variant of *_OVERFLOW should we generate?  */
    612   internal_fn icode = (intrinsic == INTRINSIC_ADDS) ? IFN_ADD_OVERFLOW
    613     : (intrinsic == INTRINSIC_SUBS) ? IFN_SUB_OVERFLOW
    614     : (intrinsic == INTRINSIC_MULS) ? IFN_MUL_OVERFLOW
    615     : (intrinsic == INTRINSIC_NEGS) ? IFN_SUB_OVERFLOW
    616     : IFN_LAST;
    617   gcc_assert (icode != IFN_LAST);
    618 
    619   tree result
    620     = build_call_expr_internal_loc (EXPR_LOCATION (callexp), icode,
    621 				    build_complex_type (type), 2, x, y);
    622 
    623   STRIP_NOPS (overflow);
    624   overflow = build_deref (overflow);
    625 
    626   /* Assign returned result to overflow parameter, however if overflow is
    627      already true, maintain its value.  */
    628   type = TREE_TYPE (overflow);
    629   result = save_expr (result);
    630 
    631   tree exp = fold_build2 (BIT_IOR_EXPR, type, overflow,
    632 			  fold_convert (type, imaginary_part (result)));
    633   exp = modify_expr (overflow, exp);
    634 
    635   /* Return the value of result.  */
    636   return compound_expr (exp, real_part (result));
    637 }
    638 
    639 /* Expand a front-end instrinsic call to volatileLoad().  This takes one
    640    argument, the signature to which can be either:
    641 
    642 	ubyte volatileLoad (ubyte* ptr);
    643 	ushort volatileLoad (ushort* ptr);
    644 	uint volatileLoad (uint* ptr);
    645 	ulong volatileLoad (ulong* ptr);
    646 
    647    This reads a value from the memory location indicated by ptr.  Calls to
    648    them are be guaranteed to not be removed (such as during DCE) or reordered
    649    in the same thread.  The original call expression is held in CALLEXP.  */
    650 
    651 static tree
    652 expand_volatile_load (tree callexp)
    653 {
    654   tree ptr = CALL_EXPR_ARG (callexp, 0);
    655   tree ptrtype = TREE_TYPE (ptr);
    656   gcc_assert (POINTER_TYPE_P (ptrtype));
    657 
    658   /* (T) *(volatile T *) ptr;  */
    659   tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE);
    660   tree result = indirect_ref (type, ptr);
    661   TREE_THIS_VOLATILE (result) = 1;
    662 
    663   return result;
    664 }
    665 
    666 /* Expand a front-end instrinsic call to volatileStore().  This takes two
    667    arguments, the signature to which can be either:
    668 
    669 	void volatileStore (ubyte* ptr, ubyte value);
    670 	void volatileStore (ushort* ptr, ushort value);
    671 	void volatileStore (uint* ptr, uint value);
    672 	void volatileStore (ulong* ptr, ulong value);
    673 
    674    This writes a value to the memory location indicated by ptr.  Calls to
    675    them are be guaranteed to not be removed (such as during DCE) or reordered
    676    in the same thread.  The original call expression is held in CALLEXP.  */
    677 
    678 static tree
    679 expand_volatile_store (tree callexp)
    680 {
    681   tree ptr = CALL_EXPR_ARG (callexp, 0);
    682   tree ptrtype = TREE_TYPE (ptr);
    683   gcc_assert (POINTER_TYPE_P (ptrtype));
    684 
    685   /* (T) *(volatile T *) ptr;  */
    686   tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE);
    687   tree result = indirect_ref (type, ptr);
    688   TREE_THIS_VOLATILE (result) = 1;
    689 
    690   /* (*(volatile T *) ptr) = value;  */
    691   tree value = CALL_EXPR_ARG (callexp, 1);
    692   return modify_expr (result, value);
    693 }
    694 
    695 /* If CALLEXP is for an intrinsic , expand and return inlined compiler
    696    generated instructions.  Most map directly to GCC builtins, others
    697    require a little extra work around them.  */
    698 
    699 tree
    700 maybe_expand_intrinsic (tree callexp)
    701 {
    702   tree callee = CALL_EXPR_FN (callexp);
    703 
    704   if (TREE_CODE (callee) == ADDR_EXPR)
    705     callee = TREE_OPERAND (callee, 0);
    706 
    707   if (TREE_CODE (callee) != FUNCTION_DECL)
    708     return callexp;
    709 
    710   /* Don't expand CTFE-only intrinsics outside of semantic processing.  */
    711   if (DECL_BUILT_IN_CTFE (callee) && !doing_semantic_analysis_p)
    712     return callexp;
    713 
    714   intrinsic_code intrinsic = DECL_INTRINSIC_CODE (callee);
    715   built_in_function code;
    716 
    717   switch (intrinsic)
    718     {
    719     case INTRINSIC_NONE:
    720       return callexp;
    721 
    722     case INTRINSIC_BSF:
    723       return expand_intrinsic_bsf (callexp);
    724 
    725     case INTRINSIC_BSR:
    726       return expand_intrinsic_bsr (callexp);
    727 
    728     case INTRINSIC_BT:
    729     case INTRINSIC_BTC:
    730     case INTRINSIC_BTR:
    731     case INTRINSIC_BTS:
    732       return expand_intrinsic_bt (intrinsic, callexp);
    733 
    734     case INTRINSIC_BSWAP:
    735       return expand_intrinsic_bswap (callexp);
    736 
    737     case INTRINSIC_POPCNT:
    738       return expand_intrinsic_popcnt (callexp);
    739 
    740     case INTRINSIC_COS:
    741       return call_builtin_fn (callexp, BUILT_IN_COSL, 1,
    742 			      CALL_EXPR_ARG (callexp, 0));
    743 
    744     case INTRINSIC_SIN:
    745       return call_builtin_fn (callexp, BUILT_IN_SINL, 1,
    746 			      CALL_EXPR_ARG (callexp, 0));
    747 
    748     case INTRINSIC_RNDTOL:
    749       /* Not sure if llroundl stands as a good replacement for the
    750 	 expected behavior of rndtol.  */
    751       return call_builtin_fn (callexp, BUILT_IN_LLROUNDL, 1,
    752 			      CALL_EXPR_ARG (callexp, 0));
    753 
    754     case INTRINSIC_SQRT:
    755     case INTRINSIC_SQRTF:
    756     case INTRINSIC_SQRTL:
    757       return expand_intrinsic_sqrt (intrinsic, callexp);
    758 
    759     case INTRINSIC_LDEXP:
    760       return call_builtin_fn (callexp, BUILT_IN_LDEXPL, 2,
    761 			      CALL_EXPR_ARG (callexp, 0),
    762 			      CALL_EXPR_ARG (callexp, 1));
    763 
    764     case INTRINSIC_FABS:
    765       return call_builtin_fn (callexp, BUILT_IN_FABSL, 1,
    766 			      CALL_EXPR_ARG (callexp, 0));
    767 
    768     case INTRINSIC_RINT:
    769       return call_builtin_fn (callexp, BUILT_IN_RINTL, 1,
    770 			      CALL_EXPR_ARG (callexp, 0));
    771 
    772     case INTRINSIC_TAN:
    773       return call_builtin_fn (callexp, BUILT_IN_TANL, 1,
    774 			      CALL_EXPR_ARG (callexp, 0));
    775 
    776     case INTRINSIC_ISNAN:
    777       return call_builtin_fn (callexp, BUILT_IN_ISNAN, 1,
    778 			      CALL_EXPR_ARG (callexp, 0));
    779 
    780     case INTRINSIC_ISINFINITY:
    781       return call_builtin_fn (callexp, BUILT_IN_ISINF, 1,
    782 			      CALL_EXPR_ARG (callexp, 0));
    783 
    784     case INTRINSIC_ISFINITE:
    785       return call_builtin_fn (callexp, BUILT_IN_ISFINITE, 1,
    786 			      CALL_EXPR_ARG (callexp, 0));
    787 
    788     case INTRINSIC_EXP:
    789       return call_builtin_fn (callexp, BUILT_IN_EXPL, 1,
    790 			      CALL_EXPR_ARG (callexp, 0));
    791 
    792     case INTRINSIC_EXPM1:
    793       return call_builtin_fn (callexp, BUILT_IN_EXPM1L, 1,
    794 			      CALL_EXPR_ARG (callexp, 0));
    795 
    796     case INTRINSIC_EXP2:
    797       return call_builtin_fn (callexp, BUILT_IN_EXP2L, 1,
    798 			      CALL_EXPR_ARG (callexp, 0));
    799 
    800     case INTRINSIC_LOG:
    801       return call_builtin_fn (callexp, BUILT_IN_LOGL, 1,
    802 			      CALL_EXPR_ARG (callexp, 0));
    803 
    804     case INTRINSIC_LOG2:
    805       return call_builtin_fn (callexp, BUILT_IN_LOG2L, 1,
    806 			      CALL_EXPR_ARG (callexp, 0));
    807 
    808     case INTRINSIC_LOG10:
    809       return call_builtin_fn (callexp, BUILT_IN_LOG10L, 1,
    810 			      CALL_EXPR_ARG (callexp, 0));
    811 
    812     case INTRINSIC_ROUND:
    813       return call_builtin_fn (callexp, BUILT_IN_ROUNDL, 1,
    814 			      CALL_EXPR_ARG (callexp, 0));
    815 
    816     case INTRINSIC_FLOORF:
    817     case INTRINSIC_FLOOR:
    818     case INTRINSIC_FLOORL:
    819       code = (intrinsic == INTRINSIC_FLOOR) ? BUILT_IN_FLOOR
    820 	: (intrinsic == INTRINSIC_FLOORF) ? BUILT_IN_FLOORF
    821 	: BUILT_IN_FLOORL;
    822       return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0));
    823 
    824     case INTRINSIC_CEILF:
    825     case INTRINSIC_CEIL:
    826     case INTRINSIC_CEILL:
    827       code = (intrinsic == INTRINSIC_CEIL) ? BUILT_IN_CEIL
    828 	: (intrinsic == INTRINSIC_CEILF) ? BUILT_IN_CEILF
    829 	: BUILT_IN_CEILL;
    830       return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0));
    831 
    832     case INTRINSIC_TRUNC:
    833       return call_builtin_fn (callexp, BUILT_IN_TRUNCL, 1,
    834 			      CALL_EXPR_ARG (callexp, 0));
    835 
    836     case INTRINSIC_FMIN:
    837       return call_builtin_fn (callexp, BUILT_IN_FMINL, 2,
    838 			      CALL_EXPR_ARG (callexp, 0),
    839 			      CALL_EXPR_ARG (callexp, 1));
    840 
    841     case INTRINSIC_FMAX:
    842       return call_builtin_fn (callexp, BUILT_IN_FMAXL, 2,
    843 			      CALL_EXPR_ARG (callexp, 0),
    844 			      CALL_EXPR_ARG (callexp, 1));
    845 
    846     case INTRINSIC_COPYSIGN:
    847       return expand_intrinsic_copysign (callexp);
    848 
    849     case INTRINSIC_POW:
    850       return expand_intrinsic_pow (callexp);
    851 
    852     case INTRINSIC_FMA:
    853       return call_builtin_fn (callexp, BUILT_IN_FMAL, 3,
    854 			      CALL_EXPR_ARG (callexp, 0),
    855 			      CALL_EXPR_ARG (callexp, 1),
    856 			      CALL_EXPR_ARG (callexp, 2));
    857 
    858     case INTRINSIC_TOPREC:
    859       return expand_intrinsic_toprec (callexp);
    860 
    861     case INTRINSIC_VA_ARG:
    862     case INTRINSIC_C_VA_ARG:
    863       return expand_intrinsic_vaarg (callexp);
    864 
    865     case INTRINSIC_VASTART:
    866       return expand_intrinsic_vastart (callexp);
    867 
    868     case INTRINSIC_ADDS:
    869     case INTRINSIC_SUBS:
    870     case INTRINSIC_MULS:
    871     case INTRINSIC_NEGS:
    872       return expand_intrinsic_checkedint (intrinsic, callexp);
    873 
    874     case INTRINSIC_VLOAD:
    875       return expand_volatile_load (callexp);
    876 
    877     case INTRINSIC_VSTORE:
    878       return expand_volatile_store (callexp);
    879 
    880     default:
    881       gcc_unreachable ();
    882     }
    883 }
    884