From 6ee874f1353933b1427b5e2953358eb3424090d5 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 14 Jul 2020 18:45:42 +0200 Subject: [PATCH] d: Refactor matching and lowering of intrinsic functions. Intrinsics are now matched explicitly, rather than through a common alias where there are multiple overrides for a common intrinsic. Where there is a corresponding DECL_FUNCTION_CODE, that is now stored in the D intrinsic array. All run-time std.math intrinsics have been removed, as the library implementation already forwards to core.math. gcc/d/ChangeLog: * d-tree.h (DEF_D_INTRINSIC): Rename second argument from A to B. * intrinsics.cc (intrinsic_decl): Add built_in field. (DEF_D_INTRINSIC): Rename second argument from ALIAS to BUILTIN. (maybe_set_intrinsic): Handle new intrinsic codes. (expand_intrinsic_bt): Likewise. (expand_intrinsic_checkedint): Likewise. (expand_intrinsic_bswap): Remove. (expand_intrinsic_sqrt): Remove. (maybe_expand_intrinsic): Group together intrinsic cases that map directly to gcc built-ins. * intrinsics.def (DEF_D_BUILTIN): Rename second argument from A to B. Update all callers to pass equivalent DECL_FUNCTION_CODE. (DEF_CTFE_BUILTIN): Likewise. (STD_COS): Remove intrinsic. (STD_FABS): Remove intrinsic. (STD_LDEXP): Remove intrinsic. (STD_RINT): Remove intrinsic. (STD_RNDTOL): Remove intrinsic. (STD_SIN): Remove intrinsic. (STD_SQRTF): Remove intrinsic. (STD_SQRT): Remove intrinsic. (STD_SQRTL): Remove intrinsic. gcc/testsuite/ChangeLog: * gdc.dg/intrinsics.d: New test. --- gcc/d/d-tree.h | 2 +- gcc/d/intrinsics.cc | 342 ++++++++++++++---------------- gcc/d/intrinsics.def | 170 +++++++-------- gcc/testsuite/gdc.dg/intrinsics.d | 117 ++++++++++ 4 files changed, 358 insertions(+), 273 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/intrinsics.d diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index b4b832f9ad8..d92418a55c9 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -80,7 +80,7 @@ enum level_kind enum intrinsic_code { -#define DEF_D_INTRINSIC(CODE, A, N, M, D, C) INTRINSIC_ ## CODE, +#define DEF_D_INTRINSIC(CODE, B, N, M, D, C) INTRINSIC_ ## CODE, #include "intrinsics.def" diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc index ba7e6aef6ed..7ef1ec5ea20 100644 --- a/gcc/d/intrinsics.cc +++ b/gcc/d/intrinsics.cc @@ -40,9 +40,12 @@ along with GCC; see the file COPYING3. If not see struct intrinsic_decl { - /* The DECL_FUNCTION_CODE of this decl. */ + /* The DECL_INTRINSIC_CODE of this decl. */ intrinsic_code code; + /* The DECL_FUNCTION_CODE of this decl, if it directly maps to any. */ + built_in_function built_in; + /* The name of the intrinsic. */ const char *name; @@ -58,8 +61,8 @@ struct intrinsic_decl static const intrinsic_decl intrinsic_decls[] = { -#define DEF_D_INTRINSIC(CODE, ALIAS, NAME, MODULE, DECO, CTFE) \ - { INTRINSIC_ ## ALIAS, NAME, MODULE, DECO, CTFE }, +#define DEF_D_INTRINSIC(CODE, BUILTIN, NAME, MODULE, DECO, CTFE) \ + { INTRINSIC_ ## CODE, BUILT_IN_ ## BUILTIN, NAME, MODULE, DECO, CTFE }, #include "intrinsics.def" @@ -144,11 +147,28 @@ maybe_set_intrinsic (FuncDeclaration *decl) case INTRINSIC_C_VA_ARG: case INTRINSIC_VASTART: case INTRINSIC_ADDS: + case INTRINSIC_ADDSL: + case INTRINSIC_ADDU: + case INTRINSIC_ADDUL: case INTRINSIC_SUBS: + case INTRINSIC_SUBSL: + case INTRINSIC_SUBU: + case INTRINSIC_SUBUL: case INTRINSIC_MULS: + case INTRINSIC_MULSL: + case INTRINSIC_MULU: + case INTRINSIC_MULUI: + case INTRINSIC_MULUL: case INTRINSIC_NEGS: - case INTRINSIC_VLOAD: - case INTRINSIC_VSTORE: + case INTRINSIC_NEGSL: + case INTRINSIC_VLOAD8: + case INTRINSIC_VLOAD16: + case INTRINSIC_VLOAD32: + case INTRINSIC_VLOAD64: + case INTRINSIC_VSTORE8: + case INTRINSIC_VSTORE16: + case INTRINSIC_VSTORE32: + case INTRINSIC_VSTORE64: break; case INTRINSIC_POW: @@ -302,14 +322,33 @@ expand_intrinsic_bt (intrinsic_code intrinsic, tree callexp) integer_minus_one_node, integer_zero_node); /* Update the bit as needed, only testing the bit for bt(). */ - if (intrinsic == INTRINSIC_BT) - return cond; + tree_code code; + + switch (intrinsic) + { + case INTRINSIC_BT: + case INTRINSIC_BT64: + return cond; + + case INTRINSIC_BTC: + case INTRINSIC_BTC64: + code = BIT_XOR_EXPR; + break; + + case INTRINSIC_BTR: + case INTRINSIC_BTR64: + bitnum = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (bitnum), bitnum); + code = BIT_AND_EXPR; + break; + + case INTRINSIC_BTS: + case INTRINSIC_BTS64: + code = BIT_IOR_EXPR; + break; - tree_code code = (intrinsic == INTRINSIC_BTC) ? BIT_XOR_EXPR - : (intrinsic == INTRINSIC_BTR) ? BIT_AND_EXPR - : (intrinsic == INTRINSIC_BTS) ? BIT_IOR_EXPR - : ERROR_MARK; - gcc_assert (code != ERROR_MARK); + default: + gcc_unreachable (); + } /* ptr[bitnum / size] op= mask; */ if (intrinsic == INTRINSIC_BTR) @@ -325,31 +364,6 @@ expand_intrinsic_bt (intrinsic_code intrinsic, tree callexp) return compound_expr (cond, compound_expr (ptr, tmp)); } -/* Expand a front-end intrinsic call to bswap(). This takes one argument, the - signature to which can be either: - - int bswap (uint arg); - int bswap (ulong arg); - - This swaps all bytes in an N byte type end-to-end. The original call - expression is held in CALLEXP. */ - -static tree -expand_intrinsic_bswap (tree callexp) -{ - tree arg = CALL_EXPR_ARG (callexp, 0); - int argsize = TYPE_PRECISION (TREE_TYPE (arg)); - - /* Which variant of __builtin_bswap* should we call? */ - built_in_function code = (argsize == 32) ? BUILT_IN_BSWAP32 - : (argsize == 64) ? BUILT_IN_BSWAP64 - : END_BUILTINS; - - gcc_assert (code != END_BUILTINS); - - return call_builtin_fn (callexp, code, 1, arg); -} - /* Expand a front-end intrinsic call to popcnt(). This takes one argument, the signature to which can be either: @@ -376,32 +390,6 @@ expand_intrinsic_popcnt (tree callexp) return call_builtin_fn (callexp, code, 1, arg); } -/* Expand a front-end intrinsic call to INTRINSIC, which is either a call to - sqrt(), sqrtf(), sqrtl(). These intrinsics expect to take one argument, - the signature to which can be either: - - float sqrt (float arg); - double sqrt (double arg); - real sqrt (real arg); - - This computes the square root of the given argument. The original call - expression is held in CALLEXP. */ - -static tree -expand_intrinsic_sqrt (intrinsic_code intrinsic, tree callexp) -{ - tree arg = CALL_EXPR_ARG (callexp, 0); - - /* Which variant of __builtin_sqrt* should we call? */ - built_in_function code = (intrinsic == INTRINSIC_SQRT) ? BUILT_IN_SQRT - : (intrinsic == INTRINSIC_SQRTF) ? BUILT_IN_SQRTF - : (intrinsic == INTRINSIC_SQRTL) ? BUILT_IN_SQRTL - : END_BUILTINS; - - gcc_assert (code != END_BUILTINS); - return call_builtin_fn (callexp, code, 1, arg); -} - /* Expand a front-end intrinsic call to copysign(). This takes two arguments, the signature to which can be either: @@ -575,28 +563,54 @@ expand_intrinsic_checkedint (intrinsic_code intrinsic, tree callexp) tree x; tree y; tree overflow; + internal_fn icode; - /* The negs() intrinsic gets turned into SUB_OVERFLOW (0, y). */ - if (intrinsic == INTRINSIC_NEGS) - { - x = fold_convert (type, integer_zero_node); - y = CALL_EXPR_ARG (callexp, 0); - overflow = CALL_EXPR_ARG (callexp, 1); - } - else + /* Which variant of *_OVERFLOW should we generate? */ + switch (intrinsic) { + case INTRINSIC_ADDS: + case INTRINSIC_ADDSL: + case INTRINSIC_ADDU: + case INTRINSIC_ADDUL: x = CALL_EXPR_ARG (callexp, 0); y = CALL_EXPR_ARG (callexp, 1); overflow = CALL_EXPR_ARG (callexp, 2); - } + icode = IFN_ADD_OVERFLOW; + break; - /* Which variant of *_OVERFLOW should we generate? */ - internal_fn icode = (intrinsic == INTRINSIC_ADDS) ? IFN_ADD_OVERFLOW - : (intrinsic == INTRINSIC_SUBS) ? IFN_SUB_OVERFLOW - : (intrinsic == INTRINSIC_MULS) ? IFN_MUL_OVERFLOW - : (intrinsic == INTRINSIC_NEGS) ? IFN_SUB_OVERFLOW - : IFN_LAST; - gcc_assert (icode != IFN_LAST); + case INTRINSIC_SUBS: + case INTRINSIC_SUBSL: + case INTRINSIC_SUBU: + case INTRINSIC_SUBUL: + x = CALL_EXPR_ARG (callexp, 0); + y = CALL_EXPR_ARG (callexp, 1); + overflow = CALL_EXPR_ARG (callexp, 2); + icode = IFN_SUB_OVERFLOW; + break; + + case INTRINSIC_MULS: + case INTRINSIC_MULSL: + case INTRINSIC_MULU: + case INTRINSIC_MULUI: + case INTRINSIC_MULUL: + x = CALL_EXPR_ARG (callexp, 0); + y = CALL_EXPR_ARG (callexp, 1); + overflow = CALL_EXPR_ARG (callexp, 2); + icode = IFN_MUL_OVERFLOW; + break; + + case INTRINSIC_NEGS: + case INTRINSIC_NEGSL: + /* The negs() intrinsic gets turned into SUB_OVERFLOW (0, y). */ + x = fold_convert (type, integer_zero_node); + y = CALL_EXPR_ARG (callexp, 0); + overflow = CALL_EXPR_ARG (callexp, 1); + icode = IFN_SUB_OVERFLOW; + break; + + default: + gcc_unreachable (); + } tree result = build_call_expr_internal_loc (EXPR_LOCATION (callexp), icode, @@ -702,142 +716,87 @@ maybe_expand_intrinsic (tree callexp) return callexp; case INTRINSIC_BSF: + case INTRINSIC_BSF64: return expand_intrinsic_bsf (callexp); case INTRINSIC_BSR: + case INTRINSIC_BSR64: return expand_intrinsic_bsr (callexp); case INTRINSIC_BT: + case INTRINSIC_BT64: case INTRINSIC_BTC: + case INTRINSIC_BTC64: case INTRINSIC_BTR: + case INTRINSIC_BTR64: case INTRINSIC_BTS: + case INTRINSIC_BTS64: return expand_intrinsic_bt (intrinsic, callexp); - case INTRINSIC_BSWAP: - return expand_intrinsic_bswap (callexp); - - case INTRINSIC_POPCNT: + case INTRINSIC_POPCNT32: + case INTRINSIC_POPCNT64: return expand_intrinsic_popcnt (callexp); - case INTRINSIC_COS: - return call_builtin_fn (callexp, BUILT_IN_COSL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_SIN: - return call_builtin_fn (callexp, BUILT_IN_SINL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_RNDTOL: - /* Not sure if llroundl stands as a good replacement for the - expected behavior of rndtol. */ - return call_builtin_fn (callexp, BUILT_IN_LLROUNDL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_SQRT: - case INTRINSIC_SQRTF: - case INTRINSIC_SQRTL: - return expand_intrinsic_sqrt (intrinsic, callexp); - - case INTRINSIC_LDEXP: - return call_builtin_fn (callexp, BUILT_IN_LDEXPL, 2, - CALL_EXPR_ARG (callexp, 0), - CALL_EXPR_ARG (callexp, 1)); - - case INTRINSIC_FABS: - return call_builtin_fn (callexp, BUILT_IN_FABSL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_RINT: - return call_builtin_fn (callexp, BUILT_IN_RINTL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_TAN: - return call_builtin_fn (callexp, BUILT_IN_TANL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_ISNAN: - return call_builtin_fn (callexp, BUILT_IN_ISNAN, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_ISINFINITY: - return call_builtin_fn (callexp, BUILT_IN_ISINF, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_ISFINITE: - return call_builtin_fn (callexp, BUILT_IN_ISFINITE, 1, - CALL_EXPR_ARG (callexp, 0)); - + case INTRINSIC_BSWAP32: + case INTRINSIC_BSWAP64: + case INTRINSIC_CEIL: + case INTRINSIC_CEILF: + case INTRINSIC_CEILL: + case INTRINSIC_COSL: case INTRINSIC_EXP: - return call_builtin_fn (callexp, BUILT_IN_EXPL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_EXPM1: - return call_builtin_fn (callexp, BUILT_IN_EXPM1L, 1, - CALL_EXPR_ARG (callexp, 0)); - case INTRINSIC_EXP2: - return call_builtin_fn (callexp, BUILT_IN_EXP2L, 1, - CALL_EXPR_ARG (callexp, 0)); - + case INTRINSIC_EXPM1: + case INTRINSIC_FABSL: + case INTRINSIC_FLOOR: + case INTRINSIC_FLOORF: + case INTRINSIC_FLOORL: + case INTRINSIC_ISFINITE: + case INTRINSIC_ISINFINITY: + case INTRINSIC_ISNAN: case INTRINSIC_LOG: - return call_builtin_fn (callexp, BUILT_IN_LOGL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_LOG2: - return call_builtin_fn (callexp, BUILT_IN_LOG2L, 1, - CALL_EXPR_ARG (callexp, 0)); - case INTRINSIC_LOG10: - return call_builtin_fn (callexp, BUILT_IN_LOG10L, 1, - CALL_EXPR_ARG (callexp, 0)); - + case INTRINSIC_LOG2: + case INTRINSIC_RINTL: + case INTRINSIC_RNDTOLL: case INTRINSIC_ROUND: - return call_builtin_fn (callexp, BUILT_IN_ROUNDL, 1, - CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_FLOORF: - case INTRINSIC_FLOOR: - case INTRINSIC_FLOORL: - code = (intrinsic == INTRINSIC_FLOOR) ? BUILT_IN_FLOOR - : (intrinsic == INTRINSIC_FLOORF) ? BUILT_IN_FLOORF - : BUILT_IN_FLOORL; - return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0)); - - case INTRINSIC_CEILF: - case INTRINSIC_CEIL: - case INTRINSIC_CEILL: - code = (intrinsic == INTRINSIC_CEIL) ? BUILT_IN_CEIL - : (intrinsic == INTRINSIC_CEILF) ? BUILT_IN_CEILF - : BUILT_IN_CEILL; - return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0)); - + case INTRINSIC_SINL: + case INTRINSIC_SQRT: + case INTRINSIC_SQRTF: + case INTRINSIC_SQRTL: + case INTRINSIC_TAN: case INTRINSIC_TRUNC: - return call_builtin_fn (callexp, BUILT_IN_TRUNCL, 1, + code = intrinsic_decls[intrinsic].built_in; + gcc_assert (code != BUILT_IN_NONE); + return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0)); + case INTRINSIC_FMAX: case INTRINSIC_FMIN: - return call_builtin_fn (callexp, BUILT_IN_FMINL, 2, + case INTRINSIC_LDEXPL: + code = intrinsic_decls[intrinsic].built_in; + gcc_assert (code != BUILT_IN_NONE); + return call_builtin_fn (callexp, code, 2, CALL_EXPR_ARG (callexp, 0), CALL_EXPR_ARG (callexp, 1)); - case INTRINSIC_FMAX: - return call_builtin_fn (callexp, BUILT_IN_FMAXL, 2, + case INTRINSIC_FMA: + code = intrinsic_decls[intrinsic].built_in; + gcc_assert (code != BUILT_IN_NONE); + return call_builtin_fn (callexp, code, 3, CALL_EXPR_ARG (callexp, 0), - CALL_EXPR_ARG (callexp, 1)); + CALL_EXPR_ARG (callexp, 1), + CALL_EXPR_ARG (callexp, 2)); case INTRINSIC_COPYSIGN: + case INTRINSIC_COPYSIGNI: return expand_intrinsic_copysign (callexp); case INTRINSIC_POW: return expand_intrinsic_pow (callexp); - case INTRINSIC_FMA: - return call_builtin_fn (callexp, BUILT_IN_FMAL, 3, - CALL_EXPR_ARG (callexp, 0), - CALL_EXPR_ARG (callexp, 1), - CALL_EXPR_ARG (callexp, 2)); - case INTRINSIC_TOPREC: + case INTRINSIC_TOPRECF: + case INTRINSIC_TOPRECL: return expand_intrinsic_toprec (callexp); case INTRINSIC_VA_ARG: @@ -848,15 +807,32 @@ maybe_expand_intrinsic (tree callexp) return expand_intrinsic_vastart (callexp); case INTRINSIC_ADDS: + case INTRINSIC_ADDSL: + case INTRINSIC_ADDU: + case INTRINSIC_ADDUL: case INTRINSIC_SUBS: + case INTRINSIC_SUBSL: + case INTRINSIC_SUBU: + case INTRINSIC_SUBUL: case INTRINSIC_MULS: + case INTRINSIC_MULSL: + case INTRINSIC_MULU: + case INTRINSIC_MULUI: + case INTRINSIC_MULUL: case INTRINSIC_NEGS: + case INTRINSIC_NEGSL: return expand_intrinsic_checkedint (intrinsic, callexp); - case INTRINSIC_VLOAD: + case INTRINSIC_VLOAD8: + case INTRINSIC_VLOAD16: + case INTRINSIC_VLOAD32: + case INTRINSIC_VLOAD64: return expand_volatile_load (callexp); - case INTRINSIC_VSTORE: + case INTRINSIC_VSTORE8: + case INTRINSIC_VSTORE16: + case INTRINSIC_VSTORE32: + case INTRINSIC_VSTORE64: return expand_volatile_store (callexp); default: diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def index 1782cd7f507..0c32126b1fa 100644 --- a/gcc/d/intrinsics.def +++ b/gcc/d/intrinsics.def @@ -15,11 +15,10 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -/* DEF_D_INTRINSIC (CODE, ALIAS, NAME, MODULE, DECO, CTFE) +/* DEF_D_INTRINSIC (CODE, BUILTIN, NAME, MODULE, DECO, CTFE) CODE The enum code used to refer to this intrinsic. - ALIAS The enum code used to reference the function DECL_FUNCTION_CODE, - if there are multiple modules or decos for a single intrinsic, - they would all refer to this code. + BUILTIN The enum code used to reference the function DECL_FUNCTION_CODE, + if the intrinsic can be mapped 1:1 to a GCC built-in. NAME The name of this intrinsic as a string. MODULE The name of the module which the intrinsic belongs to as a string. DECO The function signature decoration of the intrinsic. @@ -30,102 +29,98 @@ along with GCC; see the file COPYING3. If not see GCC builtin, or are specially handled by the compiler. */ /* A D built-in that has no runtime implementation. */ -#define DEF_D_BUILTIN(C, A, N, M, D) \ - DEF_D_INTRINSIC (C, A, N, M, D, false) +#define DEF_D_BUILTIN(C, B, N, M, D) \ + DEF_D_INTRINSIC (C, B, N, M, D, false) /* A D built-in that is specially recognized only during CTFE. */ -#define DEF_CTFE_BUILTIN(C, A, N, M, D) \ - DEF_D_INTRINSIC (C, A, N, M, D, true) +#define DEF_CTFE_BUILTIN(C, B, N, M, D) \ + DEF_D_INTRINSIC (C, B, N, M, D, true) DEF_D_BUILTIN (NONE, NONE, 0, 0, 0) /* core.bitop intrinsics. */ -DEF_D_BUILTIN (BSF, BSF, "bsf", "core.bitop", "FNaNbNiNfkZi") -DEF_D_BUILTIN (BSR, BSR, "bsr", "core.bitop", "FNaNbNiNfkZi") -DEF_D_BUILTIN (BT, BT, "bt", "core.bitop", "FNaNbNixPkkZi") -DEF_D_BUILTIN (BTC, BTC, "btc", "core.bitop", "FNaNbNiPkkZi") -DEF_D_BUILTIN (BTR, BTR, "btr", "core.bitop", "FNaNbNiPkkZi") -DEF_D_BUILTIN (BTS, BTS, "bts", "core.bitop", "FNaNbNiPkkZi") -DEF_D_BUILTIN (BSF64, BSF, "bsf", "core.bitop", "FNaNbNiNfmZi") -DEF_D_BUILTIN (BSR64, BSR, "bsr", "core.bitop", "FNaNbNiNfmZi") -DEF_D_BUILTIN (BT64, BT, "bt", "core.bitop", "FNaNbNixPmmZi") -DEF_D_BUILTIN (BTC64, BTC, "btc", "core.bitop", "FNaNbNiPmmZi") -DEF_D_BUILTIN (BTR64, BTR, "btr", "core.bitop", "FNaNbNiPmmZi") -DEF_D_BUILTIN (BTS64, BTS, "bts", "core.bitop", "FNaNbNiPmmZi") -DEF_D_BUILTIN (BSWAP, BSWAP, "bswap", "core.bitop", "FNaNbNiNfkZk") -DEF_D_BUILTIN (BSWAP64, BSWAP, "bswap", "core.bitop", "FNaNbNiNfmZm") -DEF_D_BUILTIN (POPCNT, POPCNT, "popcnt", "core.bitop", "FNaNbNiNfkZi") -DEF_D_BUILTIN (POPCNT64, POPCNT, "popcnt", "core.bitop", "FNaNbNiNfmZi") -DEF_D_BUILTIN (VLOAD, VLOAD, "volatileLoad", "core.bitop", "FNbNiNfPhZh") -DEF_D_BUILTIN (VLOAD16, VLOAD, "volatileLoad", "core.bitop", "FNbNiNfPtZt") -DEF_D_BUILTIN (VLOAD32, VLOAD, "volatileLoad", "core.bitop", "FNbNiNfPkZk") -DEF_D_BUILTIN (VLOAD64, VLOAD, "volatileLoad", "core.bitop", "FNbNiNfPmZm") -DEF_D_BUILTIN (VSTORE, VSTORE, "volatileStore", "core.bitop", "FNbNiNfPhhZv") -DEF_D_BUILTIN (VSTORE16, VSTORE, "volatileStore", "core.bitop", "FNbNiNfPttZv") -DEF_D_BUILTIN (VSTORE32, VSTORE, "volatileStore", "core.bitop", "FNbNiNfPkkZv") -DEF_D_BUILTIN (VSTORE64, VSTORE, "volatileStore", "core.bitop", "FNbNiNfPmmZv") +DEF_D_BUILTIN (BSF, NONE, "bsf", "core.bitop", "FNaNbNiNfkZi") +DEF_D_BUILTIN (BSR, NONE, "bsr", "core.bitop", "FNaNbNiNfkZi") +DEF_D_BUILTIN (BT, NONE, "bt", "core.bitop", "FNaNbNixPkkZi") +DEF_D_BUILTIN (BTC, NONE, "btc", "core.bitop", "FNaNbNiPkkZi") +DEF_D_BUILTIN (BTR, NONE, "btr", "core.bitop", "FNaNbNiPkkZi") +DEF_D_BUILTIN (BTS, NONE, "bts", "core.bitop", "FNaNbNiPkkZi") +DEF_D_BUILTIN (BSF64, NONE, "bsf", "core.bitop", "FNaNbNiNfmZi") +DEF_D_BUILTIN (BSR64, NONE, "bsr", "core.bitop", "FNaNbNiNfmZi") +DEF_D_BUILTIN (BT64, NONE, "bt", "core.bitop", "FNaNbNixPmmZi") +DEF_D_BUILTIN (BTC64, NONE, "btc", "core.bitop", "FNaNbNiPmmZi") +DEF_D_BUILTIN (BTR64, NONE, "btr", "core.bitop", "FNaNbNiPmmZi") +DEF_D_BUILTIN (BTS64, NONE, "bts", "core.bitop", "FNaNbNiPmmZi") + +DEF_D_BUILTIN (BSWAP32, BSWAP32, "bswap", "core.bitop", "FNaNbNiNfkZk") +DEF_D_BUILTIN (BSWAP64, BSWAP64, "bswap", "core.bitop", "FNaNbNiNfmZm") + +DEF_D_BUILTIN (POPCNT32, NONE, "popcnt", "core.bitop", "FNaNbNiNfkZi") +DEF_D_BUILTIN (POPCNT64, NONE, "popcnt", "core.bitop", "FNaNbNiNfmZi") + +DEF_D_BUILTIN (VLOAD8, NONE, "volatileLoad", "core.bitop", "FNbNiNfPhZh") +DEF_D_BUILTIN (VLOAD16, NONE, "volatileLoad", "core.bitop", "FNbNiNfPtZt") +DEF_D_BUILTIN (VLOAD32, NONE, "volatileLoad", "core.bitop", "FNbNiNfPkZk") +DEF_D_BUILTIN (VLOAD64, NONE, "volatileLoad", "core.bitop", "FNbNiNfPmZm") +DEF_D_BUILTIN (VSTORE8, NONE, "volatileStore", "core.bitop", "FNbNiNfPhhZv") +DEF_D_BUILTIN (VSTORE16, NONE, "volatileStore", "core.bitop", "FNbNiNfPttZv") +DEF_D_BUILTIN (VSTORE32, NONE, "volatileStore", "core.bitop", "FNbNiNfPkkZv") +DEF_D_BUILTIN (VSTORE64, NONE, "volatileStore", "core.bitop", "FNbNiNfPmmZv") /* core.checkedint intrinsics. */ -DEF_D_BUILTIN (ADDS, ADDS, "adds", "core.checkedint", "FNaNbNiNfiiKbZi") -DEF_D_BUILTIN (ADDSL, ADDS, "adds", "core.checkedint", "FNaNbNiNfllKbZl") -DEF_D_BUILTIN (ADDU, ADDS, "addu", "core.checkedint", "FNaNbNiNfkkKbZk") -DEF_D_BUILTIN (ADDUL, ADDS, "addu", "core.checkedint", "FNaNbNiNfmmKbZm") -DEF_D_BUILTIN (SUBS, SUBS, "subs", "core.checkedint", "FNaNbNiNfiiKbZi") -DEF_D_BUILTIN (SUBSL, SUBS, "subs", "core.checkedint", "FNaNbNiNfllKbZl") -DEF_D_BUILTIN (SUBU, SUBS, "subu", "core.checkedint", "FNaNbNiNfkkKbZk") -DEF_D_BUILTIN (SUBUL, SUBS, "subu", "core.checkedint", "FNaNbNiNfmmKbZm") -DEF_D_BUILTIN (MULS, MULS, "muls", "core.checkedint", "FNaNbNiNfiiKbZi") -DEF_D_BUILTIN (MULSL, MULS, "muls", "core.checkedint", "FNaNbNiNfllKbZl") -DEF_D_BUILTIN (MULU, MULS, "mulu", "core.checkedint", "FNaNbNiNfkkKbZk") -DEF_D_BUILTIN (MULUI, MULS, "mulu", "core.checkedint", "FNaNbNiNfmkKbZm") -DEF_D_BUILTIN (MULUL, MULS, "mulu", "core.checkedint", "FNaNbNiNfmmKbZm") -DEF_D_BUILTIN (NEGS, NEGS, "negs", "core.checkedint", "FNaNbNiNfiKbZi") -DEF_D_BUILTIN (NEGSL, NEGS, "negs", "core.checkedint", "FNaNbNiNflKbZl") +DEF_D_BUILTIN (ADDS, NONE, "adds", "core.checkedint", "FNaNbNiNfiiKbZi") +DEF_D_BUILTIN (ADDSL, NONE, "adds", "core.checkedint", "FNaNbNiNfllKbZl") +DEF_D_BUILTIN (ADDU, NONE, "addu", "core.checkedint", "FNaNbNiNfkkKbZk") +DEF_D_BUILTIN (ADDUL, NONE, "addu", "core.checkedint", "FNaNbNiNfmmKbZm") +DEF_D_BUILTIN (SUBS, NONE, "subs", "core.checkedint", "FNaNbNiNfiiKbZi") +DEF_D_BUILTIN (SUBSL, NONE, "subs", "core.checkedint", "FNaNbNiNfllKbZl") +DEF_D_BUILTIN (SUBU, NONE, "subu", "core.checkedint", "FNaNbNiNfkkKbZk") +DEF_D_BUILTIN (SUBUL, NONE, "subu", "core.checkedint", "FNaNbNiNfmmKbZm") +DEF_D_BUILTIN (MULS, NONE, "muls", "core.checkedint", "FNaNbNiNfiiKbZi") +DEF_D_BUILTIN (MULSL, NONE, "muls", "core.checkedint", "FNaNbNiNfllKbZl") +DEF_D_BUILTIN (MULU, NONE, "mulu", "core.checkedint", "FNaNbNiNfkkKbZk") +DEF_D_BUILTIN (MULUI, NONE, "mulu", "core.checkedint", "FNaNbNiNfmkKbZm") +DEF_D_BUILTIN (MULUL, NONE, "mulu", "core.checkedint", "FNaNbNiNfmmKbZm") +DEF_D_BUILTIN (NEGS, NONE, "negs", "core.checkedint", "FNaNbNiNfiKbZi") +DEF_D_BUILTIN (NEGSL, NONE, "negs", "core.checkedint", "FNaNbNiNflKbZl") /* core.math intrinsics. */ -DEF_D_BUILTIN (COS, COS, "cos", "core.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (FABS, FABS, "fabs", "core.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (LDEXP, LDEXP, "ldexp", "core.math", "FNaNbNiNfeiZe") -DEF_D_BUILTIN (RINT, RINT, "rint", "core.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (RNDTOL, RNDTOL, "rndtol", "core.math", "FNaNbNiNfeZl") -DEF_D_BUILTIN (SIN, SIN, "sin", "core.math", "FNaNbNiNfeZe") +DEF_D_BUILTIN (COSL, COSL, "cos", "core.math", "FNaNbNiNfeZe") +DEF_D_BUILTIN (FABSL, FABSL, "fabs", "core.math", "FNaNbNiNfeZe") +DEF_D_BUILTIN (LDEXPL, LDEXPL, "ldexp", "core.math", "FNaNbNiNfeiZe") +DEF_D_BUILTIN (RINTL, RINTL, "rint", "core.math", "FNaNbNiNfeZe") + +/* Not sure if `llroundl' stands as a good replacement for the expected + behavior of `rndtol()'. */ +DEF_D_BUILTIN (RNDTOLL, LLROUNDL, "rndtol", "core.math", "FNaNbNiNfeZl") + +DEF_D_BUILTIN (SINL, SINL, "sin", "core.math", "FNaNbNiNfeZe") DEF_D_BUILTIN (SQRTF, SQRTF, "sqrt", "core.math", "FNaNbNiNffZf") DEF_D_BUILTIN (SQRT, SQRT, "sqrt", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (SQRTL, SQRTL, "sqrt", "core.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (TOPRECF, TOPREC, "toPrec", "core.math", "FNaNbNffZI1T") -DEF_D_BUILTIN (TOPREC, TOPREC, "toPrec", "core.math", "FNaNbNfdZI1T") -DEF_D_BUILTIN (TOPRECL, TOPREC, "toPrec", "core.math", "FNaNbNfeZI1T") +DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FNaNbNffZI1T") +DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FNaNbNfdZI1T") +DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FNaNbNfeZI1T") /* std.math intrinsics. */ -DEF_D_BUILTIN (STD_COS, COS, "cos", "std.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (STD_FABS, FABS, "fabs", "std.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (STD_LDEXP, LDEXP, "ldexp", "std.math", "FNaNbNiNfeiZe") -DEF_D_BUILTIN (STD_RINT, RINT, "rint", "std.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (STD_RNDTOL, RNDTOL, "rndtol", "std.math", "FNaNbNiNfeZl") -DEF_D_BUILTIN (STD_SIN, SIN, "sin", "std.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (STD_SQRTF, SQRTF, "sqrt", "std.math", "FNaNbNiNffZf") -DEF_D_BUILTIN (STD_SQRT, SQRT, "sqrt", "std.math", "FNaNbNiNfdZd") -DEF_D_BUILTIN (STD_SQRTL, SQRTL, "sqrt", "std.math", "FNaNbNiNfeZe") - -DEF_CTFE_BUILTIN (TAN, TAN, "tan", "std.math", "FNaNbNiNeeZe") +DEF_CTFE_BUILTIN (TAN, TANL, "tan", "std.math", "FNaNbNiNeeZe") DEF_CTFE_BUILTIN (ISNAN, ISNAN, "isNaN", "std.math", "FNaNbNiNeI1XZb") -DEF_CTFE_BUILTIN (ISINFINITY, ISINFINITY, "isInfinity", "std.math", - "FNaNbNiNeI1XZb") +DEF_CTFE_BUILTIN (ISINFINITY, ISINF, "isInfinity", "std.math", "FNaNbNiNeI1XZb") DEF_CTFE_BUILTIN (ISFINITE, ISFINITE, "isFinite", "std.math", "FNaNbNiNeI1XZb") -DEF_CTFE_BUILTIN (EXP, EXP, "exp", "std.math", "FNaNbNiNeeZe") -DEF_CTFE_BUILTIN (EXPM1, EXPM1, "expm1", "std.math", "FNaNbNiNeeZe") -DEF_CTFE_BUILTIN (EXP2, EXP2, "exp2", "std.math", "FNaNbNiNeeZe") +DEF_CTFE_BUILTIN (EXP, EXPL, "exp", "std.math", "FNaNbNiNeeZe") +DEF_CTFE_BUILTIN (EXPM1, EXPM1L, "expm1", "std.math", "FNaNbNiNeeZe") +DEF_CTFE_BUILTIN (EXP2, EXP2L, "exp2", "std.math", "FNaNbNiNeeZe") -DEF_CTFE_BUILTIN (LOG, LOG, "log", "std.math", "FNaNbNiNfeZe") -DEF_CTFE_BUILTIN (LOG2, LOG2, "log2", "std.math", "FNaNbNiNfeZe") -DEF_CTFE_BUILTIN (LOG10, LOG10, "log10", "std.math", "FNaNbNiNfeZe") +DEF_CTFE_BUILTIN (LOG, LOGL, "log", "std.math", "FNaNbNiNfeZe") +DEF_CTFE_BUILTIN (LOG2, LOG2L, "log2", "std.math", "FNaNbNiNfeZe") +DEF_CTFE_BUILTIN (LOG10, LOG10L, "log10", "std.math", "FNaNbNiNfeZe") -DEF_CTFE_BUILTIN (ROUND, ROUND, "round", "std.math", "FNbNiNeeZe") +DEF_CTFE_BUILTIN (ROUND, ROUNDL, "round", "std.math", "FNbNiNeeZe") DEF_CTFE_BUILTIN (FLOORF, FLOORF, "floor", "std.math", "FNaNbNiNefZf") DEF_CTFE_BUILTIN (FLOOR, FLOOR, "floor", "std.math", "FNaNbNiNedZd") DEF_CTFE_BUILTIN (FLOORL, FLOORL, "floor", "std.math", "FNaNbNiNeeZe") @@ -133,24 +128,21 @@ DEF_CTFE_BUILTIN (CEILF, CEILF, "ceil", "std.math", "FNaNbNiNefZf") DEF_CTFE_BUILTIN (CEIL, CEIL, "ceil", "std.math", "FNaNbNiNedZd") DEF_CTFE_BUILTIN (CEILL, CEILL, "ceil", "std.math", "FNaNbNiNeeZe") -DEF_CTFE_BUILTIN (TRUNC, TRUNC, "trunc", "std.math", "FNbNiNeeZe") -DEF_CTFE_BUILTIN (FMIN, FMIN, "fmin", "std.math", "FNaNbNiNfeeZe") -DEF_CTFE_BUILTIN (FMAX, FMAX, "fmax", "std.math", "FNaNbNiNfeeZe") -DEF_CTFE_BUILTIN (COPYSIGN, COPYSIGN, "copysign", "std.math", - "FNaNbNiNeI1RI1XZI1R") -DEF_CTFE_BUILTIN (COPYSIGNI, COPYSIGN, "copysign", "std.math", +DEF_CTFE_BUILTIN (TRUNC, TRUNCL, "trunc", "std.math", "FNbNiNeeZe") +DEF_CTFE_BUILTIN (FMIN, FMINL, "fmin", "std.math", "FNaNbNiNfeeZe") +DEF_CTFE_BUILTIN (FMAX, FMAXL, "fmax", "std.math", "FNaNbNiNfeeZe") +DEF_CTFE_BUILTIN (COPYSIGN, NONE, "copysign", "std.math", "FNaNbNiNeI1RI1XZI1R") +DEF_CTFE_BUILTIN (COPYSIGNI, NONE, "copysign", "std.math", "FNaNbNiNeI1XI1RZI1R") -DEF_CTFE_BUILTIN (POW, POW, "pow", "std.math", "FNaNbNiNeI1FI1GZ@") -DEF_CTFE_BUILTIN (FMA, FMA, "fma", "std.math", "FNaNbNiNfeeeZe") +DEF_CTFE_BUILTIN (POW, NONE, "pow", "std.math", "FNaNbNiNeI1FI1GZ@") +DEF_CTFE_BUILTIN (FMA, FMAL, "fma", "std.math", "FNaNbNiNfeeeZe") /* core.stdc.stdarg intrinsics. */ -DEF_D_BUILTIN (VA_ARG, VA_ARG, "va_arg", "core.stdc.stdarg", - "FKI7va_listKI1TZv") -DEF_D_BUILTIN (C_VA_ARG, C_VA_ARG, "va_arg", "core.stdc.stdarg", - "FKI7va_listZI1T") -DEF_D_BUILTIN (VASTART, VASTART, "va_start", "core.stdc.stdarg", +DEF_D_BUILTIN (VA_ARG, NONE, "va_arg", "core.stdc.stdarg", "FKI7va_listKI1TZv") +DEF_D_BUILTIN (C_VA_ARG, NONE, "va_arg", "core.stdc.stdarg", "FKI7va_listZI1T") +DEF_D_BUILTIN (VASTART, NONE, "va_start", "core.stdc.stdarg", "FJI7va_listKI1TZv") #undef DEF_D_BUILTIN diff --git a/gcc/testsuite/gdc.dg/intrinsics.d b/gcc/testsuite/gdc.dg/intrinsics.d new file mode 100644 index 00000000000..e10c06dd41a --- /dev/null +++ b/gcc/testsuite/gdc.dg/intrinsics.d @@ -0,0 +1,117 @@ +// { dg-do compile } +// { dg-options "-fdump-tree-original" } +import core.bitop; +import core.checkedint; +import core.math; +import core.stdc.stdarg; + +////////////////////////////////////////////////////// +// core.bitop + +// { dg-final { scan-tree-dump-not " bsf " "original" } } +int test_bsf(uint a) { return bsf(a); } +int test_bsf(ulong a) { return bsf(a); } +// { dg-final { scan-tree-dump-not " bsr " "original" } } +int test_bsr(uint a) { return bsr(a); } +int test_bsr(ulong a) { return bsr(a); } +// { dg-final { scan-tree-dump-not " bt " "original" } } +int test_bt(size_t *a, size_t b) { return bt(a, b); } +// { dg-final { scan-tree-dump-not " btc " "original" } } +int test_btc(size_t *a, size_t b) { return btc(a, b); } +// { dg-final { scan-tree-dump-not " btr " "original" } } +int test_btr(size_t *a, size_t b) { return btr(a, b); } +// { dg-final { scan-tree-dump-not " bts " "original" } } +int test_bts(size_t *a, size_t b) { return bts(a, b); } +// { dg-final { scan-tree-dump-not " bswap " "original" } } +uint test_bswap(uint a) { return bswap(a); } +ulong test_bswap(ulong a) { return bswap(a); } +// { dg-final { scan-tree-dump-not " popcnt " "original" } } +int test_popcnt(uint a) { return popcnt(a); } +int test_popcnt(ulong a) { return popcnt(a); } +// { dg-final { scan-tree-dump-not " volatileLoad " "original" } } +ubyte test_volatileLoad(ubyte *a) { return volatileLoad(a); } +ushort test_volatileLoad(ushort *a) { return volatileLoad(a); } +uint test_volatileLoad(uint *a) { return volatileLoad(a); } +ulong test_volatileLoad(ulong *a) { return volatileLoad(a); } +// { dg-final { scan-tree-dump-not " volatileStore " "original" } } +void test_volatileStore(ubyte *a, ubyte b) { return volatileStore(a, b); } +void test_volatileStore(ushort *a, ushort b) { return volatileStore(a, b); } +void test_volatileStore(uint *a, uint b) { return volatileStore(a, b); } +void test_volatileStore(ulong *a, ulong b) { return volatileStore(a, b); } + +////////////////////////////////////////////////////// +// core.checkedint + +// { dg-final { scan-tree-dump-not " adds " "original" } } +int test_adds(int a, int b, ref bool c) { return adds(a, b, c); } +long test_adds(long a, long b, ref bool c) { return adds(a, b, c); } +// { dg-final { scan-tree-dump-not " addu " "original" } } +uint test_addu(uint a, uint b, ref bool c) { return addu(a, b, c); } +ulong test_addu(ulong a, ulong b, ref bool c) { return addu(a, b, c); } +// { dg-final { scan-tree-dump-not " subs " "original" } } +int test_subs(int a, int b, ref bool c) { return subs(a, b, c); } +long test_subs(long a, long b, ref bool c) { return subs(a, b, c); } +// { dg-final { scan-tree-dump-not " subu " "original" } } +uint test_subu(uint a, uint b, ref bool c) { return subu(a, b, c); } +ulong test_subu(ulong a, ulong b, ref bool c) { return subu(a, b, c); } +// { dg-final { scan-tree-dump-not " negs " "original" } } +int test_negs(int a, ref bool b) { return negs(a, b); } +long test_negs(long a, ref bool b) { return negs(a, b); } +// { dg-final { scan-tree-dump-not " muls " "original" } } +int test_muls(int a, int b, ref bool c) { return muls(a, b, c); } +long test_muls(long a, long b, ref bool c) { return muls(a, b, c); } +// { dg-final { scan-tree-dump-not " mulu " "original" } } +uint test_mulu(uint a, uint b, ref bool c) { return mulu(a, b, c); } +ulong test_mulu(ulong a, uint b, ref bool c) { return mulu(a, b, c); } +ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); } + +////////////////////////////////////////////////////// +// core.math + +// { dg-final { scan-tree-dump-not " cos " "original" } } +float test_cos(float a) { return cos(a); } +double test_cos(double a) { return cos(a); } +real test_cos(real a) { return cos(a); } +// { dg-final { scan-tree-dump-not " sin " "original" } } +float test_sin(float a) { return sin(a); } +double test_sin(double a) { return sin(a); } +real test_sin(real a) { return sin(a); } +// { dg-final { scan-tree-dump-not " rndtol " "original" } } +long test_rndtol(float a) { return rndtol(a); } +long test_rndtol(double a) { return rndtol(a); } +long test_rndtol(real a) { return rndtol(a); } +// { dg-final { scan-tree-dump-not " sqrt " "original" } } +float test_sqrt(float a) { return sqrt(a); } +double test_sqrt(double a) { return sqrt(a); } +real test_sqrt(real a) { return sqrt(a); } +// { dg-final { scan-tree-dump-not " ldexp " "original" } } +float test_ldexp(float a, int b) { return ldexp(a, b); } +double test_ldexp(double a, int b) { return ldexp(a, b); } +real test_ldexp(real a, int b) { return ldexp(a, b); } +// { dg-final { scan-tree-dump-not " fabs " "original" } } +float test_fabs(float a) { return fabs(a); } +double test_fabs(double a) { return fabs(a); } +real test_fabs(real a) { return fabs(a); } +// { dg-final { scan-tree-dump-not " rint " "original" } } +float test_rint(float a) { return rint(a); } +double test_rint(double a) { return rint(a); } +real test_rint(real a) { return rint(a); } +// { dg-final { scan-tree-dump-not " toPrec " "original" } } +float test_toPrec(float a) { return toPrec!float(a); } +float test_toPrec(double a) { return toPrec!float(a); } +float test_toPrec(real a) { return toPrec!float(a); } +double test_toPrec(float a) { return toPrec!double(a); } +double test_toPrec(double a) { return toPrec!double(a); } +double test_toPrec(real a) { return toPrec!double(a); } +real test_toPrec(float a) { return toPrec!real(a); } +real test_toPrec(double a) { return toPrec!real(a); } +real test_toPrec(real a) { return toPrec!real(a); } + +////////////////////////////////////////////////////// +// core.stdc.stdarg + +// { dg-final { scan-tree-dump-not " va_arg " "original" } } +void test_va_arg(...) { int a; return va_arg!int(_argptr, a); } +int test_va_arg(...) { return va_arg!int(_argptr); } +// { dg-final { scan-tree-dump-not " va_start " "original" } } +void test_va_start(int a, ...) { return va_start(_argptr, a); } -- 2.30.2