S/390: Rearrange fixuns_trunc pattern definitions.

This reworks the fixuns_trunc* patterns a bit which got quite confusing
after adding z13 support.  Now we just have a single RTL standard name
expander definition ("fixuns_trunc<FP:mode><GPR:mode>2") which then
multiplexes to either the emulation variants *_emu or the hardware
implementations.

gcc/ChangeLog:

2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

	* config/s390/s390.md
	("fixuns_truncdddi2", "fixuns_trunctddi2")
	("fixuns_trunc<BFP:mode><GPR:mode>2"): Merge into ...
	("fixuns_trunc<FP:mode><GPR:mode>2"): New expander.

	("fixuns_trunc<BFP:mode><GPR:mode>2", "fixuns_trunc<mode>si2"):
	Rename expanders to ...

	("fixuns_trunc<BFP:mode><GPR:mode>2_emu")
	("fixuns_truncdddi2_emu"): ... these.

	("fixuns_trunc<mode>si2_emu"): New expander.

	("*fixuns_truncdfdi2_z13"): Rename to ...
	("*fixuns_truncdfdi2_vx"): ... this.

From-SVN: r246451
This commit is contained in:
Andreas Krebbel 2017-03-24 13:59:13 +00:00 committed by Andreas Krebbel
parent 77c585ca57
commit 9751ad6e9b
2 changed files with 159 additions and 108 deletions

View File

@ -1,3 +1,21 @@
2017-03-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/s390/s390.md
("fixuns_truncdddi2", "fixuns_trunctddi2")
("fixuns_trunc<BFP:mode><GPR:mode>2"): Merge into ...
("fixuns_trunc<FP:mode><GPR:mode>2"): New expander.
("fixuns_trunc<BFP:mode><GPR:mode>2", "fixuns_trunc<mode>si2"):
Rename expanders to ...
("fixuns_trunc<BFP:mode><GPR:mode>2_emu")
("fixuns_truncdddi2_emu"): ... these.
("fixuns_trunc<mode>si2_emu"): New expander.
("*fixuns_truncdfdi2_z13"): Rename to ...
("*fixuns_truncdfdi2_vx"): ... this.
2017-03-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/s390/2964.md: Remove the single element vector compare

View File

