diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1524ee03dee..244cf230c41 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-07-24 Ulrich Weigand + + * 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 * config/alpha/elf.h: Define TARGET_UNWIND_TABLES_DEFAULT. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 02fc5d90492..0f028623871 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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) - * MIN (8, GET_MODE_SIZE (elt_mode))); + { + /* 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d37c6a94737..f64ab591c98 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-07-24 Ulrich Weigand + + * gcc.target/powerpc/ppc64-abi-warn-1.c: New test. + 2014-07-24 Ulrich Weigand * g++.dg/compat/struct-layout-1.exp: Load g++-dg.exp. diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c new file mode 100644 index 00000000000..c70c14c2858 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c @@ -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" } */ +{ +} +