[PATCH 3/9] S/390: Get rid of Y constraint in rotate patterns.

Andreas Krebbel krebbel@linux.vnet.ibm.com
Tue Feb 23 14:33:00 GMT 2016


This patch introduces substitution patterns to add PLUS const_int, and
AND operands to patterns and uses this to rewrite the existing rotate
pattern.

gcc/ChangeLog:

	* config/s390/predicates.md (const_int_6bitset_operand): New
        predicates.
	* config/s390/s390.md: Include subst.md.
	("rotl<mode>3"): New expander.
	("rotl<mode>3", "*rotl<mode>3_and"): Merge insn definitions into
	...
	("*rotl<mode>3<addr_style_op><masked_op>"): New insn definition.
	* config/s390/subst.md: New file.
---
 gcc/config/s390/predicates.md |  4 +++
 gcc/config/s390/s390.c        | 23 +++++++++++----
 gcc/config/s390/s390.md       | 34 +++++++++++-----------
 gcc/config/s390/subst.md      | 67 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 105 insertions(+), 23 deletions(-)
 create mode 100644 gcc/config/s390/subst.md

diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index cbc8092..9e91b5c 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -115,6 +115,10 @@
   return true;
 })
 
+; An integer operand with the lowest order 6 bit all ones.
+(define_predicate "const_int_6bitset_operand"
+ (and (match_code "const_int")
+      (match_test "(INTVAL (op) & 63) == 63")))
 (define_predicate "nonzero_shift_count_operand"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)")))
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index cd53b15..43219dd 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -2994,18 +2994,18 @@ s390_decompose_address (rtx addr, struct s390_address *out)
 bool
 s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
 {
-  HOST_WIDE_INT off = 0;
+  rtx off = NULL_RTX;
 
   /* We can have an integer constant, an address register,
      or a sum of the two.  */
-  if (GET_CODE (op) == CONST_INT)
+  if (CONST_SCALAR_INT_P (op))
     {
-      off = INTVAL (op);
+      off = op;
       op = NULL_RTX;
     }
-  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+  if (op && GET_CODE (op) == PLUS && CONST_SCALAR_INT_P (XEXP (op, 1)))
     {
-      off = INTVAL (XEXP (op, 1));
+      off = XEXP (op, 1);
       op = XEXP (op, 0);
     }
   while (op && GET_CODE (op) == SUBREG)
@@ -3015,7 +3015,18 @@ s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
     return false;
 
   if (offset)
-    *offset = off;
+    {
+      if (off == NULL_RTX)
+	*offset = 0;
+      else if (CONST_INT_P (off))
+	*offset = INTVAL (off);
+      else if (CONST_WIDE_INT_P (off))
+	/* The offset will anyway be cut down to 12 bits so take just
+	   the lowest order chunk of the wide int.  */
+	*offset = CONST_WIDE_INT_ELT (off, 0);
+      else
+	gcc_unreachable ();
+    }
   if (base)
     *base = op;
 
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index b878ec2..9703a30 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -741,6 +741,8 @@
 (define_mode_attr asm_fcmp [(CCVEQ "e") (CCVFH "h") (CCVFHE "he")])
 (define_mode_attr insn_cmp [(CCVEQ "eq") (CCVH "h") (CCVHU "hl") (CCVFH "h") (CCVFHE "he")])
 
+;; Subst pattern definitions
+(include "subst.md")
 
 (include "vector.md")
 
@@ -8360,28 +8362,26 @@
 ; rotl(di|si)3 instruction pattern(s).
 ;
 
-; rll, rllg
-(define_insn "rotl<mode>3"
-  [(set (match_operand:GPR 0 "register_operand" "=d")
-	(rotate:GPR (match_operand:GPR 1 "register_operand" "d")
-		    (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+(define_expand "rotl<mode>3"
+  [(set (match_operand:GPR 0 "register_operand" "")
+        (rotate:GPR (match_operand:GPR 1 "register_operand" "")
+		    (match_operand:SI 2 "nonmemory_operand" "")))]
   "TARGET_CPU_ZARCH"
-  "rll<g>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RSE")
-   (set_attr "atype"    "reg")
-   (set_attr "z10prop" "z10_super_E1")])
+  "")
 
 ; rll, rllg
-(define_insn "*rotl<mode>3_and"
-  [(set (match_operand:GPR 0 "register_operand" "=d")
-	(rotate:GPR (match_operand:GPR 1 "register_operand" "d")
-		    (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
-			    (match_operand:SI 3 "const_int_operand"   "n"))))]
-  "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
-  "rll<g>\t%0,%1,%Y2"
+(define_insn "*rotl<mode>3<addr_style_op><masked_op>"
+  [(set (match_operand:GPR             0 "register_operand" "=d,d")
+	(rotate:GPR (match_operand:GPR 1 "register_operand"  "d,d")
+		    (match_operand:SI  2 "nonmemory_operand" "a,n")))]
+  "TARGET_CPU_ZARCH"
+  "@
+   rll<g>\t%0,%1,<addr_style_op_op3>(%2)
+   rll<g>\t%0,%1,%Y2"
   [(set_attr "op_type"  "RSE")
    (set_attr "atype"    "reg")
-   (set_attr "z10prop" "z10_super_E1")])
+   (set_attr "enabled"  "*,<addr_style_op_enabled>")
+   (set_attr "z10prop"  "z10_super_E1")])
 
 
 ;;
diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md
new file mode 100644
index 0000000..8443c69
--- /dev/null
+++ b/gcc/config/s390/subst.md
@@ -0,0 +1,67 @@
+;;- Machine description for GNU compiler -- S/390 / zSeries version.
+;;  Subst patterns.
+;;  Copyright (C) 2016 Free Software Foundation, Inc.
+;;  Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it under
+;; the terms of the GNU General Public License as published by the Free
+;; Software Foundation; either version 3, or (at your option) any later
+;; version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+;; for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_code_iterator SUBST [ashift lshiftrt rotate])
+
+; This expands an register/immediate operand to a register+immediate
+; operand to draw advantage of the address style operand format
+; providing a addition for free.
+(define_subst "addr_style_op_subst"
+  [(set (match_operand:DSI 0 "" "")
+        (SUBST:DSI (match_operand:DSI 1 "" "")
+		   (match_operand:SI 2 "" "")))]
+  ""
+  [(set (match_dup 0)
+        (SUBST:DSI (match_dup 1)
+		   (plus:SI (match_operand:SI 2 "register_operand" "a")
+			    (match_operand 3 "const_int_operand"   "n"))))])
+
+; Use this in the insn name.
+(define_subst_attr "addr_style_op"     "addr_style_op_subst" "" "_plus")
+
+; In the subst pattern the additional const int operand will be used
+; as displacement.  In the normal version the displacements stays just
+; 0.
+(define_subst_attr "addr_style_op_op3" "addr_style_op_subst" "0" "%Y3")
+
+; The constraints for the second alternative are ok.  However, the
+; output template is not.  We simply disable the alternative.
+; Alternatively we could also adjust the output template with a
+; subst_attr.
+(define_subst_attr "addr_style_op_enabled" "addr_style_op_subst" "*" "0")
+
+
+; This substitution adds an explicit AND operation to the second
+; operand.  This way previous operations on the now masked out bits
+; might get optimized away.
+(define_subst "masked_op_subst"
+  [(set (match_operand:DSI 0 ""           "")
+        (SUBST:DSI (match_operand:DSI 1 "" "")
+		   (match_operand:SI  2 "" "")))]
+  ""
+  [(set (match_dup 0)
+        (SUBST:DSI (match_dup 1)
+		   (and:SI (match_dup 2)
+			   (match_operand:SI 3 "const_int_6bitset_operand" ""))))])
+
+; Use this in the insn name.
+(define_subst_attr "masked_op" "masked_op_subst" "" "_and")
+
-- 
1.9.1



More information about the Gcc-patches mailing list