From 436bd91737b08f9221d0a08601721660a7fd2f81 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 17 Jan 2015 21:58:12 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 8 +++ gcc/config/rs6000/rs6000.c | 105 ++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 46515eb4343..fc5fd061099 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-01-17 Segher Boessenkool + + * 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 * doc/invoke.texi ([-ftracer]): Remove duplicate option listing. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3926b079523..551181ba7a5 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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. */ -- 2.30.2