/* Create static initializers for the information returned by
direct_internal_fn. */
-#define not_direct { -2, -2, false }
-#define mask_load_direct { -1, 2, false }
-#define load_lanes_direct { -1, -1, false }
-#define mask_load_lanes_direct { -1, -1, false }
-#define gather_load_direct { 3, 1, false }
-#define len_load_direct { -1, -1, false }
-#define mask_store_direct { 3, 2, false }
-#define store_lanes_direct { 0, 0, false }
-#define mask_store_lanes_direct { 0, 0, false }
-#define vec_cond_mask_direct { 1, 0, false }
-#define vec_cond_direct { 2, 0, false }
-#define scatter_store_direct { 3, 1, false }
-#define len_store_direct { 3, 3, false }
-#define vec_set_direct { 3, 3, false }
-#define unary_direct { 0, 0, true }
-#define binary_direct { 0, 0, true }
-#define ternary_direct { 0, 0, true }
-#define cond_unary_direct { 1, 1, true }
-#define cond_binary_direct { 1, 1, true }
-#define cond_ternary_direct { 1, 1, true }
-#define while_direct { 0, 2, false }
-#define fold_extract_direct { 2, 2, false }
-#define fold_left_direct { 1, 1, false }
-#define mask_fold_left_direct { 1, 1, false }
-#define check_ptrs_direct { 0, 0, false }
+#define not_direct { -2, -2, false, false }
+#define direct_insn { -2, -2, true, false }
+#define optab1(TYPE0) { TYPE0, TYPE0, true, false }
+#define optab2(TYPE0, TYPE1) { TYPE0, TYPE1, true, false }
+#define vectorizable_optab1(TYPE0) { TYPE0, TYPE0, true, true }
+
+#define mask_load_direct optab2 (-1, 2)
+#define load_lanes_direct optab1 (-1)
+#define mask_load_lanes_direct optab1 (-1)
+#define gather_load_direct optab2 (3, 1)
+#define len_load_direct optab1 (-1)
+#define mask_store_direct optab2 (3, 2)
+#define store_lanes_direct optab1 (0)
+#define mask_store_lanes_direct optab1 (0)
+#define vec_cond_mask_direct optab2 (1, 0)
+#define vec_cond_direct optab2 (2, 0)
+#define scatter_store_direct optab2 (3, 1)
+#define len_store_direct optab1 (3)
+#define vec_set_direct optab1 (3)
+#define unary_direct vectorizable_optab1 (0)
+#define binary_direct vectorizable_optab1 (0)
+#define ternary_direct vectorizable_optab1 (0)
+#define cond_unary_direct vectorizable_optab1 (1)
+#define cond_binary_direct vectorizable_optab1 (1)
+#define cond_ternary_direct vectorizable_optab1 (1)
+#define while_direct optab2 (0, 2)
+#define fold_extract_direct optab1 (2)
+#define fold_left_direct optab1 (1)
+#define mask_fold_left_direct optab1 (1)
+#define check_ptrs_direct optab1 (0)
const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
UNSIGNED_OPTAB, TYPE) TYPE##_direct,
+#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
+ direct_insn,
#include "internal-fn.def"
not_direct
};
gcc_unreachable ();
}
-/* Allocate per-lane storage and begin non-uniform execution region. */
-
-static void
-expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_enter ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_enter, 1, 2);
-}
-
-/* Deallocate per-lane storage and leave non-uniform execution region. */
-
-static void
-expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_exit ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_exit, 0, 1);
-}
-
-/* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
- without SIMT execution this should be expanded in omp_device_lower pass. */
-
-static void
-expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_lane ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_lane, 1, 0);
-}
-
/* This should get expanded in omp_device_lower pass. */
static void
gcc_unreachable ();
}
-/* Lane index of the first SIMT lane that supplies a non-zero argument.
- This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
- lane that executed the last iteration for handling OpenMP lastprivate. */
-
-static void
-expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_last_lane ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_last_lane, 1, 1);
-}
-
-/* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
-
-static void
-expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_ordered ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_ordered, 1, 1);
-}
-
-/* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
- any lane supplies a non-zero argument. */
-
-static void
-expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_vote_any ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_vote_any, 1, 1);
-}
-
-/* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
- is destination lane index XOR given offset. */
-
-static void
-expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_xchg_bfly ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_bfly, 1, 2);
-}
-
-/* Exchange between SIMT lanes according to given source lane index. */
-
-static void
-expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
-{
- gcc_assert (targetm.have_omp_simt_xchg_idx ());
- expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_idx, 1, 2);
-}
-
/* This should get expanded in adjust_simduid_builtins. */
static void
direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
{
const direct_internal_fn_info &info = direct_internal_fn (fn);
+ if (info.type0 == -2)
+ /* Functions created by DEF_INTERNAL_INSN_FN are not type-dependent. */
+ return tree_pair {};
+
tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
return tree_pair (type0, type1);
direct_internal_fn_types (internal_fn fn, gcall *call)
{
const direct_internal_fn_info &info = direct_internal_fn (fn);
+ if (info.type0 == -2)
+ /* Functions created by DEF_INTERNAL_INSN_FN are not type-dependent. */
+ return tree_pair {};
+
tree op0 = (info.type0 < 0
? gimple_call_lhs (call)
: gimple_call_arg (call, info.type0));
return direct_##TYPE##_optab_supported_p (which_optab, types, \
opt_type); \
}
+#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
+ case IFN_##CODE: return targetm.have_##INSN ();
#include "internal-fn.def"
case IFN_LAST:
optab which_optab = direct_internal_fn_optab (fn, types); \
expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
}
+#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
+ static void \
+ expand_##CODE (internal_fn, gcall *stmt) \
+ { \
+ gcc_assert (targetm.have_##INSN ()); \
+ expand_fn_using_insn (stmt, targetm.code_for_##INSN, \
+ NOUTPUTS, NINPUTS); \
+ }
#include "internal-fn.def"
/* Routines to expand each internal function, indexed by function number.
UNSIGNED_OPTAB, TYPE)
DEF_INTERNAL_FLT_FN (NAME, FLAGS, OPTAB, TYPE)
DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE)
+ DEF_INTERNAL_INSN_FN (NAME, FLAGS, INSN, NOUTPUTS, NINPUTS)
where NAME is the name of the function, FLAGS is a set of
ECF_* flags and FNSPEC is a string describing functions fnspec.
says that the function extends the C-level BUILT_IN_<NAME>{,L,LL,IMAX}
group of functions to any integral mode (including vector modes).
+ DEF_INTERNAL_INSN_FN defines an internal function that maps to target
+ instruction INSN, which is one of those defined in target-insns.def.
+ The instruction has NOUTPUTS output operands (either 0 or 1) and
+ NINPUTS input operands.
+
Each entry must have a corresponding expander of the form:
void expand_NAME (gimple_call stmt)
DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
#endif
+#ifndef DEF_INTERNAL_INSN_FN
+#define DEF_INTERNAL_INSN_FN(NAME, FLAGS, INSN, NOUTPUTS, NINPUTS) \
+ DEF_INTERNAL_FN (NAME, FLAGS | ECF_LEAF, NULL)
+#endif
+
DEF_INTERNAL_OPTAB_FN (MASK_LOAD, ECF_PURE, maskload, mask_load)
DEF_INTERNAL_OPTAB_FN (LOAD_LANES, ECF_CONST, vec_load_lanes, load_lanes)
DEF_INTERNAL_OPTAB_FN (MASK_LOAD_LANES, ECF_PURE,
DEF_INTERNAL_FN (GOMP_USE_SIMT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (GOMP_SIMT_ENTER, ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_ENTER_ALLOC, ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_EXIT, ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_ENTER_ALLOC, ECF_NOTHROW, omp_simt_enter, 1, 2)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_EXIT, ECF_NOTHROW, omp_simt_exit, 0, 1)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_LANE, ECF_NOVOPS | ECF_NOTHROW,
+ omp_simt_lane, 1, 0)
DEF_INTERNAL_FN (GOMP_SIMT_VF, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_LAST_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_ORDERED_PRED, ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_VOTE_ANY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_XCHG_BFLY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
-DEF_INTERNAL_FN (GOMP_SIMT_XCHG_IDX, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_LAST_LANE, ECF_NOVOPS | ECF_NOTHROW,
+ omp_simt_last_lane, 1, 1)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_ORDERED_PRED, ECF_NOTHROW,
+ omp_simt_ordered, 1, 1)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_VOTE_ANY, ECF_NOVOPS | ECF_NOTHROW,
+ omp_simt_vote_any, 1, 1)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_XCHG_BFLY, ECF_NOVOPS | ECF_NOTHROW,
+ omp_simt_xchg_bfly, 1, 2)
+DEF_INTERNAL_INSN_FN (GOMP_SIMT_XCHG_IDX, ECF_NOVOPS | ECF_NOTHROW,
+ omp_simt_xchg_idx, 1, 2)
DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
/* <=> optimization. */
DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+#undef DEF_INTERNAL_INSN_FN
#undef DEF_INTERNAL_INT_FN
#undef DEF_INTERNAL_FLT_FN
#undef DEF_INTERNAL_FLT_FLOATN_FN