@ -4735,152 +4735,185 @@
"operands[2] = gen_lowpart (QImode, operands[0]);")
;
; fixuns_trunc(dd|td)di2 instruction pattern(s).
; fixuns_trunc(dd|td|sf|df|tf)(si|di)2 expander
;
(define_expand "fixuns_truncdddi2"
; This is the only entry point for fixuns_trunc. It multiplexes the
; expansion to either the *_emu expanders below for pre z196 machines
; or emits the default pattern otherwise.
(define_expand "fixuns_trunc<FP:mode><GPR:mode>2"
[(parallel
[(set (match_operand:GPR 0 "register_operand" "")
(unsigned_fix:GPR (match_operand:FP 1 "register_operand" "")))
(unspec:GPR [(match_dup 2)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"TARGET_HARD_FLOAT"
{
if (!TARGET_Z196)
{
/* We don't provide emulation for TD|DD->SI. */
if (GET_MODE_CLASS (<FP:MODE>mode) == MODE_DECIMAL_FLOAT
&& <GPR:MODE>mode == SImode)
FAIL;
emit_insn (gen_fixuns_trunc<FP:mode><GPR:mode>2_emu (operands[0],
operands[1]));
DONE;
}
if (GET_MODE_CLASS (<FP:MODE>mode) == MODE_DECIMAL_FLOAT)
operands[2] = GEN_INT (DFP_RND_TOWARD_0);
else
operands[2] = GEN_INT (BFP_RND_TOWARD_0);
})
; (sf|df|tf)->unsigned (si|di)
; Emulate the unsigned conversion with the signed version for pre z196
; machines.
(define_expand "fixuns_trunc<BFP:mode><GPR:mode>2_emu"
[(parallel
[(set (match_operand:GPR 0 "register_operand" "")
(unsigned_fix:GPR (match_operand:BFP 1 "register_operand" "")))
(unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"!TARGET_Z196 && TARGET_HARD_FLOAT"
{
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (<BFP:MODE>mode);
REAL_VALUE_TYPE cmp, sub;
operands[1] = force_reg (<BFP:MODE>mode, operands[1]);
real_2expN (&cmp, <GPR:bitsize> - 1, <BFP:MODE>mode);
real_2expN (&sub, <GPR:bitsize>, <BFP:MODE>mode);
emit_cmp_and_jump_insns (operands[1],
const_double_from_real_value (cmp, <BFP:MODE>mode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_sub<BFP:mode>3 (temp, operands[1],
const_double_from_real_value (sub, <BFP:MODE>mode)));
emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0], temp,
GEN_INT (BFP_RND_TOWARD_MINF)));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0],
operands[1],
GEN_INT (BFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
})
; dd->unsigned di
; Emulate the unsigned conversion with the signed version for pre z196
; machines.
(define_expand "fixuns_truncdddi2_emu"
[(parallel
[(set (match_operand:DI 0 "register_operand" "")
(unsigned_fix:DI (match_operand:DD 1 "register_operand" "")))
(unspec:DI [(const_int DFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"TARGET_HARD_DFP"
"!TARGET_Z196 && TARGET_HARD_DFP"
{
if (!TARGET_Z196)
{
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
/* 2^63 can't be represented as 64bit DFP number with full precision. The
solution is doing the check and the subtraction in TD mode and using a
TD -> DI convert afterwards. */
emit_insn (gen_extendddtd2 (temp, operands[1]));
temp = force_reg (TDmode, temp);
emit_cmp_and_jump_insns (temp,
const_double_from_real_value (cmp, TDmode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, temp,
const_double_from_real_value (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp,
GEN_INT (DFP_RND_TOWARD_MINF)));
emit_jump (label2);
/* 2^63 can't be represented as 64bit DFP number with full precision. The
solution is doing the check and the subtraction in TD mode and using a
TD -> DI convert afterwards. */
emit_insn (gen_extendddtd2 (temp, operands[1]));
temp = force_reg (TDmode, temp);
emit_cmp_and_jump_insns (temp,
const_double_from_real_value (cmp, TDmode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, temp,
const_double_from_real_value (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp,
GEN_INT (DFP_RND_TOWARD_MINF)));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_truncdddi2_dfp (operands[0], operands[1],
GEN_INT (DFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
}
emit_label (label1);
emit_insn (gen_fix_truncdddi2_dfp (operands[0], operands[1],
GEN_INT (DFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
})
(define_expand "fixuns_trunctddi2"
; td->unsigned di
; Emulate the unsigned conversion with the signed version for pre z196
; machines.
(define_expand "fixuns_trunctddi2_emu"
[(parallel
[(set (match_operand:DI 0 "register_operand" "")
(unsigned_fix:DI (match_operand:TD 1 "register_operand" "")))
(unspec:DI [(const_int DFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"TARGET_HARD_DFP"
"!TARGET_Z196 && TARGET_HARD_DFP"
{
if (!TARGET_Z196)
{
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
operands[1] = force_reg (TDmode, operands[1]);
decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
operands[1] = force_reg (TDmode, operands[1]);
decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
emit_cmp_and_jump_insns (operands[1],
const_double_from_real_value (cmp, TDmode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, operands[1],
const_double_from_real_value (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp,
GEN_INT (DFP_RND_TOWARD_MINF)));
emit_jump (label2);
emit_cmp_and_jump_insns (operands[1],
const_double_from_real_value (cmp, TDmode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, operands[1],
const_double_from_real_value (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp,
GEN_INT (DFP_RND_TOWARD_MINF)));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_trunctddi2_dfp (operands[0], operands[1],
GEN_INT (DFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
}
emit_label (label1);
emit_insn (gen_fix_trunctddi2_dfp (operands[0], operands[1],
GEN_INT (DFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
})
;
; fixuns_trunc(sf|df|tf)(si|di)2 and fix_trunc(sf|df|tf)(si|di)2
; instruction pattern(s).
;
(define_expand "fixuns_trunc<BFP:mode><GPR:mode>2"
[(parallel
[(set (match_operand:GPR 0 "register_operand" "")
(unsigned_fix:GPR (match_operand:BFP 1 "register_operand" "")))
(unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"TARGET_HARD_FLOAT"
{
if (!TARGET_Z196)
{
rtx_code_label *label1 = gen_label_rtx ();
rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (<BFP:MODE>mode);
REAL_VALUE_TYPE cmp, sub;
operands[1] = force_reg (<BFP:MODE>mode, operands[1]);
real_2expN (&cmp, <GPR:bitsize> - 1, <BFP:MODE>mode);
real_2expN (&sub, <GPR:bitsize>, <BFP:MODE>mode);
emit_cmp_and_jump_insns (operands[1],
const_double_from_real_value (cmp, <BFP:MODE>mode),
LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_sub<BFP:mode>3 (temp, operands[1],
const_double_from_real_value (sub, <BFP:MODE>mode)));
emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0], temp,
GEN_INT (BFP_RND_TOWARD_MINF)));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0],
operands[1], GEN_INT (BFP_RND_TOWARD_0)));
emit_label (label2);
DONE;
}
})
; fixuns_trunc(td|dd)si2 expander
(define_expand "fixuns_trunc<mode>si2"
; Just a dummy to make the code in the first expander a bit easier.
(define_expand "fixuns_trunc<mode>si2_emu"
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(unsigned_fix:SI (match_operand:DFP 1 "register_operand" "")))
(unspec:SI [(const_int DFP_RND_TOWARD_0)] UNSPEC_ROUND)
(unspec:DI [(const_int DFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
"TARGET_Z196 && TARGET_HARD_DFP"
"")
"!TARGET_Z196 && TARGET_HARD_DFP"
{
FAIL;
})
; fixuns_trunc(tf|df|sf|td|dd)(di|si)2 instruction patterns.
(define_insn "*fixuns_truncdfdi2_z13"
; df -> unsigned di
(define_insn "*fixuns_truncdfdi2_vx"
[(set (match_operand:DI 0 "register_operand" "=d,v")
(unsigned_fix:DI (match_operand:DF 1 "register_operand" "f,v")))
(unspec:DI [(match_operand:DI 2 "immediate_operand" "K,K")] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))]
"TARGET_VX && TARGET_HARD_FLOAT"
"@
clgdbr\t%0,%h2,%1,0
wclgdb\t%v0,%v1,0,%h2"
[(set_attr "op_type" "RRF,VRR")
(set_attr "type" "ftoi")])
"TARGET_VX && TARGET_HARD_FLOAT"
"@
clgdbr\t%0,%h2,%1,0
wclgdb\t%v0,%v1,0,%h2"
[(set_attr "op_type" "RRF,VRR")
(set_attr "type" "ftoi")])
; (dd|td|sf|df|tf)->unsigned (di|si)
; clfebr, clfdbr, clfxbr, clgebr, clgdbr, clgxbr
; clfdtr, clfxtr, clgdtr, clgxtr
(define_insn "*fixuns_trunc<FP:mode><GPR:mode>2_z196"