Commit 526303ec by Michael Meissner Committed by Michael Meissner

rs6000-protos.h (rs6000_expand_float128_convert): Add declaration.

2015-08-26  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
	Add declaration.

	* config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
	comment.
	(rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
	floating point in VSX registers.
	(rs6000_output_move_128bit): Always print out the set insn if we
	can't generate an appropriate 128-bit move.
	(rs6000_generate_compare): Add support for IEEE 128-bit floating
	point in VSX registers comparisons.
	(rs6000_expand_float128_convert): Likewise.

	* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
	predicate for only GPR hard registers.

	* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
	modes to iterators. Add new iterators for moving 128-bit values in
	scalar FPR registers and VSX registers.
	(FMOVE128): Likewise.
	(FMOVE128_FPR): Likewise.
	(FMOVE128_GPR): Likewise.
	(FMOVE128_VSX): Likewise.
	(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
	in VSX registers.
	(IFKF): Likewise.
	(IBM128): Likewise.
	(TFIFKF): Likewise.
	(RELOAD): Add IEEE 128-bit floating point modes.
	(signbittf2): Convert TF insns to add support for new IEEE 128-bit
	floating point in VSX registers modes.
	(signbit<mode>2, IBM128 iterator): Likewise.
	(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
	(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
	(negtf2): Likewise.
	(neg<mode>2, TFIFKF iterator): Likewise.
	(negtf2_internal): Likewise.
	(abstf2): Likewise.
	(abs<mode>2, TFIFKF iterator): Likewise.
	(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
	VSX insn support for negate, absolute value, and negative absolute
	value.
	(ieee_128bit_vsx_neg<mode>2): Likewise.
	(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
	(ieee_128bit_vsx_abs<mode>2): Likewise.
	(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_nabs<mode>2): Likewise.
	(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
	(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
	floating point in VSX registers.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.
	(unpackv1ti): Likewise.
	(unpack<mode>, FMOVE128_VSX iterator): Likewise.
	(packv1ti): Likewise.
	(pack<mode>, FMOVE128_VSX iterator): Likewise.
	(extenddftf2): Add support for IEEE 128-bit floating point in VSX
	registers.
	(extenddftf2_internal): Likewise.
	(trunctfdf2): Likewise.
	(trunctfdf2_internal2): Likewise.
	(fix_trunc_helper): Likewise.
	(fix_trunctfdi2"): Likewise.
	(floatditf2): Likewise.
	(floatuns<mode>tf2): Likewise.
	(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
	(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(float<SDI:mode><IFKF:mode>2): Likewise.
	(floatuns<SDI:mode><IFKF:mode>2): Likewise.

From-SVN: r227230
parent 66c182be
2015-08-26 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
Add declaration.
* config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
comment.
(rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
floating point in VSX registers.
(rs6000_output_move_128bit): Always print out the set insn if we
can't generate an appropriate 128-bit move.
(rs6000_generate_compare): Add support for IEEE 128-bit floating
point in VSX registers comparisons.
(rs6000_expand_float128_convert): Likewise.
* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
predicate for only GPR hard registers.
* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
modes to iterators. Add new iterators for moving 128-bit values in
scalar FPR registers and VSX registers.
(FMOVE128): Likewise.
(FMOVE128_FPR): Likewise.
(FMOVE128_GPR): Likewise.
(FMOVE128_VSX): Likewise.
(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
in VSX registers.
(IFKF): Likewise.
(IBM128): Likewise.
(TFIFKF): Likewise.
(RELOAD): Add IEEE 128-bit floating point modes.
(signbittf2): Convert TF insns to add support for new IEEE 128-bit
floating point in VSX registers modes.
(signbit<mode>2, IBM128 iterator): Likewise.
(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
(negtf2): Likewise.
(neg<mode>2, TFIFKF iterator): Likewise.
(negtf2_internal): Likewise.
(abstf2): Likewise.
(abs<mode>2, TFIFKF iterator): Likewise.
(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
VSX insn support for negate, absolute value, and negative absolute
value.
(ieee_128bit_vsx_neg<mode>2): Likewise.
(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
(ieee_128bit_vsx_abs<mode>2): Likewise.
(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
(ieee_128bit_vsx_nabs<mode>2): Likewise.
(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
floating point in VSX registers.
(unpack<mode>_dm): Likewise.
(unpack<mode>_nodm): Likewise.
(pack<mode>): Likewise.
(unpackv1ti): Likewise.
(unpack<mode>, FMOVE128_VSX iterator): Likewise.
(packv1ti): Likewise.
(pack<mode>, FMOVE128_VSX iterator): Likewise.
(extenddftf2): Add support for IEEE 128-bit floating point in VSX
registers.
(extenddftf2_internal): Likewise.
(trunctfdf2): Likewise.
(trunctfdf2_internal2): Likewise.
(fix_trunc_helper): Likewise.
(fix_trunctfdi2"): Likewise.
(floatditf2): Likewise.
(floatuns<mode>tf2): Likewise.
(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
(float<SDI:mode><IFKF:mode>2): Likewise.
(floatuns<SDI:mode><IFKF:mode>2): Likewise.
2015-08-26 Renlin Li <renlin.li@arm.com> 2015-08-26 Renlin Li <renlin.li@arm.com>
* config/aarch64/aarch64.md (*aarch64_bfi<GPI:mode><ALLX:mode>4): New. * config/aarch64/aarch64.md (*aarch64_bfi<GPI:mode><ALLX:mode>4): New.
......
...@@ -239,6 +239,25 @@ ...@@ -239,6 +239,25 @@
return INT_REGNO_P (REGNO (op)); return INT_REGNO_P (REGNO (op));
}) })
;; Like int_reg_operand, but don't return true for pseudo registers
(define_predicate "int_reg_operand_not_pseudo"
(match_operand 0 "register_operand")
{
if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
if (!REG_P (op))
return 0;
if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
return 0;
return INT_REGNO_P (REGNO (op));
})
;; Like int_reg_operand, but only return true for base registers ;; Like int_reg_operand, but only return true for base registers
(define_predicate "base_reg_operand" (define_predicate "base_reg_operand"
(match_operand 0 "int_reg_operand") (match_operand 0 "int_reg_operand")
......
...@@ -54,6 +54,7 @@ extern const char *output_vec_const_move (rtx *); ...@@ -54,6 +54,7 @@ extern const char *output_vec_const_move (rtx *);
extern const char *rs6000_output_move_128bit (rtx *); extern const char *rs6000_output_move_128bit (rtx *);
extern bool rs6000_move_128bit_ok_p (rtx []); extern bool rs6000_move_128bit_ok_p (rtx []);
extern bool rs6000_split_128bit_ok_p (rtx []); extern bool rs6000_split_128bit_ok_p (rtx []);
extern void rs6000_expand_float128_convert (rtx, rtx, bool);
extern void rs6000_expand_vector_init (rtx, rtx); extern void rs6000_expand_vector_init (rtx, rtx);
extern void paired_expand_vector_init (rtx, rtx); extern void paired_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, int); extern void rs6000_expand_vector_set (rtx, rtx, int);
......
...@@ -8485,7 +8485,7 @@ rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode) ...@@ -8485,7 +8485,7 @@ rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode)
during expand. */ during expand. */
gcc_assert (!reload_in_progress && !lra_in_progress && !reload_completed); gcc_assert (!reload_in_progress && !lra_in_progress && !reload_completed);
/* Use V2DImode to do swaps of types with 128-bit scalare parts (TImode, /* Use V2DImode to do swaps of types with 128-bit scalar parts (TImode,
V1TImode). */ V1TImode). */
if (mode == TImode || mode == V1TImode) if (mode == TImode || mode == V1TImode)
{ {
...@@ -18542,6 +18542,8 @@ rs6000_cannot_change_mode_class (machine_mode from, ...@@ -18542,6 +18542,8 @@ rs6000_cannot_change_mode_class (machine_mode from,
{ {
unsigned to_nregs = hard_regno_nregs[FIRST_FPR_REGNO][to]; unsigned to_nregs = hard_regno_nregs[FIRST_FPR_REGNO][to];
unsigned from_nregs = hard_regno_nregs[FIRST_FPR_REGNO][from]; unsigned from_nregs = hard_regno_nregs[FIRST_FPR_REGNO][from];
bool to_float128_vector_p = FLOAT128_VECTOR_P (to);
bool from_float128_vector_p = FLOAT128_VECTOR_P (from);
/* Don't allow 64-bit types to overlap with 128-bit types that take a /* Don't allow 64-bit types to overlap with 128-bit types that take a
single register under VSX because the scalar part of the register single register under VSX because the scalar part of the register
...@@ -18550,7 +18552,10 @@ rs6000_cannot_change_mode_class (machine_mode from, ...@@ -18550,7 +18552,10 @@ rs6000_cannot_change_mode_class (machine_mode from,
IEEE floating point can't overlap, and neither can small IEEE floating point can't overlap, and neither can small
values. */ values. */
if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode)) if (to_float128_vector_p && from_float128_vector_p)
return false;
else if (to_float128_vector_p || from_float128_vector_p)
return true; return true;
/* TDmode in floating-mode registers must always go into a register /* TDmode in floating-mode registers must always go into a register
...@@ -18578,6 +18583,8 @@ rs6000_cannot_change_mode_class (machine_mode from, ...@@ -18578,6 +18583,8 @@ rs6000_cannot_change_mode_class (machine_mode from,
if (TARGET_E500_DOUBLE if (TARGET_E500_DOUBLE
&& ((((to) == DFmode) + ((from) == DFmode)) == 1 && ((((to) == DFmode) + ((from) == DFmode)) == 1
|| (((to) == TFmode) + ((from) == TFmode)) == 1 || (((to) == TFmode) + ((from) == TFmode)) == 1
|| (((to) == IFmode) + ((from) == IFmode)) == 1
|| (((to) == KFmode) + ((from) == KFmode)) == 1
|| (((to) == DDmode) + ((from) == DDmode)) == 1 || (((to) == DDmode) + ((from) == DDmode)) == 1
|| (((to) == TDmode) + ((from) == TDmode)) == 1 || (((to) == TDmode) + ((from) == TDmode)) == 1
|| (((to) == DImode) + ((from) == DImode)) == 1)) || (((to) == DImode) + ((from) == DImode)) == 1))
...@@ -18774,13 +18781,7 @@ rs6000_output_move_128bit (rtx operands[]) ...@@ -18774,13 +18781,7 @@ rs6000_output_move_128bit (rtx operands[])
return output_vec_const_move (operands); return output_vec_const_move (operands);
} }
if (TARGET_DEBUG_ADDR) fatal_insn ("Bad 128-bit move", gen_rtx_SET (dest, src));
{
fprintf (stderr, "\n===== Bad 128 bit move:\n");
debug_rtx (gen_rtx_SET (dest, src));
}
gcc_unreachable ();
} }
/* Validate a 128-bit move. */ /* Validate a 128-bit move. */
...@@ -19824,6 +19825,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19824,6 +19825,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
break; break;
case TFmode: case TFmode:
case IFmode:
case KFmode:
cmp = (flag_finite_math_only && !flag_trapping_math) cmp = (flag_finite_math_only && !flag_trapping_math)
? gen_tsttfeq_gpr (compare_result, op0, op1) ? gen_tsttfeq_gpr (compare_result, op0, op1)
: gen_cmptfeq_gpr (compare_result, op0, op1); : gen_cmptfeq_gpr (compare_result, op0, op1);
...@@ -19851,6 +19854,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19851,6 +19854,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
break; break;
case TFmode: case TFmode:
case IFmode:
case KFmode:
cmp = (flag_finite_math_only && !flag_trapping_math) cmp = (flag_finite_math_only && !flag_trapping_math)
? gen_tsttfgt_gpr (compare_result, op0, op1) ? gen_tsttfgt_gpr (compare_result, op0, op1)
: gen_cmptfgt_gpr (compare_result, op0, op1); : gen_cmptfgt_gpr (compare_result, op0, op1);
...@@ -19878,6 +19883,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19878,6 +19883,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
break; break;
case TFmode: case TFmode:
case IFmode:
case KFmode:
cmp = (flag_finite_math_only && !flag_trapping_math) cmp = (flag_finite_math_only && !flag_trapping_math)
? gen_tsttflt_gpr (compare_result, op0, op1) ? gen_tsttflt_gpr (compare_result, op0, op1)
: gen_cmptflt_gpr (compare_result, op0, op1); : gen_cmptflt_gpr (compare_result, op0, op1);
...@@ -19915,6 +19922,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19915,6 +19922,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
break; break;
case TFmode: case TFmode:
case IFmode:
case KFmode:
cmp = (flag_finite_math_only && !flag_trapping_math) cmp = (flag_finite_math_only && !flag_trapping_math)
? gen_tsttfeq_gpr (compare_result2, op0, op1) ? gen_tsttfeq_gpr (compare_result2, op0, op1)
: gen_cmptfeq_gpr (compare_result2, op0, op1); : gen_cmptfeq_gpr (compare_result2, op0, op1);
...@@ -19937,14 +19946,117 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19937,14 +19946,117 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
emit_insn (cmp); emit_insn (cmp);
} }
/* IEEE 128-bit support in VSX registers. The comparison function (__cmpkf2)
returns 0..15 that is laid out the same way as the PowerPC CR register
would for a normal floating point comparison. */
else if (FLOAT128_IEEE_P (mode))
{
rtx and_reg = gen_reg_rtx (SImode);
rtx dest = gen_reg_rtx (SImode);
rtx libfunc = optab_libfunc (cmp_optab, mode);
HOST_WIDE_INT mask_value = 0;
/* Values that __cmpkf2 returns. */
#define PPC_CMP_UNORDERED 0x1 /* isnan (a) || isnan (b). */
#define PPC_CMP_EQUAL 0x2 /* a == b. */
#define PPC_CMP_GREATER_THEN 0x4 /* a > b. */
#define PPC_CMP_LESS_THEN 0x8 /* a < b. */
switch (code)
{
case EQ:
mask_value = PPC_CMP_EQUAL;
code = NE;
break;
case NE:
mask_value = PPC_CMP_EQUAL;
code = EQ;
break;
case GT:
mask_value = PPC_CMP_GREATER_THEN;
code = NE;
break;
case GE:
mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
code = NE;
break;
case LT:
mask_value = PPC_CMP_LESS_THEN;
code = NE;
break;
case LE:
mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
code = NE;
break;
case UNLE:
mask_value = PPC_CMP_GREATER_THEN;
code = EQ;
break;
case UNLT:
mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
code = EQ;
break;
case UNGE:
mask_value = PPC_CMP_LESS_THEN;
code = EQ;
break;
case UNGT:
mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
code = EQ;
break;
case UNEQ:
mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
code = NE;
case LTGT:
mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
code = EQ;
break;
case UNORDERED:
mask_value = PPC_CMP_UNORDERED;
code = NE;
break;
case ORDERED:
mask_value = PPC_CMP_UNORDERED;
code = EQ;
break;
default:
gcc_unreachable ();
}
gcc_assert (mask_value != 0);
and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2,
op0, mode, op1, mode);
emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value)));
compare_result = gen_reg_rtx (CCmode);
comp_mode = CCmode;
emit_insn (gen_rtx_SET (compare_result,
gen_rtx_COMPARE (comp_mode, dest, const0_rtx)));
}
else else
{ {
/* Generate XLC-compatible TFmode compare as PARALLEL with extra /* Generate XLC-compatible TFmode compare as PARALLEL with extra
CLOBBERs to match cmptf_internal2 pattern. */ CLOBBERs to match cmptf_internal2 pattern. */
if (comp_mode == CCFPmode && TARGET_XL_COMPAT if (comp_mode == CCFPmode && TARGET_XL_COMPAT
&& GET_MODE (op0) == TFmode && FLOAT128_IBM_P (GET_MODE (op0))
&& !TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS)
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
emit_insn (gen_rtx_PARALLEL (VOIDmode, emit_insn (gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (10, gen_rtvec (10,
gen_rtx_SET (compare_result, gen_rtx_SET (compare_result,
...@@ -19977,6 +20089,7 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -19977,6 +20089,7 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
/* Some kinds of FP comparisons need an OR operation; /* Some kinds of FP comparisons need an OR operation;
under flag_finite_math_only we don't bother. */ under flag_finite_math_only we don't bother. */
if (FLOAT_MODE_P (mode) if (FLOAT_MODE_P (mode)
&& !FLOAT128_IEEE_P (mode)
&& !flag_finite_math_only && !flag_finite_math_only
&& !(TARGET_HARD_FLOAT && !TARGET_FPRS) && !(TARGET_HARD_FLOAT && !TARGET_FPRS)
&& (code == LE || code == GE && (code == LE || code == GE
...@@ -20016,6 +20129,68 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) ...@@ -20016,6 +20129,68 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
} }
/* Expand floating point conversion to/from __float128 and __ibm128. */
void
rs6000_expand_float128_convert (rtx dest, rtx src, bool unsigned_p)
{
machine_mode dest_mode = GET_MODE (dest);
machine_mode src_mode = GET_MODE (src);
convert_optab cvt = unknown_optab;
rtx libfunc = NULL_RTX;
rtx dest2;
if (dest_mode == src_mode)
gcc_unreachable ();
if (FLOAT128_IEEE_P (dest_mode))
{
if (src_mode == SFmode
|| src_mode == DFmode
|| FLOAT128_IBM_P (src_mode))
cvt = sext_optab;
else if (GET_MODE_CLASS (src_mode) == MODE_INT)
cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
else if (FLOAT128_IEEE_P (src_mode))
emit_move_insn (dest, gen_lowpart (dest_mode, src));
else
gcc_unreachable ();
}
else if (FLOAT128_IEEE_P (src_mode))
{
if (dest_mode == SFmode
|| dest_mode == DFmode
|| FLOAT128_IBM_P (dest_mode))
cvt = trunc_optab;
else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
cvt = (unsigned_p) ? ufix_optab : sfix_optab;
else
gcc_unreachable ();
}
else
gcc_unreachable ();
gcc_assert (cvt != unknown_optab);
libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
gcc_assert (libfunc != NULL_RTX);
dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
src_mode);
gcc_assert (dest != NULL_RTX);
if (!rtx_equal_p (dest, dest2))
emit_move_insn (dest, dest2);
return;
}
/* Emit the RTL for an sISEL pattern. */ /* Emit the RTL for an sISEL pattern. */
void void
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