rs6000.c (rs6000_function_arg): If a float argument does not fit fully into floating-point registers...
gcc/ * config/rs6000/rs6000.c (rs6000_function_arg): If a float argument does not fit fully into floating-point registers, and there is still space in the register parameter area, use GPRs to pass those parts of the argument. Issue -Wpsabi note if any parameter is now treated differently than before. (rs6000_arg_partial_bytes): Update. gcc/testsuite/ * gcc.target/powerpc/ppc64-abi-warn-1.c: New test. From-SVN: r213015
This commit is contained in:
parent
c41e1ae6c0
commit
ff46d64d82
|
@ -1,3 +1,12 @@
|
|||
2014-07-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_function_arg): If a float argument
|
||||
does not fit fully into floating-point registers, and there is still
|
||||
space in the register parameter area, use GPRs to pass those parts
|
||||
of the argument. Issue -Wpsabi note if any parameter is now treated
|
||||
differently than before.
|
||||
(rs6000_arg_partial_bytes): Update.
|
||||
|
||||
2014-07-24 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/alpha/elf.h: Define TARGET_UNWIND_TABLES_DEFAULT.
|
||||
|
|
|
@ -10229,6 +10229,7 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
|
|||
rtx r, off;
|
||||
int i, k = 0;
|
||||
unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
|
||||
int fpr_words;
|
||||
|
||||
/* Do we also need to pass this argument in the parameter
|
||||
save area? */
|
||||
|
@ -10257,6 +10258,47 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
|
|||
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
|
||||
}
|
||||
|
||||
/* If there were not enough FPRs to hold the argument, the rest
|
||||
usually goes into memory. However, if the current position
|
||||
is still within the register parameter area, a portion may
|
||||
actually have to go into GPRs.
|
||||
|
||||
Note that it may happen that the portion of the argument
|
||||
passed in the first "half" of the first GPR was already
|
||||
passed in the last FPR as well.
|
||||
|
||||
For unnamed arguments, we already set up GPRs to cover the
|
||||
whole argument in rs6000_psave_function_arg, so there is
|
||||
nothing further to do at this point. */
|
||||
fpr_words = (i * GET_MODE_SIZE (elt_mode)) / (TARGET_32BIT ? 4 : 8);
|
||||
if (i < n_elts && align_words + fpr_words < GP_ARG_NUM_REG
|
||||
&& cum->nargs_prototype > 0)
|
||||
{
|
||||
static bool warned;
|
||||
|
||||
enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
|
||||
int n_words = rs6000_arg_size (mode, type);
|
||||
|
||||
align_words += fpr_words;
|
||||
n_words -= fpr_words;
|
||||
|
||||
do
|
||||
{
|
||||
r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words);
|
||||
off = GEN_INT (fpr_words++ * GET_MODE_SIZE (rmode));
|
||||
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
|
||||
}
|
||||
while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
|
||||
|
||||
if (!warned && warn_psabi)
|
||||
{
|
||||
warned = true;
|
||||
inform (input_location,
|
||||
"the ABI of passing homogeneous float aggregates"
|
||||
" has changed in GCC 4.10");
|
||||
}
|
||||
}
|
||||
|
||||
return rs6000_finish_function_arg (mode, rvec, k);
|
||||
}
|
||||
else if (align_words < GP_ARG_NUM_REG)
|
||||
|
@ -10332,8 +10374,23 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
|
|||
/* Otherwise, we pass in FPRs only. Check for partial copies. */
|
||||
passed_in_gprs = false;
|
||||
if (cum->fregno + n_elts * n_fpreg > FP_ARG_MAX_REG + 1)
|
||||
ret = ((FP_ARG_MAX_REG + 1 - cum->fregno)
|
||||
{
|
||||
/* Compute number of bytes / words passed in FPRs. If there
|
||||
is still space available in the register parameter area
|
||||
*after* that amount, a part of the argument will be passed
|
||||
in GPRs. In that case, the total amount passed in any
|
||||
registers is equal to the amount that would have been passed
|
||||
in GPRs if everything were passed there, so we fall back to
|
||||
the GPR code below to compute the appropriate value. */
|
||||
int fpr = ((FP_ARG_MAX_REG + 1 - cum->fregno)
|
||||
* MIN (8, GET_MODE_SIZE (elt_mode)));
|
||||
int fpr_words = fpr / (TARGET_32BIT ? 4 : 8);
|
||||
|
||||
if (align_words + fpr_words < GP_ARG_NUM_REG)
|
||||
passed_in_gprs = true;
|
||||
else
|
||||
ret = fpr;
|
||||
}
|
||||
}
|
||||
|
||||
if (passed_in_gprs
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2014-07-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/ppc64-abi-warn-1.c: New test.
|
||||
|
||||
2014-07-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* g++.dg/compat/struct-layout-1.exp: Load g++-dg.exp.
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
|
||||
/* { dg-options "-mabi=elfv2" } */
|
||||
|
||||
struct f8
|
||||
{
|
||||
float x[8];
|
||||
};
|
||||
|
||||
void test (struct f8 a, struct f8 b) /* { dg-message "note: the ABI of passing homogeneous float aggregates has changed" } */
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue