This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S/390: Disallow SImode addresses in 64 bit


Hi,

the attached patch is an attempt to fix the problem reported here:

https://gcc.gnu.org/ml/gcc/2015-05/msg00305.html

The problem is that we have address style operands as shift count
operands.  In order to benefit from reloading e.g. for invalid base
registers (r0) we mark the respective constraint as extra memory
constraint.  This unfortunately also requires us to use Pmode.  In the
end the mode doesn't matter much since the instructions anyway use
only the lower 6 bits of the resulting count.

The patch does the following to make things work:

- expanding a shift count it is wrapped into a paradoxical subreg to
  Pmode + an AND masking only the relevant bits
- change the mode of shift count operands to Pmode
- disallow SImode in legitimate_address


The expectation is that all this folds away sooner or
later. Unfortunately there are cases where it doesn't work.  In CSE I
see constant shift counts not being folded since it refuses to
propagate const-int into SUBREGs for REG_EQUAL notes:

cse_process_notes_1:
...
    case SUBREG:
      {
	rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed);
	/* We don't substitute VOIDmode constants into these rtx,
	   since they would impede folding.  */
	if (GET_MODE (new_rtx) != VOIDmode)
	  validate_change (object, &XEXP (x, 0), new_rtx, 0);
	return x;
      }
...


Any ideas how this could be circumvented?


Bootstrapped and regression tested on various CPU levels with 31 and
64 bit.

Bye,

-Andreas-




gcc/ChangeLog:

2015-08-06  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

	* config/s390/predicates.md: New predicate
	shift_count_or_setmem_operand_expand.

	* config/s390/s390-protos.h: Add prototype
	s390_expand_masked_address_operand.

	* config/s390/s390.c (s390_decompose_address): Remove SImode from
	valid modes.
	(s390_expand_masked_address_operand): New function.

	* config/s390/s390.md ("rotl<mode>3"): Rename to insn definition
	as "*rotl<mode>3" and replace SI with P modes from shift count
	operand.  Add new expander as "rotl<mode>3".
	("<shift><mode>3", "ashr<mode>3", "tabort"): Use new predicate and do
	expansion via s390_expand_masked_address_operand.
	("*<shift><mode>3_and", "*ashr<mode>3_cc", "*ashr<mode>3_cconly")
	("*ashr<mode>3", "*ashr<mode>3_cc_and")
	("*ashr<mode>3_cconly_and", "*ashr<mode>3_and")
	("*tabort_1_<mode>"): Replace SI with P mode from shift count
	operand.
	("*tabort_1_add"): New insn_and_split definition.

	* config/s390/vector.md (selbits, selmask): New mode attribute
	definitions.
	("vec_set<mode>"): Use new predicate and do expansion via
	s390_expand_masked_address_operand.
	("*vec_set<mode>"): Replace DI with P mode for shift count
	operand.
	("*vec_set<mode>_and", "*vec_extract<mode>_and")
	("*rotl<mode>3_and", "*ashl<mode>3_and", "*ashr<mode>3_and")
	("*lshr<mode>3_and"): New insn definition.
	("vec_extract<mode>", "rotl<mode>3", "ashl<mode>3", "ashr<mode>3")
	("lshr<mode>3", ): Renamed to ...
	("*vec_extract<mode>", "*rotl<mode>3", "*ashl<mode>3")
	("*ashr<mode>3", "*lshr<mode>3"): ... this.  Mode of shift
	count operand set to Pmode.
	("vec_extract<mode>", "rotl<mode>3", "ashl<mode>3")
	("ashr<mode>3","lshr<mode>3"): New expander
	definitions.

	* config/s390/vx-builtins.md: ("vec_insert<mode>")
	("vec_promote<mode>"): Use new predicate and do expansion via
	s390_expand_masked_address_operand.


diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index eeaf1ae..967c8a9 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -81,7 +81,13 @@
 
 ;; Return true if OP is a valid operand as scalar shift count or setmem.
 
