From 9751ad6e9b79eeff55e7a81272be85dddb842e0f Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 24 Mar 2017 13:59:13 +0000 Subject: [PATCH] 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_trunc2") which then multiplexes to either the emulation variants *_emu or the hardware implementations. gcc/ChangeLog: 2017-03-24 Andreas Krebbel * config/s390/s390.md ("fixuns_truncdddi2", "fixuns_trunctddi2") ("fixuns_trunc2"): Merge into ... ("fixuns_trunc2"): New expander. ("fixuns_trunc2", "fixuns_truncsi2"): Rename expanders to ... ("fixuns_trunc2_emu") ("fixuns_truncdddi2_emu"): ... these. ("fixuns_truncsi2_emu"): New expander. ("*fixuns_truncdfdi2_z13"): Rename to ... ("*fixuns_truncdfdi2_vx"): ... this. From-SVN: r246451 --- gcc/ChangeLog | 18 +++ gcc/config/s390/s390.md | 253 +++++++++++++++++++++++----------------- 2 files changed, 161 insertions(+), 110 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6e203264d1d..4efabf0d81e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2017-03-24 Andreas Krebbel + + * config/s390/s390.md + ("fixuns_truncdddi2", "fixuns_trunctddi2") + ("fixuns_trunc2"): Merge into ... + ("fixuns_trunc2"): New expander. + + ("fixuns_trunc2", "fixuns_truncsi2"): + Rename expanders to ... + + ("fixuns_trunc2_emu") + ("fixuns_truncdddi2_emu"): ... these. + + ("fixuns_truncsi2_emu"): New expander. + + ("*fixuns_truncdfdi2_z13"): Rename to ... + ("*fixuns_truncdfdi2_vx"): ... this. + 2017-03-24 Andreas Krebbel * config/s390/2964.md: Remove the single element vector compare 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_trunc2" [(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 (mode) == MODE_DECIMAL_FLOAT + && mode == SImode) + FAIL; + emit_insn (gen_fixuns_trunc2_emu (operands[0], + operands[1])); DONE; } + + if (GET_MODE_CLASS (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_trunc2_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 (mode); + REAL_VALUE_TYPE cmp, sub; + + operands[1] = force_reg (mode, operands[1]); + real_2expN (&cmp, - 1, mode); + real_2expN (&sub, , mode); + + emit_cmp_and_jump_insns (operands[1], + const_double_from_real_value (cmp, mode), + LT, NULL_RTX, VOIDmode, 0, label1); + emit_insn (gen_sub3 (temp, operands[1], + const_double_from_real_value (sub, mode))); + emit_insn (gen_fix_trunc2_bfp (operands[0], temp, + GEN_INT (BFP_RND_TOWARD_MINF))); + emit_jump (label2); + + emit_label (label1); + emit_insn (gen_fix_trunc2_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_trunc2" +; 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 (mode); - REAL_VALUE_TYPE cmp, sub; - - operands[1] = force_reg (mode, operands[1]); - real_2expN (&cmp, - 1, mode); - real_2expN (&sub, , mode); - - emit_cmp_and_jump_insns (operands[1], - const_double_from_real_value (cmp, mode), - LT, NULL_RTX, VOIDmode, 0, label1); - emit_insn (gen_sub3 (temp, operands[1], - const_double_from_real_value (sub, mode))); - emit_insn (gen_fix_trunc2_bfp (operands[0], temp, - GEN_INT (BFP_RND_TOWARD_MINF))); - emit_jump (label2); - emit_label (label1); - emit_insn (gen_fix_trunc2_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_truncsi2" +; Just a dummy to make the code in the first expander a bit easier. +(define_expand "fixuns_truncsi2_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_trunc2_z196" -- 2.30.2