Commit b699adcc by Nathan Sidwell Committed by Nathan Sidwell

nvptx.c (nvptx_name_replacement): Move earlier.

	* config/nvptx/nvptx.c (nvptx_name_replacement): Move earlier.
	(write_one_arg): Reorder parms, add 'sep' param.
	(nvptx_write_function_decl): Rename to ...
	(write_fn_proto): ... here.  Do name replacement. Emit linaer
	comment marker. Deal with both decls and defns. Simplify argument
	formatting.
	(write_function_decl_and_comment): Delete.
	(write_func_decl_from_insn): Rename to ...
	(write_fn_proto_from_insn): ... here.  Don't do name replacement.
	(nvptx_record_fndecl): Call write_fn_proto.
	(nvptx_record_libfunc): Call write_fn_proto_from_insn.
	(nvptx_declare_function_name): Adjust for write_fn_proto changes.
	(nvotx_output_call_insn): Call write_fn_prot_from_insn.

From-SVN: r231073
parent 0ef5fbc1
2015-11-30 Nathan Sidwell <nathan@acm.org>
* config/nvptx/nvptx.c (nvptx_name_replacement): Move earlier.
(write_one_arg): Reorder parms, add 'sep' param.
(nvptx_write_function_decl): Rename to ...
(write_fn_proto): ... here. Do name replacement. Emit linaer
comment marker. Deal with both decls and defns. Simplify argument
formatting.
(write_function_decl_and_comment): Delete.
(write_func_decl_from_insn): Rename to ...
(write_fn_proto_from_insn): ... here. Don't do name replacement.
(nvptx_record_fndecl): Call write_fn_proto.
(nvptx_record_libfunc): Call write_fn_proto_from_insn.
(nvptx_declare_function_name): Adjust for write_fn_proto changes.
(nvotx_output_call_insn): Call write_fn_prot_from_insn.
2015-11-30 Kirill Yukhin <kirill.yukhin@intel.com> 2015-11-30 Kirill Yukhin <kirill.yukhin@intel.com>
* config/i386/i386.md (define_mode_iterator SWI1248_AVX512BW): New. * config/i386/i386.md (define_mode_iterator SWI1248_AVX512BW): New.
...@@ -224,6 +224,24 @@ nvptx_addr_space_from_sym (rtx sym) ...@@ -224,6 +224,24 @@ nvptx_addr_space_from_sym (rtx sym)
return ADDR_SPACE_GLOBAL; return ADDR_SPACE_GLOBAL;
} }
/* Check NAME for special function names and redirect them by returning a
replacement. This applies to malloc, free and realloc, for which we
want to use libgcc wrappers, and call, which triggers a bug in ptxas. */
static const char *
nvptx_name_replacement (const char *name)
{
if (strcmp (name, "call") == 0)
return "__nvptx_call";
if (strcmp (name, "malloc") == 0)
return "__nvptx_malloc";
if (strcmp (name, "free") == 0)
return "__nvptx_free";
if (strcmp (name, "realloc") == 0)
return "__nvptx_realloc";
return name;
}
/* If MODE should be treated as two registers of an inner mode, return /* If MODE should be treated as two registers of an inner mode, return
that inner mode. Otherwise return VOIDmode. */ that inner mode. Otherwise return VOIDmode. */
...@@ -309,8 +327,8 @@ arg_promotion (machine_mode mode) ...@@ -309,8 +327,8 @@ arg_promotion (machine_mode mode)
a decl with zero TYPE_ARG_TYPES, i.e. an old-style C decl. */ a decl with zero TYPE_ARG_TYPES, i.e. an old-style C decl. */
static int static int
write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode, write_one_arg (std::stringstream &s, const char *sep, int i,
bool no_arg_types) tree type, machine_mode mode, bool no_arg_types)
{ {
if (!PASS_IN_REG_P (mode, type)) if (!PASS_IN_REG_P (mode, type))
mode = Pmode; mode = Pmode;
...@@ -318,9 +336,9 @@ write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode, ...@@ -318,9 +336,9 @@ write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode,
machine_mode split = maybe_split_mode (mode); machine_mode split = maybe_split_mode (mode);
if (split != VOIDmode) if (split != VOIDmode)
{ {
i = write_one_arg (s, NULL_TREE, i, split, false); i = write_one_arg (s, sep, i, TREE_TYPE (type), split, false);
i = write_one_arg (s, NULL_TREE, i, split, false); sep = ", ";
return i; mode = split;
} }
if (no_arg_types && !AGGREGATE_TYPE_P (type)) if (no_arg_types && !AGGREGATE_TYPE_P (type))
...@@ -330,8 +348,7 @@ write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode, ...@@ -330,8 +348,7 @@ write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode,
mode = arg_promotion (mode); mode = arg_promotion (mode);
} }
if (i) s << sep;
s << ", ";
s << ".param" << nvptx_ptx_type_from_mode (mode, false) << " %in_ar" s << ".param" << nvptx_ptx_type_from_mode (mode, false) << " %in_ar"
<< i << (mode == QImode || mode == HImode ? "[1]" : ""); << i << (mode == QImode || mode == HImode ? "[1]" : "");
if (mode == BLKmode) if (mode == BLKmode)
...@@ -349,41 +366,41 @@ write_as_kernel (tree attrs) ...@@ -349,41 +366,41 @@ write_as_kernel (tree attrs)
|| lookup_attribute ("omp target entrypoint", attrs) != NULL_TREE); || lookup_attribute ("omp target entrypoint", attrs) != NULL_TREE);
} }
/* Write a function decl for DECL to S, where NAME is the name to be used. /* Write a .func or .kernel declaration or definition along with
This includes ptx .visible or .extern specifiers, .func or .kernel, and a helper comment for use by ld. S is the stream to write to, DECL
argument and return types. */ the decl for the function with name NAME. For definitions, emit
a declaration too. */
static void static const char *
nvptx_write_function_decl (std::stringstream &s, const char *name, const_tree decl) write_fn_proto (std::stringstream &s, bool is_defn,
const char *name, const_tree decl)
{ {
tree fntype = TREE_TYPE (decl); if (is_defn)
tree result_type = TREE_TYPE (fntype); /* Emit a declaration. The PTX assembler gets upset without it. */
tree args = TYPE_ARG_TYPES (fntype); name = write_fn_proto (s, false, name, decl);
tree attrs = DECL_ATTRIBUTES (decl); else
bool kernel = write_as_kernel (attrs);
bool is_main = strcmp (name, "main") == 0;
bool args_from_decl = false;
/* We get:
NULL in TYPE_ARG_TYPES, for old-style functions
NULL in DECL_ARGUMENTS, for builtin functions without another
declaration.
So we have to pick the best one we have. */
if (args == 0)
{ {
args = DECL_ARGUMENTS (decl); /* Avoid repeating the name replacement. */
args_from_decl = true; name = nvptx_name_replacement (name);
if (name[0] == '*')
name++;
} }
/* Emit the linker marker. */
s << "\n// BEGIN";
if (TREE_PUBLIC (decl))
s << " GLOBAL";
s << " FUNCTION " << (is_defn ? "DEF" : "DECL") << ": " << name << "\n";
/* PTX declaration. */
if (DECL_EXTERNAL (decl)) if (DECL_EXTERNAL (decl))
s << ".extern "; s << ".extern ";
else if (TREE_PUBLIC (decl)) else if (TREE_PUBLIC (decl))
s << (DECL_WEAK (decl) ? ".weak " : ".visible "); s << (DECL_WEAK (decl) ? ".weak " : ".visible ");
s << (write_as_kernel (DECL_ATTRIBUTES (decl)) ? ".entry " : ".func ");
if (kernel) tree fntype = TREE_TYPE (decl);
s << ".entry "; tree result_type = TREE_TYPE (fntype);
else
s << ".func ";
/* Declare the result. */ /* Declare the result. */
bool return_in_mem = false; bool return_in_mem = false;
...@@ -396,78 +413,74 @@ nvptx_write_function_decl (std::stringstream &s, const char *name, const_tree de ...@@ -396,78 +413,74 @@ nvptx_write_function_decl (std::stringstream &s, const char *name, const_tree de
{ {
mode = arg_promotion (mode); mode = arg_promotion (mode);
s << "(.param" << nvptx_ptx_type_from_mode (mode, false) s << "(.param" << nvptx_ptx_type_from_mode (mode, false)
<< " %out_retval)"; << " %out_retval) ";
} }
} }
if (name[0] == '*') s << name;
s << (name + 1);
else const char *sep = " (";
s << name; int i = 0;
/* Declare argument types. */ /* Emit argument list. */
if ((args != NULL_TREE if (return_in_mem)
&& !(TREE_CODE (args) == TREE_LIST
&& TREE_VALUE (args) == void_type_node))
|| is_main
|| return_in_mem
|| DECL_STATIC_CHAIN (decl))
{ {
s << "("; s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_ar0";
int i = 0; sep = ", ";
i++;
}
if (return_in_mem) /* We get:
{ NULL in TYPE_ARG_TYPES, for old-style functions
s << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_ar0"; NULL in DECL_ARGUMENTS, for builtin functions without another
i++; declaration.
} So we have to pick the best one we have. */
while (args != NULL_TREE) tree args = TYPE_ARG_TYPES (fntype);
{ bool null_type_args = !args;
tree type = args_from_decl ? TREE_TYPE (args) : TREE_VALUE (args); if (null_type_args)
machine_mode mode = TYPE_MODE (type); args = DECL_ARGUMENTS (decl);
if (mode != VOIDmode) for (; args; args = TREE_CHAIN (args))
i = write_one_arg (s, type, i, mode, {
TYPE_ARG_TYPES (fntype) == 0); tree type = null_type_args ? TREE_TYPE (args) : TREE_VALUE (args);
args = TREE_CHAIN (args); machine_mode mode = TYPE_MODE (type);
}
if (stdarg_p (fntype)) if (mode == VOIDmode)
{ break;
gcc_assert (i > 0); i = write_one_arg (s, sep, i, type, mode, null_type_args);
s << ", .param.u" << GET_MODE_BITSIZE (Pmode) << " %in_argp"; sep = ", ";
}
if (DECL_STATIC_CHAIN (decl))
{
if (i)
s << ", ";
s << ".reg.u" << GET_MODE_BITSIZE (Pmode)
<< reg_names [STATIC_CHAIN_REGNUM];
}
if (!i && is_main)
s << ".param.u32 %argc, .param.u" << GET_MODE_BITSIZE (Pmode)
<< " %argv";
s << ")";
} }
}
/* Write a .func or .kernel declaration (not a definition) along with if (stdarg_p (fntype))
a helper comment for use by ld. S is the stream to write to, DECL {
the decl for the function with name NAME. */ s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_argp";
i++;
sep = ", ";
}
static void if (DECL_STATIC_CHAIN (decl))
write_function_decl_and_comment (std::stringstream &s, const char *name, const_tree decl) {
{ s << sep << ".reg.u" << GET_MODE_BITSIZE (Pmode)
s << "\n// BEGIN"; << reg_names [STATIC_CHAIN_REGNUM];
if (TREE_PUBLIC (decl)) i++;
s << " GLOBAL"; sep = ", ";
s << " FUNCTION DECL: "; }
if (name[0] == '*')
s << (name + 1); if (!i && strcmp (name, "main") == 0)
else {
s << name; s << sep
s << "\n"; << ".param.u32 %argc, .param.u" << GET_MODE_BITSIZE (Pmode)
nvptx_write_function_decl (s, name, decl); << " %argv";
s << ";\n"; i++;
sep = ", ";
}
if (i)
s << ")";
s << (is_defn ? "\n" : ";\n");
return name;
} }
/* Construct a function declaration from a call insn. This can be /* Construct a function declaration from a call insn. This can be
...@@ -476,8 +489,8 @@ write_function_decl_and_comment (std::stringstream &s, const char *name, const_t ...@@ -476,8 +489,8 @@ write_function_decl_and_comment (std::stringstream &s, const char *name, const_t
generated by emit_library_call for which no decl exists. */ generated by emit_library_call for which no decl exists. */
static void static void
write_func_decl_from_insn (std::stringstream &s, const char *name, write_fn_proto_from_insn (std::stringstream &s, const char *name,
rtx result, rtx pat) rtx result, rtx pat)
{ {
if (!name) if (!name)
{ {
...@@ -486,6 +499,7 @@ write_func_decl_from_insn (std::stringstream &s, const char *name, ...@@ -486,6 +499,7 @@ write_func_decl_from_insn (std::stringstream &s, const char *name,
} }
else else
{ {
name = nvptx_name_replacement (name);
s << "\n// BEGIN GLOBAL FUNCTION DECL: " << name << "\n"; s << "\n// BEGIN GLOBAL FUNCTION DECL: " << name << "\n";
s << "\t.extern .func "; s << "\t.extern .func ";
} }
...@@ -519,24 +533,6 @@ write_func_decl_from_insn (std::stringstream &s, const char *name, ...@@ -519,24 +533,6 @@ write_func_decl_from_insn (std::stringstream &s, const char *name,
s << ";\n"; s << ";\n";
} }
/* Check NAME for special function names and redirect them by returning a
replacement. This applies to malloc, free and realloc, for which we
want to use libgcc wrappers, and call, which triggers a bug in ptxas. */
static const char *
nvptx_name_replacement (const char *name)
{
if (strcmp (name, "call") == 0)
return "__nvptx_call";
if (strcmp (name, "malloc") == 0)
return "__nvptx_malloc";
if (strcmp (name, "free") == 0)
return "__nvptx_free";
if (strcmp (name, "realloc") == 0)
return "__nvptx_realloc";
return name;
}
/* DECL is an external FUNCTION_DECL, make sure its in the fndecl hash /* DECL is an external FUNCTION_DECL, make sure its in the fndecl hash
table and and write a ptx prototype. These are emitted at end of table and and write a ptx prototype. These are emitted at end of
compilation. */ compilation. */
...@@ -549,8 +545,7 @@ nvptx_record_fndecl (tree decl) ...@@ -549,8 +545,7 @@ nvptx_record_fndecl (tree decl)
{ {
*slot = decl; *slot = decl;
const char *name = get_fnname_from_decl (decl); const char *name = get_fnname_from_decl (decl);
name = nvptx_name_replacement (name); write_fn_proto (func_decls, false, name, decl);
write_function_decl_and_comment (func_decls, name, decl);
} }
} }
...@@ -567,8 +562,7 @@ nvptx_record_libfunc (rtx callee, rtx retval, rtx pat) ...@@ -567,8 +562,7 @@ nvptx_record_libfunc (rtx callee, rtx retval, rtx pat)
*slot = callee; *slot = callee;
const char *name = XSTR (callee, 0); const char *name = XSTR (callee, 0);
name = nvptx_name_replacement (name); write_fn_proto_from_insn (func_decls, name, retval, pat);
write_func_decl_from_insn (func_decls, name, retval, pat);
} }
} }
...@@ -625,29 +619,13 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) ...@@ -625,29 +619,13 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl)
tree result_type = TREE_TYPE (fntype); tree result_type = TREE_TYPE (fntype);
int argno = 0; int argno = 0;
name = nvptx_name_replacement (name);
std::stringstream s; std::stringstream s;
write_function_decl_and_comment (s, name, decl); write_fn_proto (s, true, name, decl);
s << "// BEGIN";
if (TREE_PUBLIC (decl))
s << " GLOBAL";
s << " FUNCTION DEF: ";
if (name[0] == '*')
s << (name + 1);
else
s << name;
s << "\n";
nvptx_write_function_decl (s, name, decl);
fprintf (file, "%s", s.str().c_str()); fprintf (file, "%s", s.str().c_str());
fprintf (file, "{\n");
bool return_in_mem = (TYPE_MODE (result_type) != VOIDmode bool return_in_mem = (TYPE_MODE (result_type) != VOIDmode
&& !RETURN_IN_REG_P (TYPE_MODE (result_type))); && !RETURN_IN_REG_P (TYPE_MODE (result_type)));
fprintf (file, "\n{\n");
if (return_in_mem) if (return_in_mem)
{ {
fprintf (file, "\t.reg.u%d %%ar%d;\n", GET_MODE_BITSIZE (Pmode), argno); fprintf (file, "\t.reg.u%d %%ar%d;\n", GET_MODE_BITSIZE (Pmode), argno);
...@@ -1794,7 +1772,7 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) ...@@ -1794,7 +1772,7 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee)
labelno++; labelno++;
ASM_OUTPUT_LABEL (asm_out_file, buf); ASM_OUTPUT_LABEL (asm_out_file, buf);
std::stringstream s; std::stringstream s;
write_func_decl_from_insn (s, NULL, result, pat); write_fn_proto_from_insn (s, NULL, result, pat);
fputs (s.str().c_str(), asm_out_file); fputs (s.str().c_str(), asm_out_file);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment