Skip to content

Commit f8baf40

Browse files
committed
Add a general mapping from internal fns to target insns
Several existing internal functions map directly to an instruction defined in target-insns.def. This patch makes it easier to define more such functions in future. This should help to reduce cut-&-paste, but more importantly, it allows the difference between optab functions and target-insns.def functions to be abstracted away; both are now treated as “directly-mapped”. gcc/ * internal-fn.def (DEF_INTERNAL_INSN_FN): New macro. (GOMP_SIMT_ENTER_ALLOC, GOMP_SIMT_EXIT, GOMP_SIMT_LANE) (GOMP_SIMT_LAST_LANE, GOMP_SIMT_ORDERED_PRED, GOMP_SIMT_VOTE_ANY) (GOMP_SIMT_XCHG_BFLY, GOMP_SIMT_XCHG_IDX): Use it. * internal-fn.h (direct_internal_fn_info::directly_mapped): New member variable. (direct_internal_fn_info::vectorizable): Reduce to 1 bit. (direct_internal_fn_p): Also return true for internal functions that map directly to instructions defined target-insns.def. (direct_internal_fn): Adjust comment accordingly. * internal-fn.cc (direct_insn, optab1, optab2, vectorizable_optab1) (vectorizable_optab2): New local macros. (not_direct): Initialize directly_mapped. (mask_load_direct, load_lanes_direct, mask_load_lanes_direct) (gather_load_direct, len_load_direct, mask_store_direct) (store_lanes_direct, mask_store_lanes_direct, vec_cond_mask_direct) (vec_cond_direct, scatter_store_direct, len_store_direct) (vec_set_direct, unary_direct, binary_direct, ternary_direct) (cond_unary_direct, cond_binary_direct, cond_ternary_direct) (while_direct, fold_extract_direct, fold_left_direct) (mask_fold_left_direct, check_ptrs_direct): Use the macros above. (expand_GOMP_SIMT_ENTER_ALLOC, expand_GOMP_SIMT_EXIT): Delete (expand_GOMP_SIMT_LANE, expand_GOMP_SIMT_LAST_LANE): Likewise; (expand_GOMP_SIMT_ORDERED_PRED, expand_GOMP_SIMT_VOTE_ANY): Likewise. (expand_GOMP_SIMT_XCHG_BFLY, expand_GOMP_SIMT_XCHG_IDX): Likewise. (direct_internal_fn_types): Handle functions that map to instructions defined in target-insns.def. (direct_internal_fn_types): Likewise. (direct_internal_fn_supported_p): Likewise. (internal_fn_expanders): Likewise.
1 parent 1d205db commit f8baf40

File tree

3 files changed

+87
-119
lines changed

3 files changed

+87
-119
lines changed

gcc/internal-fn.cc

Lines changed: 50 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -105,37 +105,44 @@ init_internal_fns ()
105105

106106
/* Create static initializers for the information returned by
107107
direct_internal_fn. */
108-
#define not_direct { -2, -2, false }
109-
#define mask_load_direct { -1, 2, false }
110-
#define load_lanes_direct { -1, -1, false }
111-
#define mask_load_lanes_direct { -1, -1, false }
112-
#define gather_load_direct { 3, 1, false }
113-
#define len_load_direct { -1, -1, false }
114-
#define mask_store_direct { 3, 2, false }
115-
#define store_lanes_direct { 0, 0, false }
116-
#define mask_store_lanes_direct { 0, 0, false }
117-
#define vec_cond_mask_direct { 1, 0, false }
118-
#define vec_cond_direct { 2, 0, false }
119-
#define scatter_store_direct { 3, 1, false }
120-
#define len_store_direct { 3, 3, false }
121-
#define vec_set_direct { 3, 3, false }
122-
#define unary_direct { 0, 0, true }
123-
#define binary_direct { 0, 0, true }
124-
#define ternary_direct { 0, 0, true }
125-
#define cond_unary_direct { 1, 1, true }
126-
#define cond_binary_direct { 1, 1, true }
127-
#define cond_ternary_direct { 1, 1, true }
128-
#define while_direct { 0, 2, false }
129-
#define fold_extract_direct { 2, 2, false }
130-
#define fold_left_direct { 1, 1, false }
131-
#define mask_fold_left_direct { 1, 1, false }
132-
#define check_ptrs_direct { 0, 0, false }
108+
#define not_direct { -2, -2, false, false }
109+
#define direct_insn { -2, -2, true, false }
110+
#define optab1(TYPE0) { TYPE0, TYPE0, true, false }
111+
#define optab2(TYPE0, TYPE1) { TYPE0, TYPE1, true, false }
112+
#define vectorizable_optab1(TYPE0) { TYPE0, TYPE0, true, true }
113+
114+
#define mask_load_direct optab2 (-1, 2)
115+
#define load_lanes_direct optab1 (-1)
116+
#define mask_load_lanes_direct optab1 (-1)
117+
#define gather_load_direct optab2 (3, 1)
118+
#define len_load_direct optab1 (-1)
119+
#define mask_store_direct optab2 (3, 2)
120+
#define store_lanes_direct optab1 (0)
121+
#define mask_store_lanes_direct optab1 (0)
122+
#define vec_cond_mask_direct optab2 (1, 0)
123+
#define vec_cond_direct optab2 (2, 0)
124+
#define scatter_store_direct optab2 (3, 1)
125+
#define len_store_direct optab1 (3)
126+
#define vec_set_direct optab1 (3)
127+
#define unary_direct vectorizable_optab1 (0)
128+
#define binary_direct vectorizable_optab1 (0)
129+
#define ternary_direct vectorizable_optab1 (0)
130+
#define cond_unary_direct vectorizable_optab1 (1)
131+
#define cond_binary_direct vectorizable_optab1 (1)
132+
#define cond_ternary_direct vectorizable_optab1 (1)
133+
#define while_direct optab2 (0, 2)
134+
#define fold_extract_direct optab1 (2)
135+
#define fold_left_direct optab1 (1)
136+
#define mask_fold_left_direct optab1 (1)
137+
#define check_ptrs_direct optab1 (0)
133138