-(define_predicate "shift_count_or_setmem_operand"
+;; In the end a shift count operand must always be Pmode (or VOIDmode)
+;; but during expansion we allow also SImode on 64 bit.  Otherwise it
+;; would be impossible to e.g. write the rotlsi3 expander which would
+;; require both DI and SI for the shift count depending on the
+;; addressing mode.
+
+(define_predicate "shift_count_or_setmem_operand_expand"
   (match_code "reg, subreg, plus, const_int")
 {
   HOST_WIDE_INT offset;
@@ -109,6 +115,22 @@
   return true;
 })
 
+;; Return true if OP is a valid operand as shift count or setmem in
+;; matching patterns.
+
+(define_predicate "shift_count_or_setmem_operand"
+  (and (match_code "reg, subreg, plus, const_int")
+       (match_operand 0 "shift_count_or_setmem_operand_expand"))
+{
+  /* The Y constraint used in conjunction with this predicate is an
+     extra memory constraint and therefore goes through
+     s390_decompose_address.  That's why we need Pmode mode here.  */
+  if (GET_MODE (op) != VOIDmode && GET_MODE (op) != Pmode)
+    return false;
+
+  return true;
+})
+
 (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-protos.h b/gcc/config/s390/s390-protos.h
index a8b8854..178671a 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -118,6 +118,7 @@ extern rtx_insn *s390_load_got (void);
 extern rtx s390_get_thread_pointer (void);
 extern void s390_emit_tpf_eh_return (rtx);
 extern bool s390_legitimate_address_without_index_p (rtx);
+extern rtx s390_expand_masked_address_operand (rtx, int);
 extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
 extern int s390_branch_condition_mask (rtx);
 extern int s390_compare_and_branch_condition_mask (rtx);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 7f609ba..082134a 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -2757,9 +2757,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
 	    return false;
 	  }
 
-      if (!REG_P (base)
-	  || (GET_MODE (base) != SImode
-	      && GET_MODE (base) != Pmode))
+      if (!REG_P (base) || GET_MODE (base) != Pmode)
 	return false;
 
       if (REGNO (base) == STACK_POINTER_REGNUM
@@ -2805,9 +2803,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
 	    return false;
 	  }
 
-      if (!REG_P (indx)
-	  || (GET_MODE (indx) != SImode
-	      && GET_MODE (indx) != Pmode))
+      if (!REG_P (indx) || GET_MODE (indx) != Pmode)
 	return false;
 
       if (REGNO (indx) == STACK_POINTER_REGNUM
@@ -2926,6 +2922,34 @@ s390_decompose_address (rtx addr, struct s390_address *out)
   return true;
 }
 
+/* Convert the shift count operand OP to Pmode under the assumption
+   that only the NUM_MASK_BITS lower significant bits are really
+   used.  */
+rtx
+s390_expand_masked_address_operand (rtx op, int num_mask_bits)
+{
+  gcc_assert (GET_MODE (op) == VOIDmode
+	      || GET_MODE_SIZE (GET_MODE (op)) <= GET_MODE_SIZE (Pmode));
+
+  if (GET_MODE (op) == VOIDmode)
+    return op;
+
+  if (GET_MODE (op) != Pmode)
+    {
+      /* In case we anyway only need at most the bits of the smaller
+	 mode we do not need to zero-extend the shift count.  */
+      if (num_mask_bits <= GET_MODE_BITSIZE (GET_MODE (op)))
+	op = simplify_gen_subreg (Pmode, op, GET_MODE (op), 0);
+      else
+	op = convert_to_mode (Pmode, op, true);
+    }
+
+  if (num_mask_bits < GET_MODE_BITSIZE (Pmode))
+    op = gen_rtx_AND (Pmode, op,
+		      GEN_INT ((HOST_WIDE_INT_1U << num_mask_bits) - 1));
+  return op;
+}
+
 /* Decompose a RTL expression OP for a shift count into its components,
    and return the base register in BASE and the offset in OFFSET.
 
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index b23973e..959ca8cb 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -8276,11 +8276,20 @@
 ; rotl(di|si)3 instruction pattern(s).
 ;
 
+(define_expand "rotl<mode>3"
+  [(set (match_operand:GPR 0 "register_operand" "")
+	(rotate:GPR (match_operand:GPR 1 "register_operand" "")
+		    (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+  "TARGET_CPU_ZARCH"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
+
 ; rll, rllg
-(define_insn "rotl<mode>3"
+(define_insn "*rotl<GPR:mode>3_<P:mode>"
   [(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")))]
+		    (match_operand:P   2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_CPU_ZARCH"
   "rll<g>\t%0,%1,%Y2"
   [(set_attr "op_type"  "RSE")
@@ -8288,11 +8297,11 @@
    (set_attr "z10prop" "z10_super_E1")])
 
 ; rll, rllg
-(define_insn "*rotl<mode>3_and"
+(define_insn "*rotl<mode>3_and_<P:mode>"
   [(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"))))]
+		    (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+			   (match_operand:P 3 "const_int_operand"   "n"))))]
   "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
   "rll<g>\t%0,%1,%Y2"
   [(set_attr "op_type"  "RSE")
@@ -8310,10 +8319,12 @@
 
 (define_expand "<shift><mode>3"
   [(set (match_operand:DSI 0 "register_operand" "")
-        (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
-                   (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
+    (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
+	       (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
   ""
-  "")
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
 
 ; sldl, srdl
 (define_insn "*<shift>di3_31"
@@ -8327,10 +8338,10 @@
    (set_attr "z196prop" "z196_cracked")])
 
 ; sll, srl, sllg, srlg, sllk, srlk
-(define_insn "*<shift><mode>3"
+(define_insn "*<shift><mode>3_<P:mode>"
   [(set (match_operand:GPR 0 "register_operand"                          "=d,d")
         (SHIFT:GPR (match_operand:GPR 1 "register_operand"             "<d0>,d")
-                   (match_operand:SI 2 "shift_count_or_setmem_operand"    "Y,Y")))]
+                   (match_operand:P   2 "shift_count_or_setmem_operand"   "Y,Y")))]
   ""
   "@
    s<lr>l<g>\t%0,<1>%Y2
@@ -8353,10 +8364,10 @@
 
 ; sll, srl, sllg, srlg, sllk, srlk
 (define_insn "*<shift><mode>3_and"
-  [(set (match_operand:GPR 0 "register_operand"                                 "=d,d")
-        (SHIFT:GPR (match_operand:GPR 1 "register_operand"                    "<d0>,d")
-                   (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand"   "Y,Y")
-			   (match_operand:SI 3 "const_int_operand"               "n,n"))))]
+  [(set (match_operand:GPR 0 "register_operand"                               "=d,d")
+        (SHIFT:GPR (match_operand:GPR      1 "register_operand"             "<d0>,d")
+                   (and:P (match_operand:P 2 "shift_count_or_setmem_operand"   "Y,Y")
+		          (match_operand:P 3 "const_int_operand"               "n,n"))))]
   "(INTVAL (operands[3]) & 63) == 63"
   "@
    s<lr>l<g>\t%0,<1>%Y2
@@ -8374,10 +8385,12 @@
   [(parallel
     [(set (match_operand:DSI 0 "register_operand" "")
           (ashiftrt:DSI (match_operand:DSI 1 "register_operand" "")
-                        (match_operand:SI 2 "shift_count_or_setmem_operand" "")))
+                        (match_operand:SI  2 "shift_count_or_setmem_operand_expand" "")))
      (clobber (reg:CC CC_REGNUM))])]
   ""
-  "")
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
 
 (define_insn "*ashrdi3_cc_31"
   [(set (reg CC_REGNUM)
@@ -8413,10 +8426,10 @@
    (set_attr "atype"    "reg")])
 
 ; sra, srag, srak
-(define_insn "*ashr<mode>3_cc"
+(define_insn "*ashr<GPR:mode>3_cc_<P:mode>"
   [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                               (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
+        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"           "<d0>,d")
+                               (match_operand:P   2 "shift_count_or_setmem_operand" "Y,Y"))
                  (const_int 0)))
    (set (match_operand:GPR 0 "register_operand"                                   "=d,d")
         (ashiftrt:GPR (match_dup 1) (match_dup 2)))]
@@ -8430,10 +8443,10 @@
    (set_attr "z10prop" "z10_super_E1,*")])
 
 ; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly"
+(define_insn "*ashr<GPR:mode>3_cconly_<P:mode>"
   [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                               (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
+        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"           "<d0>,d")
+                               (match_operand:P   2 "shift_count_or_setmem_operand" "Y,Y"))
                  (const_int 0)))
    (clobber (match_scratch:GPR 0                                                  "=d,d"))]
   "s390_match_ccmode(insn, CCSmode)"
@@ -8446,10 +8459,10 @@
    (set_attr "z10prop" "z10_super_E1,*")])
 
 ; sra, srag
-(define_insn "*ashr<mode>3"
-  [(set (match_operand:GPR 0 "register_operand"                          "=d,d")
-        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                      (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))
+(define_insn "*ashr<GPR:mode>3_<P:mode>"
+  [(set (match_operand:GPR 0 "register_operand"                           "=d,d")
+        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"           "<d0>,d")
+                      (match_operand:P   2 "shift_count_or_setmem_operand" "Y,Y")))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "@
@@ -8502,14 +8515,14 @@
    (set_attr "atype"    "reg")])
 
 ; sra, srag, srak
-(define_insn "*ashr<mode>3_cc_and"
+(define_insn "*ashr<GPR:mode>3_cc_and_<P:mode>"
   [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                               (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-				       (match_operand:SI 3 "const_int_operand"             "n,n")))
+        (compare (ashiftrt:GPR (match_operand:GPR      1 "register_operand"           "<d0>,d")
+                               (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+				      (match_operand:P 3 "const_int_operand"             "n,n")))
 		 (const_int 0)))
-   (set (match_operand:GPR 0 "register_operand"                                           "=d,d")
-        (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+   (set (match_operand:GPR 0 "register_operand"                                     "=d,d")
+        (ashiftrt:GPR (match_dup 1) (and (match_dup 2) (match_dup 3))))]
   "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
   "@
    sra<g>\t%0,<1>%Y2
@@ -8520,13 +8533,13 @@
    (set_attr "z10prop" "z10_super_E1,*")])
 
 ; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly_and"
+(define_insn "*ashr<GPR:mode>3_cconly_and_<P:mode>"
   [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                               (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-				       (match_operand:SI 3 "const_int_operand"             "n,n")))
+        (compare (ashiftrt:GPR (match_operand:GPR      1 "register_operand"           "<d0>,d")
+                               (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+				      (match_operand:P 3 "const_int_operand"             "n,n")))
                  (const_int 0)))
-   (clobber (match_scratch:GPR 0                                                          "=d,d"))]
+   (clobber (match_scratch:GPR 0                                                        "=d,d"))]
   "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
   "@
    sra<g>\t%0,<1>%Y2
@@ -8537,11 +8550,11 @@
    (set_attr "z10prop" "z10_super_E1,*")])
 
 ; sra, srag, srak
-(define_insn "*ashr<mode>3_and"
-  [(set (match_operand:GPR 0 "register_operand"                                  "=d,d")
-        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                      (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-			      (match_operand:SI 3 "const_int_operand"             "n,n"))))
+(define_insn "*ashr<GPR:mode>3_and_<P:mode>"
+  [(set (match_operand:GPR 0 "register_operand"                                "=d,d")
+        (ashiftrt:GPR (match_operand:GPR      1 "register_operand"           "<d0>,d")
+                      (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+			     (match_operand:P 3 "const_int_operand"             "n,n"))))
    (clobber (reg:CC CC_REGNUM))]
   "(INTVAL (operands[3]) & 63) == 63"
   "@
@@ -10703,7 +10716,7 @@
 ; Transaction abort
 
 (define_expand "tabort"
-  [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "")]
+  [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand_expand" "")]
 		    UNSPECV_TABORT)]
   "TARGET_HTM && operands != NULL"
 {
@@ -10715,15 +10728,39 @@
 	     INTVAL (operands[0]));
       FAIL;
     }
+  operands[0] = s390_expand_masked_address_operand (operands[0],
+						    GET_MODE_BITSIZE (Pmode));
 })
 
-(define_insn "*tabort_1"
-  [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "Y")]
+(define_insn "*tabort_1_<mode>"
+  [(unspec_volatile [(match_operand:P 0 "shift_count_or_setmem_operand" "Y")]
 		    UNSPECV_TABORT)]
   "TARGET_HTM && operands != NULL"
   "tabort\t%Y0"
   [(set_attr "op_type" "S")])
 
+; This splitter pulls a SI->DI zeroextend out of the address
+; calculation in order to enable the PLUS being executed as part of
+; the address operand.
+(define_insn_and_split "*tabort_1_add"
+  [(unspec_volatile
+    [(and:DI
+      (subreg:DI
+       (plus:SI (match_operand:SI 0 "register_operand"  "d")
+		(match_operand    1 "immediate_operand" "J"))
+       0)
+      (const_int 4294967295))] UNSPECV_TABORT)]
+  "TARGET_HTM"
+  "#"
+  ""
+  [(set (match_dup 2)
+	(zero_extend:DI (match_dup 0)))
+   (unspec_volatile [(plus:DI (match_dup 2) (match_dup 1))] UNSPECV_TABORT)]
+{
+  operands[2] = gen_reg_rtx(DImode);
+})
+
+
 ; Transaction extract nesting depth
 
 (define_insn "etnd"
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 16276e0..43d5c52 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -81,6 +81,27 @@
 			(V1DF "g") (V2DF "g")
 			(V1TF "q")])
 
+; Number of bits required to specify an element of a vector type
+(define_mode_attr selbits[(V1QI "4") (V2QI "4") (V4QI "4") (V8QI "4") (V16QI "4")
+			  (V1HI "3") (V2HI "3") (V4HI "3") (V8HI "3")
+			  (V1SI "2") (V2SI "2") (V4SI "2")
+			  (V1DI "1") (V2DI "1")
+			  (V1TI "0") (TI "0")
+			  (V1SF "2") (V2SF "2") (V4SF "2")
+			  (V1DF "1") (V2DF "1")
+			  (V1TF "0")])
+
+; Bitmask required to specify an element of a vector type
+; (1 << <selbits>) - 1
+(define_mode_attr selmask[(V1QI "15") (V2QI "15") (V4QI "15") (V8QI "15") (V16QI "15")
+			  (V1HI "7") (V2HI "7") (V4HI "7") (V8HI "7")
+			  (V1SI "3") (V2SI "3") (V4SI "3")
+			  (V1DI "1") (V2DI "1")
+			  (V1TI "0") (TI "0")
+			  (V1SF "3") (V2SF "3") (V4SF "3")
+			  (V1DF "1") (V2DF "1")
+			  (V1TF "0")])
+
 ; This is for vmalhw. It gets an 'w' attached to avoid confusion with
 ; multiply and add logical high vmalh.
 (define_mode_attr w [(V1QI "")  (V2QI "")  (V4QI "")  (V8QI "") (V16QI "")
@@ -306,6 +327,19 @@
 
 ; vec_store_lanes?
 
+; vec_set is supposed to *modify* an existing vector so operand 0 is
+; duplicated as input operand.
+(define_expand "vec_set<mode>"
+  [(set (match_operand:V                    0 "register_operand"                     "")
+	(unspec:V [(match_operand:<non_vec> 1 "general_operand"                      "")
+		   (match_operand:SI        2 "shift_count_or_setmem_operand_expand" "")
+		   (match_dup 0)]
+		   UNSPEC_VEC_SET))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
+
 ; FIXME: Support also vector mode operands for 1
 ; FIXME: A target memory operand seems to be useful otherwise we end
 ; up with vl vlvgg vst.  Shouldn't the middle-end be able to handle
@@ -313,7 +347,7 @@
 (define_insn "*vec_set<mode>"
   [(set (match_operand:V                    0 "register_operand"             "=v, v,v")
 	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "d,QR,K")
-		   (match_operand:DI        2 "shift_count_or_setmem_operand" "Y, I,I")
+		   (match_operand:P         2 "shift_count_or_setmem_operand" "Y, I,I")
 		   (match_operand:V         3 "register_operand"              "0, 0,0")]
 		  UNSPEC_VEC_SET))]
   "TARGET_VX"
@@ -323,23 +357,34 @@
    vlei<bhfgq>\t%v0,%1,%2"
   [(set_attr "op_type" "VRS,VRX,VRI")])
 
-; vec_set is supposed to *modify* an existing vector so operand 0 is
-; duplicated as input operand.
-(define_expand "vec_set<mode>"
-  [(set (match_operand:V                    0 "register_operand"              "")
-	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "")
-		   (match_operand:SI        2 "shift_count_or_setmem_operand" "")
-		   (match_dup 0)]
-		   UNSPEC_VEC_SET))]
-  "TARGET_VX")
+(define_insn "*vec_set<mode>_and"
+  [(set (match_operand:V                    0 "register_operand"             "=v")
+	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "d")
+		   (and:P (match_operand:P  2 "shift_count_or_setmem_operand" "Y")
+			  (const_int 4095))
+		   (match_operand:V         3 "register_operand"              "0")]
+		  UNSPEC_VEC_SET))]
+  "TARGET_VX"
+  "vlvg<bhfgq>\t%v0,%1,%Y2"
+  [(set_attr "op_type" "VRS")])
 
 ; FIXME: Support also vector mode operands for 0
 ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
 ; This is used via RTL standard name as well as for expanding the builtin
-(define_insn "vec_extract<mode>"
-  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"                        "=d,QR")
-	(unspec:<non_vec> [(match_operand:V  1 "register_operand"                " v, v")
-			   (match_operand:SI 2 "shift_count_or_setmem_operand"   " Y, I")]
+(define_expand "vec_extract<mode>"
+  [(set (match_operand:<non_vec>             0 "nonimmediate_operand"                 "")
+	(unspec:<non_vec> [(match_operand:V  1 "register_operand"                     "")
+			   (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")]
+			  UNSPEC_VEC_EXTRACT))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
+
+(define_insn "*vec_extract<mode>"
+  [(set (match_operand:<non_vec>            0 "nonimmediate_operand"            "=d,QR")
+	(unspec:<non_vec> [(match_operand:V 1 "register_operand"                " v, v")
+			   (match_operand:P 2 "shift_count_or_setmem_operand"   " Y, I")]
 			  UNSPEC_VEC_EXTRACT))]
   "TARGET_VX"
   "@
@@ -347,6 +392,16 @@
    vste<bhfgq>\t%v1,%0,%2"
   [(set_attr "op_type" "VRS,VRX")])
 
+(define_insn "*vec_extract<mode>_and"
+  [(set (match_operand:<non_vec>                   0 "nonimmediate_operand"         "=d")
+	(unspec:<non_vec> [(match_operand:V        1 "register_operand"              "v")
+			   (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+				  (const_int 4095))]
+			  UNSPEC_VEC_EXTRACT))]
+  "TARGET_VX"
+  "vlgv<bhfgq>\t%0,%v1,%Y2"
+  [(set_attr "op_type" "VRS")])
+
 (define_expand "vec_init<V_HW:mode>"
   [(match_operand:V_HW 0 "register_operand" "")
    (match_operand:V_HW 1 "nonmemory_operand" "")]
@@ -669,15 +724,33 @@
 ; Vector rotate instructions
 
 ; Each vector element rotated by a scalar
+(define_expand "rotl<mode>3"
+  [(set (match_operand:VI            0 "register_operand"                    "=v")
+	(rotate:VI (match_operand:VI 1 "register_operand"                     "v")
+		   (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], <selbits>);
+})
+
 ; verllb, verllh, verllf, verllg
-(define_insn "rotl<mode>3"
+(define_insn "*rotl<mode>3"
   [(set (match_operand:VI            0 "register_operand"             "=v")
 	(rotate:VI (match_operand:VI 1 "register_operand"              "v")
-		   (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+		   (match_operand:P  2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_VX"
   "verll<bhfgq>\t%v0,%v1,%Y2"
   [(set_attr "op_type" "VRS")])
 
+(define_insn "*rotl<mode>3_and"
+  [(set (match_operand:VI                  0 "register_operand"             "=v")
+	(rotate:VI (match_operand:VI       1 "register_operand"              "v")
+		   (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+			  (match_operand   3 "const_int_operand"             ""))))]
+  "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+  "verll<bhfgq>\t%v0,%v1,%Y2"
+  [(set_attr "op_type" "VRS")])
+
 ; Each vector element rotated by the corresponding vector element
 ; verllvb, verllvh, verllvf, verllvg
 (define_insn "vrotl<mode>3"
@@ -692,32 +765,87 @@
 ; Shift each element by scalar value
 
 ; veslb, veslh, veslf, veslg
-(define_insn "ashl<mode>3"
+(define_expand "ashl<mode>3"
+  [(set (match_operand:VI            0 "register_operand"                     "")
+	(ashift:VI (match_operand:VI 1 "register_operand"                     "")
+		   (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], <selbits>);
+})
+
+(define_insn "*ashl<mode>3"
   [(set (match_operand:VI            0 "register_operand"             "=v")
 	(ashift:VI (match_operand:VI 1 "register_operand"              "v")
-		   (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+		   (match_operand:P  2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_VX"
   "vesl<bhfgq>\t%v0,%v1,%Y2"
   [(set_attr "op_type" "VRS")])
 
+(define_insn "*ashl<mode>3_and"
+  [(set (match_operand:VI                  0 "register_operand"             "=v")
+	(ashift:VI (match_operand:VI       1 "register_operand"              "v")
+		   (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+			  (match_operand   3 "const_int_operand"             ""))))]
+  "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+  "vesl<bhfgq>\t%v0,%v1,%Y2"
+  [(set_attr "op_type" "VRS")])
+
 ; vesrab, vesrah, vesraf, vesrag
-(define_insn "ashr<mode>3"
+(define_expand "ashr<mode>3"
+  [(set (match_operand:VI              0 "register_operand"                     "")
+	(ashiftrt:VI (match_operand:VI 1 "register_operand"                     "")
+		     (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], <VI:selbits>);
+})
+
+(define_insn "*ashr<mode>3"
   [(set (match_operand:VI              0 "register_operand"             "=v")
 	(ashiftrt:VI (match_operand:VI 1 "register_operand"              "v")
-		     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+		     (match_operand:P  2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_VX"
   "vesra<bhfgq>\t%v0,%v1,%Y2"
   [(set_attr "op_type" "VRS")])
 
+(define_insn "*ashr<mode>3_and"
+  [(set (match_operand:VI                    0 "register_operand"             "=v")
+	(ashiftrt:VI (match_operand:VI       1 "register_operand"              "v")
+		     (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+			    (match_operand   3 "const_int_operand"             ""))))]
+  "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+  "vesra<bhfgq>\t%v0,%v1,%Y2"
+  [(set_attr "op_type" "VRS")])
+
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:VI              0 "register_operand"                    "=v")
+	(lshiftrt:VI (match_operand:VI 1 "register_operand"                     "v")
+		     (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))]
+  "TARGET_VX"
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], <VI:selbits>);
+})
+
 ; vesrlb, vesrlh, vesrlf, vesrlg
-(define_insn "lshr<mode>3"
+(define_insn "*lshr<mode>3"
   [(set (match_operand:VI              0 "register_operand"             "=v")
 	(lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
-		     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+		     (match_operand:P  2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_VX"
   "vesrl<bhfgq>\t%v0,%v1,%Y2"
   [(set_attr "op_type" "VRS")])
 
+(define_insn "*lshr<mode>3_and"
+  [(set (match_operand:VI                    0 "register_operand"             "=v")
+	(lshiftrt:VI (match_operand:VI       1 "register_operand"              "v")
+		     (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+			    (match_operand   3 "const_int_operand"             ""))))]
+  "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+  "vesrl<bhfgq>\t%v0,%v1,%Y2"
+  [(set_attr "op_type" "VRS")])
+
 
 ; Shift each element by corresponding vector element
 
diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index 35ada13..3e8e4c0 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -150,21 +150,27 @@
 (define_expand "vec_insert<mode>"
   [(set (match_operand:V_HW                    0 "register_operand" "")
 	(unspec:V_HW [(match_operand:<non_vec> 2 "register_operand" "")
-		      (match_operand:SI        3 "shift_count_or_setmem_operand" "")
+		      (match_operand:SI        3 "shift_count_or_setmem_operand_expand" "")
 		      (match_operand:V_HW      1 "register_operand" "")]
 		     UNSPEC_VEC_SET))]
   "TARGET_VX"
-  "")
+{
+  operands[3] = s390_expand_masked_address_operand (operands[3], 12);
+})
+
 
 ; This is vec_set + modulo arithmetic on the element selector (op 2)
+; The modulo operation is emitted in s390-c.c.
 (define_expand "vec_promote<mode>"
   [(set (match_operand:V_HW                    0 "register_operand" "")
 	(unspec:V_HW [(match_operand:<non_vec> 1 "register_operand" "")
-		      (match_operand:SI        2 "shift_count_or_setmem_operand" "")
+		      (match_operand:SI        2 "shift_count_or_setmem_operand_expand" "")
 		      (match_dup 0)]
 		     UNSPEC_VEC_SET))]
   "TARGET_VX"
-  "")
+{
+  operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
 
 ; vec_extract is also an RTL standard name -> vector.md
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]