2015-09-24 Nathan Sidwell <nathan@codesourcery.com>
* config/nvptx/nvptx.c (struct builtin_description): Delete.
(nvptx_expand_shuffle_down): Rename to ...
(nvptx_expand_shuffle): ... here. add additional arg for type of
shuffle.
(nvptx_expand_work_red_addr): Rename to ...
(nvptx_expand_worker_addr): ... here.
(nvptx_expand_swap): New.
(nvptx_expand_cmp_swap): New.
(enum nvptx_types): Delete.
(enum nvptx_builtins): Rename builtins. Remove float mode
shuffles, add SWAP and CMP_SWAP.
(builtins): Delete.
(nvptx_init_builtins): Reimplement.
(nvptx_expand_builtin): Likewise.
(nvptx_get_worker_red_addr): Adjust.
(nvptx_generate_vector_shuffle): Adjust.
===================================================================
@@ -4115,36 +4115,28 @@ nvptx_file_end (void)
}
}
-/* Descriptor for a builtin. */
+/* Expander for the shuffle builtins. */
-struct builtin_description
-{
- const char *name;
- unsigned short type;
- rtx (*expander) (tree, rtx, machine_mode, int);
-};
-
-/* Expander for the shuffle down builtins. */
static rtx
-nvptx_expand_shuffle_down (tree exp, rtx target, machine_mode mode, int ignore)
+nvptx_expand_shuffle (tree exp, rtx target, machine_mode mode, int ignore)
{
if (ignore)
return target;
- if (! target)
- target = gen_reg_rtx (mode);
-
rtx src = expand_expr (CALL_EXPR_ARG (exp, 0),
NULL_RTX, mode, EXPAND_NORMAL);
if (!REG_P (src))
src = copy_to_mode_reg (mode, src);
rtx idx = expand_expr (CALL_EXPR_ARG (exp, 1),
+ NULL_RTX, SImode, EXPAND_NORMAL);
+ rtx op = expand_expr (CALL_EXPR_ARG (exp, 2),
NULL_RTX, SImode, EXPAND_NORMAL);
+
if (!REG_P (idx) && GET_CODE (idx) != CONST_INT)
idx = copy_to_mode_reg (SImode, idx);
- rtx pat = nvptx_gen_shuffle (target, src, idx, SHUFFLE_DOWN);
+ rtx pat = nvptx_gen_shuffle (target, src, idx, INTVAL (op));
if (pat)
emit_insn (pat);
@@ -4152,10 +4144,10 @@ nvptx_expand_shuffle_down (tree exp, rtx
}
/* Worker reduction address expander. */
+
static rtx
-nvptx_expand_work_red_addr (tree exp, rtx target,
- machine_mode ARG_UNUSED (mode),
- int ignore)
+nvptx_expand_worker_addr (tree exp, rtx target,
+ machine_mode ARG_UNUSED (mode), int ignore)
{
if (ignore)
return target;
@@ -4205,41 +4197,71 @@ nvptx_expand_work_red_addr (tree exp, rt
return target;
}
-enum nvptx_types
- {
- NT_UINT_UINT_INT,
- NT_ULL_ULL_INT,
- NT_FLT_FLT_INT,
- NT_DBL_DBL_INT,
- NT_PTR_UINT_UINT_UINT_UINT,
- NT_MAX
- };
+static rtx
+nvptx_expand_swap (tree exp, rtx target,
+ machine_mode mode, int ARG_UNUSED (ignore))
+{
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ rtx mem = expand_expr (CALL_EXPR_ARG (exp, 0),
+ NULL_RTX, Pmode, EXPAND_NORMAL);
+ rtx src = expand_expr (CALL_EXPR_ARG (exp, 1),
+ NULL_RTX, mode, EXPAND_NORMAL);
+
+ rtx pat;
+
+ if (mode == SImode)
+ pat = gen_atomic_exchangesi (target, mem, src, const0_rtx);
+ else
+ pat = gen_atomic_exchangedi (target, mem, src, const0_rtx);
+
+ emit_insn (pat);
+
+ return target;
+}
+
+static rtx
+nvptx_expand_cmp_swap (tree exp, rtx target,
+ machine_mode mode, int ARG_UNUSED (ignore))
+{
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ rtx mem = expand_expr (CALL_EXPR_ARG (exp, 0),
+ NULL_RTX, Pmode, EXPAND_NORMAL);
+ rtx cmp = expand_expr (CALL_EXPR_ARG (exp, 1),
+ NULL_RTX, mode, EXPAND_NORMAL);
+ rtx src = expand_expr (CALL_EXPR_ARG (exp, 2),
+ NULL_RTX, mode, EXPAND_NORMAL);
+ rtx pat;
+
+ mem = gen_rtx_MEM (mode, mem);
+
+ if (mode == SImode)
+ pat = gen_atomic_compare_and_swapsi_1 (target, mem, cmp, src, const0_rtx);
+ else
+ pat = gen_atomic_compare_and_swapdi_1 (target, mem, cmp, src, const0_rtx);
+
+ emit_insn (pat);
+
+ return target;
+}
+
/* Codes for all the NVPTX builtins. */
enum nvptx_builtins
{
- NVPTX_BUILTIN_SHUFFLE_DOWN,
- NVPTX_BUILTIN_SHUFFLE_DOWNLL,
- NVPTX_BUILTIN_SHUFFLE_DOWNF,
- NVPTX_BUILTIN_SHUFFLE_DOWND,
- NVPTX_BUILTIN_WORK_RED_ADDR,
+ NVPTX_BUILTIN_SHUFFLE,
+ NVPTX_BUILTIN_SHUFFLELL,
+ NVPTX_BUILTIN_WORKER_ADDR,
+ NVPTX_BUILTIN_SWAP,
+ NVPTX_BUILTIN_SWAPLL,
+ NVPTX_BUILTIN_CMP_SWAP,
+ NVPTX_BUILTIN_CMP_SWAPLL,
NVPTX_BUILTIN_MAX
};
-static const struct builtin_description builtins[] =
-{
- {"__builtin_nvptx_shuffle_down", NT_UINT_UINT_INT,
- nvptx_expand_shuffle_down},
- {"__builtin_nvptx_shuffle_downll", NT_ULL_ULL_INT,
- nvptx_expand_shuffle_down},
- {"__builtin_nvptx_shuffle_downf", NT_FLT_FLT_INT,
- nvptx_expand_shuffle_down},
- {"__builtin_nvptx_shuffle_downd", NT_DBL_DBL_INT,
- nvptx_expand_shuffle_down},
- {"__builtin_nvptx_work_red_addr", NT_PTR_UINT_UINT_UINT_UINT,
- nvptx_expand_work_red_addr},
-};
-
static GTY(()) tree nvptx_builtin_decls[NVPTX_BUILTIN_MAX];
/* Return the NVPTX builtin for CODE. */
@@ -4256,32 +4278,28 @@ nvptx_builtin_decl (unsigned code, bool
static void
nvptx_init_builtins (void)
{
- tree types[NT_MAX];
- unsigned ix;
-
- types[NT_UINT_UINT_INT]
- = build_function_type_list (unsigned_type_node, unsigned_type_node,
- integer_type_node, NULL_TREE);
- types[NT_ULL_ULL_INT]
- = build_function_type_list (long_long_unsigned_type_node,
- long_long_unsigned_type_node,
- integer_type_node, NULL_TREE);
- types[NT_FLT_FLT_INT]
- = build_function_type_list (float_type_node, float_type_node,
- integer_type_node, NULL_TREE);
- types[NT_DBL_DBL_INT]
- = build_function_type_list (double_type_node, double_type_node,
- integer_type_node, NULL_TREE);
- types[NT_PTR_UINT_UINT_UINT_UINT]
- = build_function_type_list (ptr_type_node,
- unsigned_type_node, unsigned_type_node,
- unsigned_type_node, unsigned_type_node,
- NULL_TREE);
-
- for (ix = 0; ix != NVPTX_BUILTIN_MAX; ix++)
- nvptx_builtin_decls[ix]
- = add_builtin_function (builtins[ix].name, types[builtins[ix].type],
- ix, BUILT_IN_MD, NULL, NULL);
+#define DEF(ID, NAME, T) \
+ (nvptx_builtin_decls[NVPTX_BUILTIN_ ## ID] = \
+ add_builtin_function ("__builtin_nvptx_" NAME, \
+ build_function_type_list T, \
+ NVPTX_BUILTIN_ ## ID, BUILT_IN_MD, NULL, NULL))
+#define UINT unsigned_type_node
+#define LLUINT long_long_unsigned_type_node
+#define PTRVOID ptr_type_node
+
+ DEF (SHUFFLE, "shuffle", (UINT, UINT, UINT, UINT, NULL_TREE));
+ DEF (SHUFFLELL, "shufflell", (LLUINT, LLUINT, UINT, UINT, NULL_TREE));
+ DEF (WORKER_ADDR, "worker_addr",
+ (PTRVOID, UINT, UINT, UINT, UINT, NULL_TREE));
+ DEF (SWAP, "swap", (UINT, PTRVOID, UINT, NULL_TREE));
+ DEF (SWAPLL, "swapll", (LLUINT, PTRVOID, LLUINT, NULL_TREE));
+ DEF (CMP_SWAP, "cmp_swap", (UINT, PTRVOID, UINT, UINT, NULL_TREE));
+ DEF (CMP_SWAPLL, "cmp_swapll", (LLUINT, PTRVOID, LLUINT, LLUINT, NULL_TREE));
+
+#undef DEF
+#undef UINT
+#undef LLUINT
+#undef PTRVOID
}
/* Expand an expression EXP that calls a built-in function,
@@ -4297,9 +4315,25 @@ nvptx_expand_builtin (tree exp, rtx targ
int ignore)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
- const struct builtin_description *d = &builtins[DECL_FUNCTION_CODE (fndecl)];
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case NVPTX_BUILTIN_SHUFFLE:
+ case NVPTX_BUILTIN_SHUFFLELL:
+ return nvptx_expand_shuffle (exp, target, mode, ignore);
+
+ case NVPTX_BUILTIN_WORKER_ADDR:
+ return nvptx_expand_worker_addr (exp, target, mode, ignore);
+
+ case NVPTX_BUILTIN_SWAP:
+ case NVPTX_BUILTIN_SWAPLL:
+ return nvptx_expand_swap (exp, target, mode, ignore);
+
+ case NVPTX_BUILTIN_CMP_SWAP:
+ case NVPTX_BUILTIN_CMP_SWAPLL:
+ return nvptx_expand_cmp_swap (exp, target, mode, ignore);
- return d->expander (exp, target, mode, ignore);
+ default: gcc_unreachable ();
+ }
}
/* Define vector size for known hardware. */
@@ -4406,7 +4440,7 @@ static tree
nvptx_get_worker_red_addr (tree type, tree rid, tree lid)
{
machine_mode mode = TYPE_MODE (type);
- tree fndecl = nvptx_builtin_decl (NVPTX_BUILTIN_WORK_RED_ADDR, true);
+ tree fndecl = nvptx_builtin_decl (NVPTX_BUILTIN_WORKER_ADDR, true);
PROMOTE_MODE (mode, NULL, type);
tree size = build_int_cst (unsigned_type_node, GET_MODE_SIZE (mode));
@@ -4425,7 +4459,7 @@ nvptx_generate_vector_shuffle (location_
tree dest_var, tree var, unsigned shift,
gimple_seq *seq)
{
- unsigned fn = NVPTX_BUILTIN_SHUFFLE_DOWN;
+ unsigned fn = NVPTX_BUILTIN_SHUFFLE;
tree_code code = NOP_EXPR;
tree type = unsigned_type_node;
@@ -4444,16 +4478,17 @@ nvptx_generate_vector_shuffle (location_
/* FALLTHROUGH */
case DImode:
type = long_long_unsigned_type_node;
- fn = NVPTX_BUILTIN_SHUFFLE_DOWNLL;
+ fn = NVPTX_BUILTIN_SHUFFLELL;
break;
default:
gcc_unreachable ();
}
- tree call = build_call_expr_loc (loc, nvptx_builtin_decl (fn, true),
- 2, build1 (code, type, var),
- build_int_cst (unsigned_type_node, shift));
+ tree call = build_call_expr_loc
+ (loc, nvptx_builtin_decl (fn, true), 3, build1 (code, type, var),
+ build_int_cst (unsigned_type_node, shift),
+ build_int_cst (unsigned_type_node, SHUFFLE_DOWN));
call = fold_build1 (code, TREE_TYPE (dest_var), call);