Hello, this is the final patch preparing for the new ABI.
The logic in rs6000_arg_partial_bytes is a bit complex, since it apparently still contains remnants from the time where this routine was used even for arguments that are returned both in GPRs and FPRs/VRs (*and* memory). These days, all such cases are handled completely in rs6000_function_arg so rs6000_arg_partial_bytes should always return 0; which it *does*, even though in a somewhat complex way. This complex logic would make handling homogeneous structs more difficult than it needs to be. Therefore, this patch simplifies the logic by making explicit the fact that rs6000_arg_partial_bytes does not actually need to handle the cases described above. No change in generated code expected. Tested on powerpc64-linux and powerpc64le-linux. OK for mainline? Bye, Ulrich ChangeLog: 2013-11-11 Ulrich Weigand <ulrich.weig...@de.ibm.com> * config/rs6000/rs6000.c (rs6000_arg_partial_bytes): Simplify logic by making use of the fact that for vector / floating point arguments passed both in VRs/FPRs and in the fixed parameter area, the partial bytes mechanism is in fact not used. Index: gcc/gcc/config/rs6000/rs6000.c =================================================================== --- gcc.orig/gcc/config/rs6000/rs6000.c +++ gcc/gcc/config/rs6000/rs6000.c @@ -9835,15 +9835,25 @@ rs6000_arg_partial_bytes (cumulative_arg tree type, bool named) { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + bool passed_in_gprs = true; int ret = 0; int align_words; if (DEFAULT_ABI == ABI_V4) return 0; - if (USE_ALTIVEC_FOR_ARG_P (cum, mode, named) - && cum->nargs_prototype >= 0) - return 0; + if (USE_ALTIVEC_FOR_ARG_P (cum, mode, named)) + { + /* If we are passing this arg in the fixed parameter save area + (gprs or memory) as well as VRs, we do not use the partial + bytes mechanism; instead, rs6000_function_arg wil return a + PARALLEL including a memory element as necessary. */ + if (TARGET_64BIT && ! cum->prototype) + return 0; + + /* Otherwise, we pass in VRs only. No partial copy possible. */ + passed_in_gprs = false; + } /* In this complicated case we just disable the partial_nregs code. */ if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) @@ -9853,24 +9863,27 @@ rs6000_arg_partial_bytes (cumulative_arg if (USE_FP_FOR_ARG_P (cum, mode)) { + unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3; + /* If we are passing this arg in the fixed parameter save area - (gprs or memory) as well as fprs, then this function should - return the number of partial bytes passed in the parameter - save area rather than partial bytes passed in fprs. */ + (gprs or memory) as well as FPRs, we do not use the partial + bytes mechanism; instead, rs6000_function_arg wil return a + PARALLEL including a memory element as necessary. */ if (type && (cum->nargs_prototype <= 0 || (DEFAULT_ABI == ABI_AIX && TARGET_XL_COMPAT && align_words >= GP_ARG_NUM_REG))) return 0; - else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) - > FP_ARG_MAX_REG + 1) + + /* Otherwise, we pass in FPRs only. Check for partial copies. */ + passed_in_gprs = false; + if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1) ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8; - else if (cum->nargs_prototype >= 0) - return 0; } - if (align_words < GP_ARG_NUM_REG + if (passed_in_gprs + && align_words < GP_ARG_NUM_REG && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type)) ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8); -- Dr. Ulrich Weigand GNU/Linux compilers and toolchain ulrich.weig...@de.ibm.com