Commit c8acbe37 by Alan Modra Committed by Alan Modra

[RS6000] complex long double ABI_V4 fix

Revision 235794 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.

	* 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.

From-SVN: r236111
parent 36bc0163
2016-05-11 Alan Modra <amodra@gmail.com>
* 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.
2016-05-10 Segher Boessenkool <segher@kernel.crashing.org> 2016-05-10 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/71028 PR rtl-optimization/71028
......
...@@ -10089,6 +10089,35 @@ rs6000_must_pass_in_stack (machine_mode mode, const_tree type) ...@@ -10089,6 +10089,35 @@ rs6000_must_pass_in_stack (machine_mode mode, const_tree type)
return must_pass_in_stack_var_size_or_pad (mode, 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 /* If defined, a C expression which determines whether, and in which
direction, to pad out an argument with extra space. The value direction, to pad out an argument with extra space. The value
should be of type `enum direction': either `upward' to pad above should be of type `enum direction': either `upward' to pad above
...@@ -10173,6 +10202,7 @@ rs6000_function_arg_boundary (machine_mode mode, const_tree type) ...@@ -10173,6 +10202,7 @@ rs6000_function_arg_boundary (machine_mode mode, const_tree type)
&& (GET_MODE_SIZE (mode) == 8 && (GET_MODE_SIZE (mode) == 8
|| (TARGET_HARD_FLOAT || (TARGET_HARD_FLOAT
&& TARGET_FPRS && TARGET_FPRS
&& !is_complex_IBM_long_double (mode)
&& FLOAT128_2REG_P (mode)))) && FLOAT128_2REG_P (mode))))
return 64; return 64;
else if (FLOAT128_VECTOR_P (mode)) else if (FLOAT128_VECTOR_P (mode))
...@@ -10552,11 +10582,7 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, ...@@ -10552,11 +10582,7 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode,
} }
else if (DEFAULT_ABI == ABI_V4) else if (DEFAULT_ABI == ABI_V4)
{ {
if (TARGET_HARD_FLOAT && TARGET_FPRS if (abi_v4_pass_in_fpr (mode))
&& ((TARGET_SINGLE_FLOAT && mode == SFmode)
|| (TARGET_DOUBLE_FLOAT && mode == DFmode)
|| FLOAT128_2REG_P (mode)
|| DECIMAL_FLOAT_MODE_P (mode)))
{ {
/* _Decimal128 must use an even/odd register pair. This assumes /* _Decimal128 must use an even/odd register pair. This assumes
that the register number is odd when fregno is odd. */ that the register number is odd when fregno is odd. */
...@@ -11213,11 +11239,7 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, ...@@ -11213,11 +11239,7 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode,
else if (abi == ABI_V4) else if (abi == ABI_V4)
{ {
if (TARGET_HARD_FLOAT && TARGET_FPRS if (abi_v4_pass_in_fpr (mode))
&& ((TARGET_SINGLE_FLOAT && mode == SFmode)
|| (TARGET_DOUBLE_FLOAT && mode == DFmode)
|| FLOAT128_2REG_P (mode)
|| DECIMAL_FLOAT_MODE_P (mode)))
{ {
/* _Decimal128 must use an even/odd register pair. This assumes /* _Decimal128 must use an even/odd register pair. This assumes
that the register number is odd when fregno is odd. */ that the register number is odd when fregno is odd. */
...@@ -12138,19 +12160,15 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, ...@@ -12138,19 +12160,15 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
rsize = (size + 3) / 4; rsize = (size + 3) / 4;
align = 1; align = 1;
if (TARGET_HARD_FLOAT && TARGET_FPRS machine_mode mode = TYPE_MODE (type);
&& ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode) if (abi_v4_pass_in_fpr (mode))
|| (TARGET_DOUBLE_FLOAT
&& (TYPE_MODE (type) == DFmode
|| FLOAT128_2REG_P (TYPE_MODE (type))
|| DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
{ {
/* FP args go in FP registers, if present. */ /* FP args go in FP registers, if present. */
reg = fpr; reg = fpr;
n_reg = (size + 7) / 8; n_reg = (size + 7) / 8;
sav_ofs = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4) * 4; sav_ofs = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4) * 4;
sav_scale = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 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; align = 8;
} }
else else
...@@ -12170,7 +12188,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, ...@@ -12170,7 +12188,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
addr = create_tmp_var (ptr_type_node, "addr"); addr = create_tmp_var (ptr_type_node, "addr");
/* AltiVec vectors never go in registers when -mabi=altivec. */ /* 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; align = 16;
else else
{ {
...@@ -12191,7 +12209,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, ...@@ -12191,7 +12209,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
} }
/* _Decimal128 is passed in even/odd fpr pairs; the stored /* _Decimal128 is passed in even/odd fpr pairs; the stored
reg number is 0 for f1, so we want to make it odd. */ 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), t = build2 (BIT_IOR_EXPR, TREE_TYPE (reg), unshare_expr (reg),
build_int_cst (TREE_TYPE (reg), 1)); build_int_cst (TREE_TYPE (reg), 1));
...@@ -12218,7 +12236,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, ...@@ -12218,7 +12236,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
FP register for 32-bit binaries. */ FP register for 32-bit binaries. */
if (TARGET_32BIT if (TARGET_32BIT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_HARD_FLOAT && TARGET_FPRS
&& TYPE_MODE (type) == SDmode) && mode == SDmode)
t = fold_build_pointer_plus_hwi (t, size); t = fold_build_pointer_plus_hwi (t, size);
gimplify_assign (addr, t, pre_p); gimplify_assign (addr, t, pre_p);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment