nvptx.c (write_one_arg): Deal with prologue emission too.

* config/nvptx/nvptx.c (write_one_arg): Deal with prologue
	emission too. Change 'no_arg_types' to 'prototyped'.
	(write_fn_proto):  Use write_one_arg for stdarg, static chain &
	main.
	(nvptx_declare_function_name): Use write_one_arg for prologue copies.

From-SVN: r231267
This commit is contained in:
Nathan Sidwell 2015-12-04 14:02:27 +00:00 committed by Nathan Sidwell
parent 96d977a8f3
commit dc3d2aebdc
2 changed files with 91 additions and 98 deletions

View File

@ -1,3 +1,11 @@
2015-12-04 Nathan Sidwell <nathan@acm.org>
* config/nvptx/nvptx.c (write_one_arg): Deal with prologue
emission too. Change 'no_arg_types' to 'prototyped'.
(write_fn_proto): Use write_one_arg for stdarg, static chain &
main.
(nvptx_declare_function_name): Use write_one_arg for prologue copies.
2015-12-04 Richard Biener <rguenther@suse.de>
* tree-ssa-sccvn.c (sccvn_dom_walker): Add unreachable_dom

View File

@ -389,38 +389,67 @@ arg_promotion (machine_mode mode)
return mode;
}
/* Write the declaration of a function arg of TYPE to S. I is the index
of the argument, MODE its mode. NO_ARG_TYPES is true if this is for
a decl with zero TYPE_ARG_TYPES, i.e. an old-style C decl. */
/* Process function parameter TYPE, either emitting in a prototype
argument, or as a copy a in a function prologue. ARGNO is the
index of this argument in the PTX function. FOR_REG is negative,
if we're emitting the PTX prototype. It is zero if we're copying
to an argument register and it is greater than zero if we're
copying to a specific hard register. PROTOTYPED is true, if this
is a prototyped function, rather than an old-style C declaration.
The behaviour here must match the regular GCC function parameter
marshalling machinery. */
static int
write_one_arg (std::stringstream &s, const char *sep, int i,
tree type, machine_mode mode, bool no_arg_types)
write_one_arg (std::stringstream &s, int for_reg, int argno,
tree type, bool prototyped)
{
machine_mode mode = TYPE_MODE (type);
if (!PASS_IN_REG_P (mode, type))
mode = Pmode;
machine_mode split = maybe_split_mode (mode);
if (split != VOIDmode)
{
i = write_one_arg (s, sep, i, TREE_TYPE (type), split, false);
sep = ", ";
mode = split;
argno = write_one_arg (s, for_reg, argno,
TREE_TYPE (type), prototyped);
}
if (no_arg_types && !AGGREGATE_TYPE_P (type))
if (!prototyped && !AGGREGATE_TYPE_P (type))
{
if (mode == SFmode)
mode = DFmode;
mode = arg_promotion (mode);
}
s << sep;
s << ".param" << nvptx_ptx_type_from_mode (mode, false) << " %in_ar"
<< i << (mode == QImode || mode == HImode ? "[1]" : "");
if (mode == BLKmode)
s << "[" << int_size_in_bytes (type) << "]";
return i + 1;
if (for_reg < 0)
{
/* Writing PTX prototype. */
s << (argno ? ", " : " (");
s << ".param" << nvptx_ptx_type_from_mode (mode, false)
<< " %in_ar" << argno;
if (mode == QImode || mode == HImode)
s << "[1]";
}
else
{
mode = arg_promotion (mode);
s << "\t.reg" << nvptx_ptx_type_from_mode (mode, false) << " ";
if (for_reg)
s << reg_names[for_reg];
else
s << "%ar" << argno;
s << ";\n";
s << "\tld.param" << nvptx_ptx_type_from_mode (mode, false) << " ";
if (for_reg)
s << reg_names[for_reg];
else
s << "%ar" << argno;
s<< ", [%in_ar" << argno << "];\n";
}
return argno + 1;
}
/* Look for attributes in ATTRS that would indicate we must write a function
@ -507,16 +536,11 @@ write_fn_proto (std::stringstream &s, bool is_defn,
s << name;
const char *sep = " (";
int i = 0;
int argno = 0;
/* Emit argument list. */
if (return_in_mem)
{
s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_ar0";
sep = ", ";
i++;
}
argno = write_one_arg (s, -1, argno, ptr_type_node, true);
/* We get:
NULL in TYPE_ARG_TYPES, for old-style functions
@ -524,46 +548,34 @@ write_fn_proto (std::stringstream &s, bool is_defn,
declaration.
So we have to pick the best one we have. */
tree args = TYPE_ARG_TYPES (fntype);
bool null_type_args = !args;
if (null_type_args)
args = DECL_ARGUMENTS (decl);
bool prototyped = true;
if (!args)
{
args = DECL_ARGUMENTS (decl);
prototyped = false;
}
for (; args; args = TREE_CHAIN (args))
{
tree type = null_type_args ? TREE_TYPE (args) : TREE_VALUE (args);
machine_mode mode = TYPE_MODE (type);
tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args);
if (mode == VOIDmode)
break;
i = write_one_arg (s, sep, i, type, mode, null_type_args);
sep = ", ";
if (type != void_type_node)
argno = write_one_arg (s, -1, argno, type, prototyped);
}
if (stdarg_p (fntype))
{
s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_argp";
i++;
sep = ", ";
}
argno = write_one_arg (s, -1, argno, ptr_type_node, true);
if (DECL_STATIC_CHAIN (decl))
argno = write_one_arg (s, -1, argno, ptr_type_node, true);
if (!argno && strcmp (name, "main") == 0)
{
s << sep << ".reg.u" << GET_MODE_BITSIZE (Pmode)
<< reg_names [STATIC_CHAIN_REGNUM];
i++;
sep = ", ";
argno = write_one_arg (s, -1, argno, integer_type_node, true);
argno = write_one_arg (s, -1, argno, ptr_type_node, true);
}
if (!i && strcmp (name, "main") == 0)
{
s << sep
<< ".param.u32 %argc, .param.u" << GET_MODE_BITSIZE (Pmode)
<< " %argv";
i++;
sep = ", ";
}
if (i)
if (argno)
s << ")";
s << (is_defn ? "\n" : ";\n");
@ -705,64 +717,44 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl)
{
tree fntype = TREE_TYPE (decl);
tree result_type = TREE_TYPE (fntype);
int argno = 0;
int argno = 0;
/* We construct the initial part of the function into a string
stream, in order to share the prototype writing code. */
std::stringstream s;
write_fn_proto (s, true, name, decl);
fprintf (file, "%s", s.str().c_str());
fprintf (file, "{\n");
s << "{\n";
bool return_in_mem = (TYPE_MODE (result_type) != VOIDmode
&& !RETURN_IN_REG_P (TYPE_MODE (result_type)));
if (return_in_mem)
{
fprintf (file, "\t.reg.u%d %%ar%d;\n", GET_MODE_BITSIZE (Pmode), argno);
fprintf (file, "\tld.param.u%d %%ar%d, [%%in_ar%d];\n",
GET_MODE_BITSIZE (Pmode), argno, argno);
argno++;
}
argno = write_one_arg (s, 0, argno, ptr_type_node, true);
/* Declare and initialize incoming arguments. */
tree args = DECL_ARGUMENTS (decl);
bool prototyped = false;
if (TYPE_ARG_TYPES (fntype))
tree args = TYPE_ARG_TYPES (fntype);
bool prototyped = true;
if (!args)
{
args = TYPE_ARG_TYPES (fntype);
prototyped = true;
args = DECL_ARGUMENTS (decl);
prototyped = false;
}
for (; args != NULL_TREE; args = TREE_CHAIN (args))
{
tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args);
machine_mode mode = TYPE_MODE (type);
int count = 1;
if (mode == VOIDmode)
break;
if (!PASS_IN_REG_P (mode, type))
mode = Pmode;
machine_mode split = maybe_split_mode (mode);
if (split != VOIDmode)
{
count = 2;
mode = split;
}
else if (!prototyped && !AGGREGATE_TYPE_P (type) && mode == SFmode)
mode = DFmode;
mode = arg_promotion (mode);
while (count--)
{
fprintf (file, "\t.reg%s %%ar%d;\n",
nvptx_ptx_type_from_mode (mode, false), argno);
fprintf (file, "\tld.param%s %%ar%d, [%%in_ar%d];\n",
nvptx_ptx_type_from_mode (mode, false), argno, argno);
argno++;
}
if (type != void_type_node)
argno = write_one_arg (s, 0, argno, type, prototyped);
}
if (stdarg_p (fntype))
argno = write_one_arg (s, ARG_POINTER_REGNUM, argno, ptr_type_node, true);
if (DECL_STATIC_CHAIN (decl))
argno = write_one_arg (s, STATIC_CHAIN_REGNUM, argno, ptr_type_node, true);
fprintf (file, "%s", s.str().c_str());
/* C++11 ABI causes us to return a reference to the passed in
pointer for return_in_mem. */
if (cfun->machine->ret_reg_mode != VOIDmode)
@ -773,16 +765,9 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl)
nvptx_ptx_type_from_mode (mode, false));
}
if (stdarg_p (fntype))
{
fprintf (file, "\t.reg.u%d %%argp;\n", GET_MODE_BITSIZE (Pmode));
fprintf (file, "\tld.param.u%d %%argp, [%%in_argp];\n",
GET_MODE_BITSIZE (Pmode));
}
fprintf (file, "\t.reg.u%d %s;\n", GET_MODE_BITSIZE (Pmode),
reg_names[OUTGOING_STATIC_CHAIN_REGNUM]);
/* Declare the pseudos we have as ptx registers. */
int maxregs = max_reg_num ();
for (int i = LAST_VIRTUAL_REGISTER + 1; i < maxregs; i++)