rs6000.c (rs6000_parallel_return): New function.

* config/rs6000/rs6000.c (rs6000_parallel_return): New function.
	(rs6000_function_value): Use it.  Handle SCmode and TCmode as well,
	for TARGET_32BIT && TARGET_POWERPC64.  Fix another BITS_PER_WORD
	snafu.
	(rs6000_libcall_value): Use the new function.

From-SVN: r219804
This commit is contained in:
Segher Boessenkool 2015-01-17 21:58:12 +01:00 committed by Segher Boessenkool
parent 3b97ab5aed
commit 436bd91737
2 changed files with 53 additions and 60 deletions

View File

@ -1,3 +1,11 @@
2015-01-17 Segher Boessenkool <segher@kernel.crashing.org>
* config/rs6000/rs6000.c (rs6000_parallel_return): New function.
(rs6000_function_value): Use it. Handle SCmode and TCmode as well,
for TARGET_32BIT && TARGET_POWERPC64. Fix another BITS_PER_WORD
snafu.
(rs6000_libcall_value): Use the new function.
2015-01-17 Sandra Loosemore <sandra@codesourcery.com>
* doc/invoke.texi ([-ftracer]): Remove duplicate option listing.

View File

@ -31583,6 +31583,29 @@ rs6000_complex_function_value (machine_mode mode)
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
}
/* Return an rtx describing a return value of MODE as a PARALLEL
in N_ELTS registers, each of mode ELT_MODE, starting at REGNO,
stride REG_STRIDE. */
static rtx
rs6000_parallel_return (machine_mode mode,
int n_elts, machine_mode elt_mode,
unsigned int regno, unsigned int reg_stride)
{
rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
int i;
for (i = 0; i < n_elts; i++)
{
rtx r = gen_rtx_REG (elt_mode, regno);
rtx off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, r, off);
regno += reg_stride;
}
return par;
}
/* Target hook for TARGET_FUNCTION_VALUE.
On the SPE, both FPs and vectors are returned in r3.
@ -31618,12 +31641,12 @@ rs6000_function_value (const_tree valtype,
/* Otherwise fall through to standard ABI rules. */
}
mode = TYPE_MODE (valtype);
/* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */
if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (valtype), valtype,
&elt_mode, &n_elts))
if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode, &n_elts))
{
int first_reg, n_regs, i;
rtx par;
int first_reg, n_regs;
if (SCALAR_FLOAT_MODE_P (elt_mode))
{
@ -31637,53 +31660,25 @@ rs6000_function_value (const_tree valtype,
n_regs = 1;
}
par = gen_rtx_PARALLEL (TYPE_MODE (valtype), rtvec_alloc (n_elts));
for (i = 0; i < n_elts; i++)
{
rtx r = gen_rtx_REG (elt_mode, first_reg + i * n_regs);
rtx off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, r, off);
}
return par;
return rs6000_parallel_return (mode, n_elts, elt_mode, first_reg, n_regs);
}
if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
{
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */
return gen_rtx_PARALLEL (DImode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode, GP_ARG_RETURN),
const0_rtx),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode,
GP_ARG_RETURN + 1),
GEN_INT (4))));
}
if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DCmode)
{
return gen_rtx_PARALLEL (DCmode,
gen_rtvec (4,
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode, GP_ARG_RETURN),
const0_rtx),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode,
GP_ARG_RETURN + 1),
GEN_INT (4)),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode,
GP_ARG_RETURN + 2),
GEN_INT (8)),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode,
GP_ARG_RETURN + 3),
GEN_INT (12))));
}
/* Some return value types need be split in -mpowerpc64, 32bit ABI. */
if (TARGET_32BIT && TARGET_POWERPC64)
switch (mode)
{
default:
break;
case DImode:
case SCmode:
case DCmode:
case TCmode:
int count = GET_MODE_SIZE (mode) / 4;
return rs6000_parallel_return (mode, count, SImode, GP_ARG_RETURN, 1);
}
mode = TYPE_MODE (valtype);
if ((INTEGRAL_TYPE_P (valtype) && GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
if ((INTEGRAL_TYPE_P (valtype)
&& GET_MODE_BITSIZE (mode) < (TARGET_32BIT ? 32 : 64))
|| POINTER_TYPE_P (valtype))
mode = TARGET_32BIT ? SImode : DImode;
@ -31720,19 +31715,9 @@ rs6000_libcall_value (machine_mode mode)
{
unsigned int regno;
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */
if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
{
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */
return gen_rtx_PARALLEL (DImode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode, GP_ARG_RETURN),
const0_rtx),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SImode,
GP_ARG_RETURN + 1),
GEN_INT (4))));
}
return rs6000_parallel_return (mode, 2, SImode, GP_ARG_RETURN, 1);
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */