[PATCH 08/16] S/390: Rearrange fixuns_trunc pattern definitions.

Andreas Krebbel krebbel@linux.vnet.ibm.com
Fri Mar 24 14:13:00 GMT 2017


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.
---
 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 fef571c..779101e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,23 @@
 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
 	instructions which are no longer used.
 	* config/s390/s390.c (s390_select_ccmode): Remove handling of
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index e72d5be..d4d3781 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"
-- 
2.9.1



More information about the Gcc-patches mailing list