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>
PR rtl-optimization/71028
......
......@@ -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);
}
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
......@@ -10173,6 +10202,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))
......@@ -10552,11 +10582,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. */
......@@ -11213,11 +11239,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 assumes
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,
rsize = (size + 3) / 4;
align = 1;
if (TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode)
|| (TARGET_DOUBLE_FLOAT
&& (TYPE_MODE (type) == DFmode
|| FLOAT128_2REG_P (TYPE_MODE (type))
|| DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
machine_mode mode = TYPE_MODE (type);
if (abi_v4_pass_in_fpr (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
......@@ -12170,7 +12188,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
{
......@@ -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
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));
......@@ -12218,7 +12236,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);
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