Re: [RS6000] complex long double ABI_V4 fix
On Wed, May 11, 2016 at 09:17:00AM +0930, Alan Modra wrote: > On Mon, May 09, 2016 at 09:43:36AM -0500, Segher Boessenkool wrote: > > Since this monstruous, unreadable condition is used a lot, use a nicely > > named > > helper function instead? > > Like this? Like that. Thanks! > * config/rs6000/rs6000.c (is_complex_IBM_long_double, > abi_v4_pass_in_fpr): New functions. > (rs6000_function_arg_boundary): Exclude complex IBM long double > from 64-bit alignment when ABI_V4. > (rs6000_function_arg, rs6000_function_arg_advance_1, > rs6000_gimplify_va_arg): Use abi_v4_pass_in_fpr. Okay for trunk. Segher
Re: [RS6000] complex long double ABI_V4 fix
On Mon, May 09, 2016 at 09:43:36AM -0500, Segher Boessenkool wrote: > On Fri, May 06, 2016 at 03:54:43PM +0930, Alan Modra wrote: > > Revision 235792 regressed compat/scalar-by-value-6 for powerpc-linux > > -m32 due to accidentally changing the ABI. By another historical > > accident, complex long double is stupidly passed in gprs for -m32. > > > > Bootstrapped and regression tested powerpc64-linux. Also fixes > > gfortran.dg/{large_real_kind_2.F90,large_real_kind_form_io_1.f90}. > > OK to apply? > > > * config/rs6000/rs6000.c (rs6000_function_arg): Exclude IBM > > complex long double from args passed in fprs for ABI_V4. > > (rs6000_function_arg_boundary, rs6000_function_arg_advance_1, > > rs6000_gimplify_va_arg): Likewise. > > > > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > > index 1215925..9c7a37b 100644 > > --- a/gcc/config/rs6000/rs6000.c > > +++ b/gcc/config/rs6000/rs6000.c > > @@ -10142,6 +10142,7 @@ rs6000_function_arg_boundary (machine_mode mode, > > const_tree type) > >&& (GET_MODE_SIZE (mode) == 8 > > || (TARGET_HARD_FLOAT > > && TARGET_FPRS > > + && !(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) > > && FLOAT128_2REG_P (mode > > Since this monstruous, unreadable condition is used a lot, use a nicely named > helper function instead? Like this? Regstrapped powerpc64-linux. If you look closely you'll see that this changes the condition for rs6000_gimplify_arg slightly, which had TARGET_DOUBLE_FLOAT being tested for more than just DFmode. It's wrong for function_arg to be different to gimplify_va_arg, and might matter for spe. Note that I doubt abi_v4_pass_in_fpr is completely correct regarding TARGET_SINGLE_FLOAT and TARGET_DOUBLE_FLOAT, but I'm going to leave tidying that to a maintainer. It seems to me that TARGET_SINGLE_FLOAT ought to affect SDmode as well as SFmode, and TARGET_DOUBLE_FLOAT everything else. * config/rs6000/rs6000.c (is_complex_IBM_long_double, abi_v4_pass_in_fpr): New functions. (rs6000_function_arg_boundary): Exclude complex IBM long double from 64-bit alignment when ABI_V4. (rs6000_function_arg, rs6000_function_arg_advance_1, rs6000_gimplify_va_arg): Use abi_v4_pass_in_fpr. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e01630e..2763ea6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -10053,6 +10053,35 @@ rs6000_must_pass_in_stack (machine_mode mode, const_tree type) return must_pass_in_stack_var_size_or_pad (mode, type); } +static inline bool +is_complex_IBM_long_double (machine_mode mode) +{ + return mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode); +} + +/* Whether ABI_V4 passes MODE args to a function in floating point + registers. */ + +static bool +abi_v4_pass_in_fpr (machine_mode mode) +{ + if (!TARGET_FPRS || !TARGET_HARD_FLOAT) +return false; + if (TARGET_SINGLE_FLOAT && mode == SFmode) +return true; + if (TARGET_DOUBLE_FLOAT && mode == DFmode) +return true; + /* ABI_V4 passes complex IBM long double in 8 gprs. + Stupid, but we can't change the ABI now. */ + if (is_complex_IBM_long_double (mode)) +return false; + if (FLOAT128_2REG_P (mode)) +return true; + if (DECIMAL_FLOAT_MODE_P (mode)) +return true; + return false; +} + /* If defined, a C expression which determines whether, and in which direction, to pad out an argument with extra space. The value should be of type `enum direction': either `upward' to pad above @@ -10137,6 +10166,7 @@ rs6000_function_arg_boundary (machine_mode mode, const_tree type) && (GET_MODE_SIZE (mode) == 8 || (TARGET_HARD_FLOAT && TARGET_FPRS + && !is_complex_IBM_long_double (mode) && FLOAT128_2REG_P (mode return 64; else if (FLOAT128_VECTOR_P (mode)) @@ -10516,11 +10546,7 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, } else if (DEFAULT_ABI == ABI_V4) { - if (TARGET_HARD_FLOAT && TARGET_FPRS - && ((TARGET_SINGLE_FLOAT && mode == SFmode) - || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || FLOAT128_2REG_P (mode) - || DECIMAL_FLOAT_MODE_P (mode))) + if (abi_v4_pass_in_fpr (mode)) { /* _Decimal128 must use an even/odd register pair. This assumes that the register number is odd when fregno is odd. */ @@ -11177,11 +11203,7 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, else if (abi == ABI_V4) { - if (TARGET_HARD_FLOAT && TARGET_FPRS - && ((TARGET_SINGLE_FLOAT && mode == SFmode) - || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || FLOAT128_2REG_P (mode) - || DECIMAL_FLOAT_MODE_P (mode))) + if (abi_v4_pass_in_fpr (mode)) { /* _Decimal128 must use an even/odd register pair. This
Re: [RS6000] complex long double ABI_V4 fix
On Fri, May 06, 2016 at 03:54:43PM +0930, Alan Modra wrote: > Revision 235792 regressed compat/scalar-by-value-6 for powerpc-linux > -m32 due to accidentally changing the ABI. By another historical > accident, complex long double is stupidly passed in gprs for -m32. Sorry about the breakage. Thanks for digging into it. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Re: [RS6000] complex long double ABI_V4 fix
On Fri, May 06, 2016 at 03:54:43PM +0930, Alan Modra wrote: > Revision 235792 regressed compat/scalar-by-value-6 for powerpc-linux > -m32 due to accidentally changing the ABI. By another historical > accident, complex long double is stupidly passed in gprs for -m32. > > Bootstrapped and regression tested powerpc64-linux. Also fixes > gfortran.dg/{large_real_kind_2.F90,large_real_kind_form_io_1.f90}. > OK to apply? > * config/rs6000/rs6000.c (rs6000_function_arg): Exclude IBM > complex long double from args passed in fprs for ABI_V4. > (rs6000_function_arg_boundary, rs6000_function_arg_advance_1, > rs6000_gimplify_va_arg): Likewise. > > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > index 1215925..9c7a37b 100644 > --- a/gcc/config/rs6000/rs6000.c > +++ b/gcc/config/rs6000/rs6000.c > @@ -10142,6 +10142,7 @@ rs6000_function_arg_boundary (machine_mode mode, > const_tree type) >&& (GET_MODE_SIZE (mode) == 8 > || (TARGET_HARD_FLOAT > && TARGET_FPRS > + && !(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) > && FLOAT128_2REG_P (mode Since this monstruous, unreadable condition is used a lot, use a nicely named helper function instead? Segher
Re: [RS6000] complex long double ABI_V4 fix
On Fri, May 06, 2016 at 03:54:43PM +0930, Alan Modra wrote: > Revision 235792 regressed compat/scalar-by-value-6 for powerpc-linux Sorry, typo in the revision. Should be 235794, git 3c62cae0. -- Alan Modra Australia Development Lab, IBM
[RS6000] complex long double ABI_V4 fix
Revision 235792 regressed compat/scalar-by-value-6 for powerpc-linux -m32 due to accidentally changing the ABI. By another historical accident, complex long double is stupidly passed in gprs for -m32. Bootstrapped and regression tested powerpc64-linux. Also fixes gfortran.dg/{large_real_kind_2.F90,large_real_kind_form_io_1.f90}. OK to apply? * config/rs6000/rs6000.c (rs6000_function_arg): Exclude IBM complex long double from args passed in fprs for ABI_V4. (rs6000_function_arg_boundary, rs6000_function_arg_advance_1, rs6000_gimplify_va_arg): Likewise. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 1215925..9c7a37b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -10142,6 +10142,7 @@ rs6000_function_arg_boundary (machine_mode mode, const_tree type) && (GET_MODE_SIZE (mode) == 8 || (TARGET_HARD_FLOAT && TARGET_FPRS + && !(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) && FLOAT128_2REG_P (mode return 64; else if (FLOAT128_VECTOR_P (mode)) @@ -10524,7 +10525,8 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, if (TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && mode == SFmode) || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || FLOAT128_2REG_P (mode) + || (!(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) + && FLOAT128_2REG_P (mode)) || DECIMAL_FLOAT_MODE_P (mode))) { /* _Decimal128 must use an even/odd register pair. This assumes @@ -11185,7 +11187,10 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, if (TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && mode == SFmode) || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || FLOAT128_2REG_P (mode) + /* ABI_V4 passes complex IBM long double in 8 gprs. +Stupid, but we can't change the ABI now. */ + || (!(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) + && FLOAT128_2REG_P (mode)) || DECIMAL_FLOAT_MODE_P (mode))) { /* _Decimal128 must use an even/odd register pair. This assumes @@ -12107,19 +12112,21 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, rsize = (size + 3) / 4; align = 1; + machine_mode mode = TYPE_MODE (type); if (TARGET_HARD_FLOAT && TARGET_FPRS - && ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode) + && ((TARGET_SINGLE_FLOAT && mode == SFmode) || (TARGET_DOUBLE_FLOAT - && (TYPE_MODE (type) == DFmode - || FLOAT128_2REG_P (TYPE_MODE (type)) - || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)) + && (mode == DFmode + || (!(mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode)) + && FLOAT128_2REG_P (mode)) + || DECIMAL_FLOAT_MODE_P (mode) { /* FP args go in FP registers, if present. */ reg = fpr; n_reg = (size + 7) / 8; sav_ofs = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4) * 4; sav_scale = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4); - if (TYPE_MODE (type) != SFmode && TYPE_MODE (type) != SDmode) + if (mode != SFmode && mode != SDmode) align = 8; } else @@ -12139,7 +12146,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, addr = create_tmp_var (ptr_type_node, "addr"); /* AltiVec vectors never go in registers when -mabi=altivec. */ - if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))) + if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) align = 16; else { @@ -12160,7 +12167,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, } /* _Decimal128 is passed in even/odd fpr pairs; the stored reg number is 0 for f1, so we want to make it odd. */ - else if (reg == fpr && TYPE_MODE (type) == TDmode) + else if (reg == fpr && mode == TDmode) { t = build2 (BIT_IOR_EXPR, TREE_TYPE (reg), unshare_expr (reg), build_int_cst (TREE_TYPE (reg), 1)); @@ -12187,7 +12194,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, FP register for 32-bit binaries. */ if (TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPRS - && TYPE_MODE (type) == SDmode) + && mode == SDmode) t = fold_build_pointer_plus_hwi (t, size); gimplify_assign (addr, t, pre_p); -- Alan Modra Australia Development Lab, IBM