S/390: Rearrange fixuns_trunc pattern definitions.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 24 Mar 2017 13:59:13 +0000 (13:59 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 24 Mar 2017 13:59:13 +0000 (13:59 +0000)
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

gcc/ChangeLog
gcc/config/s390/s390.md

index 6e203264d1dfc734426638aec94d59e693031ad2..4efabf0d81ed99b7f9cc6b5d6c0f295d84bff8df 100644 (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
index e72d5be36ccb6ca80a49fd858986701c6362f81e..d4d3781d3a7f629ed8006904181483ee2020eb3e 100644 (file)
   "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"