134139
const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
135140
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
136141
#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
137142
#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
138143
UNSIGNED_OPTAB, TYPE) TYPE##_direct,
144+
#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
145+
direct_insn,
139146
#include "internal-fn.def"
140147
not_direct
141148
};
@@ -308,34 +315,6 @@ expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
308315
gcc_unreachable ();
309316
}
310317

311-
/* Allocate per-lane storage and begin non-uniform execution region. */
312-
313-
static void
314-
expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
315-
{
316-
gcc_assert (targetm.have_omp_simt_enter ());
317-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_enter, 1, 2);
318-
}
319-
320-
/* Deallocate per-lane storage and leave non-uniform execution region. */
321-
322-
static void
323-
expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
324-
{
325-
gcc_assert (targetm.have_omp_simt_exit ());
326-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_exit, 0, 1);
327-
}
328-
329-
/* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
330-
without SIMT execution this should be expanded in omp_device_lower pass. */
331-
332-
static void
333-
expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
334-
{
335-
gcc_assert (targetm.have_omp_simt_lane ());
336-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_lane, 1, 0);
337-
}
338-
339318
/* This should get expanded in omp_device_lower pass. */
340319

341320
static void
@@ -344,55 +323,6 @@ expand_GOMP_SIMT_VF (internal_fn, gcall *)
344323
gcc_unreachable ();
345324
}
346325

347-
/* Lane index of the first SIMT lane that supplies a non-zero argument.
348-
This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
349-
lane that executed the last iteration for handling OpenMP lastprivate. */
350-
351-
static void
352-
expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
353-
{
354-
gcc_assert (targetm.have_omp_simt_last_lane ());
355-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_last_lane, 1, 1);
356-
}
357-
358-
/* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
359-
360-
static void
361-
expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
362-
{
363-
gcc_assert (targetm.have_omp_simt_ordered ());
364-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_ordered, 1, 1);
365-
}
366-
367-
/* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
368-
any lane supplies a non-zero argument. */
369-
370-
static void
371-
expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
372-
{
373-
gcc_assert (targetm.have_omp_simt_vote_any ());
374-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_vote_any, 1, 1);
375-
}
376-
377-
/* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
378-
is destination lane index XOR given offset. */
379-
380-
static void
381-
expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
382-
{
383-
gcc_assert (targetm.have_omp_simt_xchg_bfly ());
384-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_bfly, 1, 2);
385-
}
386-
387-
/* Exchange between SIMT lanes according to given source lane index. */
388-
389-
static void
390-
expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
391-
{
392-
gcc_assert (targetm.have_omp_simt_xchg_idx ());
393-
expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_idx, 1, 2);
394-
}
395-
396326
/* This should get expanded in adjust_simduid_builtins. */
397327

