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:
parent
77c585ca57
commit
9751ad6e9b
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue