summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-14 19:26:49 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-14 19:26:49 +0000
commitdf931be43215b210a0a8ba6f8ea3fa70d3e5ec8f (patch)
tree0db4672849e10a27a980f0dffce1ba6e0e14c9cd /gcc/config
parent7ca909c695cf94388d30d13e46d829ae0bcea84d (diff)
downloadgcc-df931be43215b210a0a8ba6f8ea3fa70d3e5ec8f.tar.gz
gcc/
* config/nvptx/nvptx.h (PARM_BOUNDARY): Set to 32. * config/nvptx/nvptx.c (PASS_IN_REG_P, RETURN_IN_REG_P): Delete. (pass_in_memory, promote_arg, promote_return): New. (nvptx_function_arg_boundary): Delete. (nvptx_function_value): Use promote_return. (nvptx_pass_by_reference): Use pass_in_memory. (nvptx_return_in_memory): Use pass_in_memory. (nvptx_promote_function_mode): Use promote_arg. (write_arg): Adjust arg splitting logic. (write_return): Check and clear ret_reg_mode, if needed. (write_fn_proto, nvptx_declare_function_name): Adust write_return calls. (TARGET_RUNCTION_ARG_BOUNDARY, TARGET_FUNCTION_ARG_ROUND_BOUNDARY): Don't override. gcc/testsuite/ * g++.dg/abi/nvptx-nrv1.C: New. * g++.dg/abi/nvptx-ptrmem1.C: New. * gcc.target/nvptx/abi-complex-arg.c: New. * gcc.target/nvptx/abi-complex-ret.c: New. * gcc.target/nvptx/abi-enum-arg.c: New. * gcc.target/nvptx/abi-enum-ret.c: New. * gcc.target/nvptx/abi-knr-arg.c: New. * gcc.target/nvptx/abi-knr-ret.c: New. * gcc.target/nvptx/abi-scalar-arg.c: New. * gcc.target/nvptx/abi-scalar-ret.c: New. * gcc.target/nvptx/abi-struct-arg.c: New. * gcc.target/nvptx/abi-struct-ret.c: New. * gcc.target/nvptx/abi-vararg-1.c: New. * gcc.target/nvptx/abi-vararg-2.c: New. * gcc.target/nvptx/abi-vect-arg.c: New. * gcc.target/nvptx/abi-vect-ret.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231628 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/nvptx/nvptx.c230
-rw-r--r--gcc/config/nvptx/nvptx.h3
2 files changed, 120 insertions, 113 deletions
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 44b0c302d6d..bb4c384a5d2 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -365,18 +365,6 @@ nvptx_emit_joining (unsigned mask, bool is_call)
}
}
-#define PASS_IN_REG_P(MODE, TYPE) \
- ((GET_MODE_CLASS (MODE) == MODE_INT \
- || GET_MODE_CLASS (MODE) == MODE_FLOAT \
- || ((GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
- || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
- && !AGGREGATE_TYPE_P (TYPE))) \
- && (MODE) != TImode)
-
-#define RETURN_IN_REG_P(MODE) \
- ((GET_MODE_CLASS (MODE) == MODE_INT \
- || GET_MODE_CLASS (MODE) == MODE_FLOAT) \
- && GET_MODE_SIZE (MODE) <= 8)
/* Perform a mode promotion for a function argument with MODE. Return
the promoted mode. */
@@ -389,6 +377,61 @@ arg_promotion (machine_mode mode)
return mode;
}
+/* Determine whether MODE and TYPE (possibly NULL) should be passed or
+ returned in memory. Integer and floating types supported by the
+ machine are passed in registers, everything else is passed in
+ memory. Complex types are split. */
+
+static bool
+pass_in_memory (machine_mode mode, const_tree type, bool for_return)
+{
+ if (type)
+ {
+ if (AGGREGATE_TYPE_P (type))
+ return true;
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ return true;
+ }
+
+ if (!for_return && COMPLEX_MODE_P (mode))
+ /* Complex types are passed as two underlying args. */
+ mode = GET_MODE_INNER (mode);
+
+ if (GET_MODE_CLASS (mode) != MODE_INT
+ && GET_MODE_CLASS (mode) != MODE_FLOAT)
+ return true;
+
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ return true;
+
+ return false;
+}
+
+/* A non-memory argument of mode MODE is being passed, determine the mode it
+ should be promoted to. This is also used for determining return
+ type promotion. */
+
+static machine_mode
+promote_arg (machine_mode mode, bool prototyped)
+{
+ if (!prototyped && mode == SFmode)
+ /* K&R float promotion for unprototyped functions. */
+ mode = DFmode;
+ else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
+ mode = SImode;
+
+ return mode;
+}
+
+/* A non-memory return type of MODE is being returned. Determine the
+ mode it should be promoted to. */
+
+static machine_mode
+promote_return (machine_mode mode)
+{
+ return promote_arg (mode, true);
+}
+
/* Implement TARGET_FUNCTION_ARG. */
static rtx
@@ -450,40 +493,6 @@ nvptx_strict_argument_naming (cumulative_args_t cum_v)
return cum->fntype == NULL_TREE || stdarg_p (cum->fntype);
}
-/* Implement TARGET_FUNCTION_ARG_BOUNDARY. */
-
-static unsigned int
-nvptx_function_arg_boundary (machine_mode mode, const_tree type)
-{
- unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode);
-
- if (boundary > UNITS_PER_WORD * BITS_PER_UNIT)
- boundary = UNITS_PER_WORD * BITS_PER_UNIT;
- else if (mode == BLKmode)
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
-
- if (size > UNITS_PER_WORD)
- boundary = UNITS_PER_WORD;
- else
- {
- /* Keep rounding up until only 1 bit set. */
- unsigned lsb = (unsigned) size;
-
- boundary = 0;
- do
- {
- boundary += lsb;
- lsb = boundary & -boundary;
- }
- while (boundary != lsb);
- }
- boundary *= BITS_PER_UNIT;
- }
-
- return boundary;
-}
-
/* Implement TARGET_LIBCALL_VALUE. */
static rtx
@@ -501,13 +510,11 @@ nvptx_libcall_value (machine_mode mode, const_rtx)
where function FUNC returns or receives a value of data type TYPE. */
static rtx
-nvptx_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED,
+nvptx_function_value (const_tree type, const_tree ARG_UNUSED (func),
bool outgoing)
{
- int unsignedp = TYPE_UNSIGNED (type);
- machine_mode orig_mode = TYPE_MODE (type);
- machine_mode mode = promote_function_mode (type, orig_mode,
- &unsignedp, NULL_TREE, 1);
+ machine_mode mode = promote_return (TYPE_MODE (type));
+
if (outgoing)
return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM);
@@ -529,7 +536,7 @@ static bool
nvptx_pass_by_reference (cumulative_args_t ARG_UNUSED (cum), machine_mode mode,
const_tree type, bool ARG_UNUSED (named))
{
- return !PASS_IN_REG_P (mode, type);
+ return pass_in_memory (mode, type, false);
}
/* Implement TARGET_RETURN_IN_MEMORY. */
@@ -537,35 +544,17 @@ nvptx_pass_by_reference (cumulative_args_t ARG_UNUSED (cum), machine_mode mode,
static bool
nvptx_return_in_memory (const_tree type, const_tree)
{
- machine_mode mode = TYPE_MODE (type);
- if (!RETURN_IN_REG_P (mode))
- return true;
- return false;
+ return pass_in_memory (TYPE_MODE (type), type, true);
}
/* Implement TARGET_PROMOTE_FUNCTION_MODE. */
static machine_mode
nvptx_promote_function_mode (const_tree type, machine_mode mode,
- int *punsignedp,
+ int *ARG_UNUSED (punsignedp),
const_tree funtype, int for_return)
{
- if (type == NULL_TREE)
- return mode;
- if (for_return)
- return promote_mode (type, mode, punsignedp);
- /* For K&R-style functions, try to match the language promotion rules to
- minimize type mismatches at assembly time. */
- if (TYPE_ARG_TYPES (funtype) == NULL_TREE
- && type != NULL_TREE
- && !AGGREGATE_TYPE_P (type))
- {
- if (mode == SFmode)
- mode = DFmode;
- mode = arg_promotion (mode);
- }
-
- return mode;
+ return promote_arg (mode, for_return || !type || TYPE_ARG_TYPES (funtype));
}
/* Implement TARGET_STATIC_CHAIN. */
@@ -576,7 +565,6 @@ nvptx_static_chain (const_tree fndecl, bool incoming_p)
if (!DECL_STATIC_CHAIN (fndecl))
return NULL;
-
return gen_rtx_REG (Pmode, (incoming_p ? STATIC_CHAIN_REGNUM
: OUTGOING_STATIC_CHAIN_REGNUM));
}
@@ -620,8 +608,9 @@ write_one_arg (std::stringstream &s, int for_reg, int argno, machine_mode mode)
}
/* Process function parameter TYPE to emit one or more PTX
- arguments. PROTOTYPED is true, if this is a prototyped function,
- rather than an old-style C declaration.
+ arguments. S, FOR_REG and ARGNO as for write_one_arg. PROTOTYPED
+ is true, if this is a prototyped function, rather than an old-style
+ C declaration. Returns the next argument number to use.
The promotion behaviour here must match the regular GCC function
parameter marshalling machinery. */
@@ -635,50 +624,71 @@ write_arg (std::stringstream &s, int for_reg, int argno,
if (mode == VOIDmode)
return argno;
- if (!PASS_IN_REG_P (mode, type))
+ if (pass_in_memory (mode, type, false))
mode = Pmode;
+ else
+ {
+ bool split = TREE_CODE (type) == COMPLEX_TYPE;
- machine_mode split = maybe_split_mode (mode);
- if (split != VOIDmode)
- mode = split;
+ if (split)
+ {
+ /* Complex types are sent as two separate args. */
+ type = TREE_TYPE (type);
+ mode = TYPE_MODE (type);
+ prototyped = true;
+ }
- if (!prototyped && !AGGREGATE_TYPE_P (type))
- {
- if (mode == SFmode)
- mode = DFmode;
- mode = arg_promotion (mode);
+ mode = promote_arg (mode, prototyped);
+ if (split)
+ argno = write_one_arg (s, for_reg, argno, mode);
}
- else if (for_reg >= 0)
- mode = arg_promotion (mode);
- if (split != VOIDmode)
- argno = write_one_arg (s, for_reg, argno, mode);
return write_one_arg (s, for_reg, argno, mode);
}
+/* Process a function return TYPE to emit a PTX return as a prototype
+ or function prologue declaration. DECL_RESULT is the decl result
+ of the function and needed for determining named result
+ behaviour. Returns true if return is via an additional pointer
+ parameter. The promotion behaviour here must match the regular GCC
+ function return mashalling. */
+
static bool
-write_return (std::stringstream &s, bool for_proto, tree type,
- machine_mode ret_mode)
+write_return (std::stringstream &s, bool for_proto, tree type)
{
machine_mode mode = TYPE_MODE (type);
- bool return_in_mem = mode != VOIDmode && !RETURN_IN_REG_P (mode);
- mode = arg_promotion (mode);
- if (for_proto)
+ if (mode == VOIDmode)
+ return false;
+
+ bool return_in_mem = pass_in_memory (mode, type, true);
+
+ if (return_in_mem)
{
- if (!return_in_mem && mode != VOIDmode)
- s << "(.param" << nvptx_ptx_type_from_mode (mode, false)
- << " %out_retval) ";
+ if (for_proto)
+ return return_in_mem;
+
+ /* Named return values can cause us to return a pointer as well
+ as expect an argument for the return location. This is
+ optimization-level specific, so no caller can make use of
+ this data, but more importantly for us, we must ensure it
+ doesn't change the PTX prototype. */
+ mode = (machine_mode) cfun->machine->ret_reg_mode;
+ if (mode == VOIDmode)
+ return return_in_mem;
+
+ /* Clear ret_reg_mode to inhibit copy of retval to non-existent
+ retval parameter. */
+ cfun->machine->ret_reg_mode = VOIDmode;
}
else
- {
- /* Prologue. C++11 ABI causes us to return a reference to the
- passed in pointer for return_in_mem. */
- ret_mode = arg_promotion (ret_mode);
- if (ret_mode != VOIDmode)
- s << "\t.reg" << nvptx_ptx_type_from_mode (ret_mode, false)
- << " %retval;\n";
- }
+ mode = promote_return (mode);
+
+ const char *ptx_type = nvptx_ptx_type_from_mode (mode, false);
+ if (for_proto)
+ s << "(.param" << ptx_type << " %out_retval) ";
+ else
+ s << "\t.reg" << ptx_type << " %retval;\n";
return return_in_mem;
}
@@ -751,7 +761,7 @@ write_fn_proto (std::stringstream &s, bool is_defn,
tree result_type = TREE_TYPE (fntype);
/* Declare the result. */
- bool return_in_mem = write_return (s, true, result_type, VOIDmode);
+ bool return_in_mem = write_return (s, true, result_type);
s << name;
@@ -943,8 +953,7 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl)
write_fn_proto (s, true, name, decl);
s << "{\n";
- bool return_in_mem = write_return (s, false, result_type,
- (machine_mode)cfun->machine->ret_reg_mode);
+ bool return_in_mem = write_return (s, false, result_type);
if (return_in_mem)
argno = write_arg (s, 0, argno, ptr_type_node, true);
@@ -1203,6 +1212,7 @@ nvptx_expand_call (rtx retval, rtx address)
if (tmp_retval != retval)
emit_move_insn (retval, tmp_retval);
}
+
/* Emit a comparison COMPARE, and return the new test to be used in the
jump. */
@@ -4840,10 +4850,6 @@ nvptx_goacc_reduction (gcall *call)
#define TARGET_FUNCTION_INCOMING_ARG nvptx_function_incoming_arg
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE nvptx_function_arg_advance
-#undef TARGET_FUNCTION_ARG_BOUNDARY
-#define TARGET_FUNCTION_ARG_BOUNDARY nvptx_function_arg_boundary
-#undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY
-#define TARGET_FUNCTION_ARG_ROUND_BOUNDARY nvptx_function_arg_boundary
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE nvptx_pass_by_reference
#undef TARGET_FUNCTION_VALUE_REGNO_P
diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index 33b2c72d9d9..ed0f28e0dd8 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -46,7 +46,8 @@
/* Chosen such that we won't have to deal with multi-word subregs. */
#define UNITS_PER_WORD 8
-#define PARM_BOUNDARY 8
+/* Alignments in bits. */
+#define PARM_BOUNDARY 32
#define STACK_BOUNDARY 64
#define FUNCTION_BOUNDARY 32
#define BIGGEST_ALIGNMENT 64