398328
static void
@@ -3633,6 +3563,10 @@ tree_pair
36333563
direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
36343564
{
36353565
const direct_internal_fn_info &info = direct_internal_fn (fn);
3566+
if (info.type0 == -2)
3567+
/* Functions created by DEF_INTERNAL_INSN_FN are not type-dependent. */
3568+
return tree_pair {};
3569+
36363570
tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
36373571
tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
36383572
return tree_pair (type0, type1);
@@ -3646,6 +3580,10 @@ tree_pair
36463580
direct_internal_fn_types (internal_fn fn, gcall *call)
36473581
{
36483582
const direct_internal_fn_info &info = direct_internal_fn (fn);
3583+
if (info.type0 == -2)
3584+
/* Functions created by DEF_INTERNAL_INSN_FN are not type-dependent. */
3585+
return tree_pair {};
3586+
36493587
tree op0 = (info.type0 < 0
36503588
? gimple_call_lhs (call)
36513589
: gimple_call_arg (call, info.type0));
@@ -3790,6 +3728,8 @@ direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
37903728
return direct_##TYPE##_optab_supported_p (which_optab, types, \
37913729
opt_type); \
37923730
}
3731+
#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
3732+
case IFN_##CODE: return targetm.have_##INSN ();
37933733
#include "internal-fn.def"
37943734

37953735
case IFN_LAST:
@@ -3941,6 +3881,14 @@ set_edom_supported_p (void)
39413881
optab which_optab = direct_internal_fn_optab (fn, types); \
39423882
expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
39433883
}
3884+
#define DEF_INTERNAL_INSN_FN(CODE, FLAGS, INSN, NOUTPUTS, NINPUTS) \
3885+
static void \
3886+
expand_##CODE (internal_fn, gcall *stmt) \
3887+
{ \
3888+
gcc_assert (targetm.have_##INSN ()); \
3889+
expand_fn_using_insn (stmt, targetm.code_for_##INSN, \
3890+
NOUTPUTS, NINPUTS); \
3891+
}
39443892
#include "internal-fn.def"
39453893

39463894
/* Routines to expand each internal function, indexed by function number.

gcc/internal-fn.def

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
3434
UNSIGNED_OPTAB, TYPE)
3535
DEF_INTERNAL_FLT_FN (NAME, FLAGS, OPTAB, TYPE)
3636
DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE)
37+
DEF_INTERNAL_INSN_FN (NAME, FLAGS, INSN, NOUTPUTS, NINPUTS)
3738

3839
where NAME is the name of the function, FLAGS is a set of
3940
ECF_* flags and FNSPEC is a string describing functions fnspec.
@@ -82,6 +83,11 @@ along with GCC; see the file COPYING3. If not see
8283
says that the function extends the C-level BUILT_IN_<NAME>{,L,LL,IMAX}
8384
group of functions to any integral mode (including vector modes).
8485

86+
DEF_INTERNAL_INSN_FN defines an internal function that maps to target
87+
instruction INSN, which is one of those defined in target-insns.def.
88+
The instruction has NOUTPUTS output operands (either 0 or 1) and
89+
NINPUTS input operands.
90+
8591
Each entry must have a corresponding expander of the form:
8692

8793
void expand_NAME (gimple_call stmt)
@@ -120,6 +126,11 @@ along with GCC; see the file COPYING3. If not see
120126
DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
121127
#endif
122128

129+
#ifndef DEF_INTERNAL_INSN_FN
130+
#define DEF_INTERNAL_INSN_FN(NAME, FLAGS, INSN, NOUTPUTS, NINPUTS) \
131+
DEF_INTERNAL_FN (NAME, FLAGS | ECF_LEAF, NULL)
132+
#endif
133+
123134
DEF_INTERNAL_OPTAB_FN (MASK_LOAD, ECF_PURE, maskload, mask_load)
124135
DEF_INTERNAL_OPTAB_FN (LOAD_LANES, ECF_CONST, vec_load_lanes, load_lanes)
125136
DEF_INTERNAL_OPTAB_FN (MASK_LOAD_LANES, ECF_PURE,
@@ -315,15 +326,21 @@ DEF_INTERNAL_INT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary)
315326

316327
DEF_INTERNAL_FN (GOMP_USE_SIMT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
317328
DEF_INTERNAL_FN (GOMP_SIMT_ENTER, ECF_LEAF | ECF_NOTHROW, NULL)
318-
DEF_INTERNAL_FN (GOMP_SIMT_ENTER_ALLOC, ECF_LEAF | ECF_NOTHROW, NULL)
319-
DEF_INTERNAL_FN (GOMP_SIMT_EXIT, ECF_LEAF | ECF_NOTHROW, NULL)
320-
DEF_INTERNAL_FN (GOMP_SIMT_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
329+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_ENTER_ALLOC, ECF_NOTHROW, omp_simt_enter, 1, 2)
330+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_EXIT, ECF_NOTHROW, omp_simt_exit, 0, 1)
331+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_LANE, ECF_NOVOPS | ECF_NOTHROW,
332+
omp_simt_lane, 1, 0)
321333
DEF_INTERNAL_FN (GOMP_SIMT_VF, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
322-
DEF_INTERNAL_FN (GOMP_SIMT_LAST_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
323-
DEF_INTERNAL_FN (GOMP_SIMT_ORDERED_PRED, ECF_LEAF | ECF_NOTHROW, NULL)
324-
DEF_INTERNAL_FN (GOMP_SIMT_VOTE_ANY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
325-
DEF_INTERNAL_FN (GOMP_SIMT_XCHG_BFLY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
326-
DEF_INTERNAL_FN (GOMP_SIMT_XCHG_IDX, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
334+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_LAST_LANE, ECF_NOVOPS | ECF_NOTHROW,
335+
omp_simt_last_lane, 1, 1)
336+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_ORDERED_PRED, ECF_NOTHROW,
337+
omp_simt_ordered, 1, 1)
338+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_VOTE_ANY, ECF_NOVOPS | ECF_NOTHROW,
339+
omp_simt_vote_any, 1, 1)
340+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_XCHG_BFLY, ECF_NOVOPS | ECF_NOTHROW,
341+
omp_simt_xchg_bfly, 1, 2)
342+
DEF_INTERNAL_INSN_FN (GOMP_SIMT_XCHG_IDX, ECF_NOVOPS | ECF_NOTHROW,
343+
omp_simt_xchg_idx, 1, 2)
327344
DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
328345
DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
329346
DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
@@ -433,6 +450,7 @@ DEF_INTERNAL_FN (SHUFFLEVECTOR, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
433450
/* <=> optimization. */
434451
DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
435452

453+
#undef DEF_INTERNAL_INSN_FN
436454
#undef DEF_INTERNAL_INT_FN
437455
#undef DEF_INTERNAL_FLT_FN
438456
#undef DEF_INTERNAL_FLT_FLOATN_FN

gcc/internal-fn.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ internal_fn_fnspec (enum internal_fn fn)
133133
return internal_fn_fnspec_array[(int) fn];
134134
}
135135

