diff options
author | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-03-24 13:59:13 +0000 |
---|---|---|
committer | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-03-24 13:59:13 +0000 |
commit | 9335ea999bf0fc96b9a01c4a2620adaeef88c230 (patch) | |
tree | 1bfcbef3bf46dca78b0d4f6a139e9e7e2dc5f157 /gcc/config/s390/s390.md | |
parent | 29c098f6265106b08f71d4c40c3df3bfbca4bdfb (diff) | |
download | gcc-9335ea999bf0fc96b9a01c4a2620adaeef88c230.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@246451 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r-- | gcc/config/s390/s390.md | 253 |
1 files changed, 143 insertions, 110 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index e72d5be36cc..d4d3781d3a7 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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:DI 0 "register_operand" "") - (unsigned_fix:DI (match_operand:DD 1 "register_operand" ""))) - (unspec:DI [(const_int DFP_RND_TOWARD_0)] UNSPEC_ROUND) + [(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_DFP" + "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 (TDmode); - REAL_VALUE_TYPE cmp, sub; - - 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); - - emit_label (label1); - emit_insn (gen_fix_truncdddi2_dfp (operands[0], operands[1], - GEN_INT (DFP_RND_TOWARD_0))); - emit_label (label2); + /* 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; }) -(define_expand "fixuns_trunctddi2" +; 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:TD 1 "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" -{ - 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; - - 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_label (label1); - emit_insn (gen_fix_trunctddi2_dfp (operands[0], operands[1], - GEN_INT (DFP_RND_TOWARD_0))); - emit_label (label2); - DONE; - } + "!TARGET_Z196 && TARGET_HARD_DFP" +{ + 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 */ + + /* 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; }) -; -; fixuns_trunc(sf|df|tf)(si|di)2 and fix_trunc(sf|df|tf)(si|di)2 -; instruction pattern(s). -; +; td->unsigned di -(define_expand "fixuns_trunc<BFP:mode><GPR:mode>2" +; Emulate the unsigned conversion with the signed version for pre z196 +; machines. +(define_expand "fixuns_trunctddi2_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) + [(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_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; - } + "!TARGET_Z196 && TARGET_HARD_DFP" +{ + 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 */ + + 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; }) -; 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" |