alpha.c (function_arg): Don't pass small aggregates in floating point registers.

* config/alpha/alpha.c (function_arg): Don't pass small aggregates
        in floating point registers.  Validate that we don't receive complex
        values here.  Use #elif.
        (return_in_memory, function_value): New.
        (alpha_va_arg): Handle complex values as two arguments.
        * config/alpha/alpha.h (RETURN_IN_MEMORY): Use return_in_memory.
        (FUNCTION_VALUE, LIBCALL_VALUE): Use function_value.
        (SPLIT_COMPLEX_ARGS): New.
        * config/alpha/alpha-protos.h: Update.

From-SVN: r68591
This commit is contained in:
Richard Henderson 2003-06-27 10:52:03 -07:00
parent 75d75435b6
commit 7e4fb06a51
4 changed files with 174 additions and 33 deletions

View File

@ -1,4 +1,16 @@
2003-06-13 Ulrich Weigand <uweigand@de.ibm.com>
2003-06-27 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (function_arg): Don't pass small aggregates
in floating point registers. Validate that we don't receive complex
values here. Use #elif.
(return_in_memory, function_value): New.
(alpha_va_arg): Handle complex values as two arguments.
* config/alpha/alpha.h (RETURN_IN_MEMORY): Use return_in_memory.
(FUNCTION_VALUE, LIBCALL_VALUE): Use function_value.
(SPLIT_COMPLEX_ARGS): New.
* config/alpha/alpha-protos.h: Update.
2003-06-27 Ulrich Weigand <uweigand@de.ibm.com>
* ggc-page.c (inverse_table): Change type of mult to size_t.
(compute_inverse): Compute inverse using size_t, not unsigned int.

View File

@ -135,6 +135,9 @@ extern void alpha_setup_incoming_varargs (CUMULATIVE_ARGS, enum machine_mode,
extern void alpha_va_start (tree, rtx);
extern rtx alpha_va_arg (tree, tree);
extern rtx function_arg (CUMULATIVE_ARGS, enum machine_mode, tree, int);
extern rtx function_value (tree, tree, enum machine_mode);
extern bool return_in_memory (tree, enum machine_mode);
extern void alpha_start_function (FILE *, const char *, tree);
extern void alpha_end_function (FILE *, const char *, tree);

View File

@ -5864,14 +5864,25 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
int basereg;
int num_args;
/* Set up defaults for FP operands passed in FP registers, and
integral operands passed in integer registers. */
if (TARGET_FPREGS
&& (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
|| GET_MODE_CLASS (mode) == MODE_FLOAT))
basereg = 32 + 16;
else
/* Don't get confused and pass small structures in FP registers. */
if (type && AGGREGATE_TYPE_P (type))
basereg = 16;
else
{
#ifdef ENABLE_CHECKING
/* With SPLIT_COMPLEX_ARGS, we shouldn't see any raw complex
values here. */
if (COMPLEX_MODE_P (mode))
abort ();
#endif
/* Set up defaults for FP operands passed in FP registers, and
integral operands passed in integer registers. */
if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT)
basereg = 32 + 16;
else
basereg = 16;
}
/* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for
the three platforms, so we can't avoid conditional compilation. */
@ -5884,8 +5895,7 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
return NULL_RTX;
}
#else
#if TARGET_ABI_UNICOSMK
#elif TARGET_ABI_UNICOSMK
{
int size;
@ -5949,7 +5959,7 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
}
}
}
#else
#elif TARGET_ABI_OSF
{
if (cum >= 6)
return NULL_RTX;
@ -5963,12 +5973,119 @@ function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
basereg = 16;
}
#endif /* TARGET_ABI_UNICOSMK */
#endif /* TARGET_ABI_OPEN_VMS */
#else
#error Unhandled ABI
#endif
return gen_rtx_REG (mode, num_args + basereg);
}
/* Return true if TYPE must be returned in memory, instead of in registers. */
bool
return_in_memory (tree type, enum machine_mode mode)
{
int size;
if (type)
{
mode = TYPE_MODE (type);
/* All aggregates are returned in memory. */
if (AGGREGATE_TYPE_P (type))
return true;
}
size = GET_MODE_SIZE (mode);
switch (GET_MODE_CLASS (mode))
{
case MODE_VECTOR_FLOAT:
/* Pass all float vectors in memory, like an aggregate. */
return true;
case MODE_COMPLEX_FLOAT:
/* We judge complex floats on the size of their element,
not the size of the whole type. */
size = GET_MODE_UNIT_SIZE (mode);
break;
case MODE_INT:
case MODE_FLOAT:
case MODE_COMPLEX_INT:
case MODE_VECTOR_INT:
break;
default:
/* ??? We get called on all sorts of random stuff from
aggregate_value_p. We can't abort, but it's not clear
what's safe to return. Pretend it's a struct I guess. */
return true;
}
/* Otherwise types must fit in one register. */
return size > UNITS_PER_WORD;
}
/* Define how to find the value returned by a function. VALTYPE is the
data type of the value (as a tree). If the precise function being
called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0.
MODE is set instead of VALTYPE for libcalls.
On Alpha the value is found in $0 for integer functions and
$f0 for floating-point functions. */
rtx
function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
enum machine_mode mode)
{
unsigned int regnum;
enum mode_class class;
#ifdef ENABLE_CHECKING
if (return_in_memory (valtype, mode))
abort ();
#endif
if (valtype)
mode = TYPE_MODE (valtype);
class = GET_MODE_CLASS (mode);
switch (class)
{
case MODE_INT:
/* Do the same thing as PROMOTE_MODE. */
mode = DImode;
/* FALLTHRU */
case MODE_COMPLEX_INT:
case MODE_VECTOR_INT:
regnum = 0;
break;
case MODE_FLOAT:
regnum = 32;
break;
case MODE_COMPLEX_FLOAT:
{
enum machine_mode cmode = GET_MODE_INNER (mode);
return gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 32),
GEN_INT (0)),
gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 33),
GEN_INT (GET_MODE_SIZE (cmode)))));
}
default:
abort ();
}
return gen_rtx_REG (mode, regnum);
}
tree
alpha_build_va_list (void)
{
@ -6162,7 +6279,27 @@ alpha_va_arg (tree valist, tree type)
indirect = 1;
rounded_size = size_int (UNITS_PER_WORD);
}
else if (FLOAT_TYPE_P (type))
else if (TREE_CODE (type) == COMPLEX_TYPE)
{
rtx real_part, imag_part, value, tmp;
real_part = alpha_va_arg (valist, TREE_TYPE (type));
imag_part = alpha_va_arg (valist, TREE_TYPE (type));
/* ??? Most irritatingly, we're not returning the value here,
but the address. Since real_part and imag_part are not
necessarily contiguous, we must copy to local storage. */
real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part);
imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part);
value = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part);
tmp = assign_temp (type, 0, 1, 0);
emit_move_insn (tmp, value);
return XEXP (tmp, 0);
}
else if (TREE_CODE (type) == REAL_TYPE)
{
tree fpaddend, cond;

View File

@ -994,25 +994,14 @@ extern int alpha_memory_latency;
On Alpha the value is found in $0 for integer functions and
$f0 for floating-point functions. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE)) \
? word_mode : TYPE_MODE (VALTYPE), \
((TARGET_FPREGS \
&& (TREE_CODE (VALTYPE) == REAL_TYPE \
|| TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
? 32 : 0))
#define FUNCTION_VALUE(VALTYPE, FUNC) \
function_value (VALTYPE, FUNC, VOIDmode)
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
#define LIBCALL_VALUE(MODE) \
gen_rtx_REG (MODE, \
(TARGET_FPREGS \
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
? 32 : 0))
#define LIBCALL_VALUE(MODE) \
function_value (NULL, NULL, MODE)
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers.
@ -1021,10 +1010,7 @@ extern int alpha_memory_latency;
are integers whose size is larger than 64 bits. */
#define RETURN_IN_MEMORY(TYPE) \
(TYPE_MODE (TYPE) == BLKmode \
|| TYPE_MODE (TYPE) == TFmode \
|| TYPE_MODE (TYPE) == TCmode \
|| (TREE_CODE (TYPE) == INTEGER_TYPE && TYPE_PRECISION (TYPE) > 64))
return_in_memory (TYPE, VOIDmode)
/* 1 if N is a possible register number for a function value
as seen by the caller. */
@ -1889,3 +1875,6 @@ do { \
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS 1
/* Pass complex arguments independently. */
#define SPLIT_COMPLEX_ARGS 1