136-
/* Describes an internal function that maps directly to an optab. */
136+
/* Describes an internal function that maps directly to either an optab
137+
or an instruction defined in target-insns.def. */
137138
struct direct_internal_fn_info
138139
{
139140
/* optabs can be parameterized by one or two modes. These fields describe
@@ -144,24 +145,25 @@ struct direct_internal_fn_info
144145
function isn't directly mapped to an optab. */
145146
signed int type0 : 8;
146147
signed int type1 : 8;
148+
/* True if the function is directly mapped to either an optab or an
149+
instruction defined in target-insns.def. */
150+
unsigned int directly_mapped : 1;
147151
/* True if the function is pointwise, so that it can be vectorized by
148152
converting the return type and all argument types to vectors of the
149153
same number of elements. E.g. we can vectorize an IFN_SQRT on
150-
floats as an IFN_SQRT on vectors of N floats.
151-
152-
This only needs 1 bit, but occupies the full 16 to ensure a nice
153-
layout. */
154-
unsigned int vectorizable : 16;
154+
floats as an IFN_SQRT on vectors of N floats. */
155+
unsigned int vectorizable : 1;
155156
};
156157

157158
extern const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1];
158159

159-
/* Return true if FN is mapped directly to an optab. */
160+
/* Return true if FN is mapped directly to either an optab or an instruction
161+
defined in target-insns.def. */
160162

161163
inline bool
162164
direct_internal_fn_p (internal_fn fn)
163165
{
164-
return direct_internal_fn_array[fn].type0 >= -1;
166+
return direct_internal_fn_array[fn].directly_mapped;
165167
}
166168

167169
/* Return true if FN is a direct internal function that can be vectorized by
@@ -175,7 +177,7 @@ vectorizable_internal_fn_p (internal_fn fn)
175177
return direct_internal_fn_array[fn].vectorizable;
176178
}
177179

178-
/* Return optab information about internal function FN. Only meaningful
180+
/* Return information about internal function FN. Only meaningful
179181
if direct_internal_fn_p (FN). */
180182

181183
inline const direct_internal_fn_info &

0 commit comments

Comments
 (0)