OSDN Git Service

* config/s390/s390-protos.h (s390_offset_p): Add prototype.
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 Oct 2004 14:33:25 +0000 (14:33 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 Oct 2004 14:33:25 +0000 (14:33 +0000)
* config/s390/s390.c (s390_offset_p): New function.
* config/s390/s390.md ("*cmpdi_cct", "*cmpsi_cct", "*cmpdi_ccu",
"*cmpsi_ccu", "*cmphi_ccu", "*cmpqi_ccu"): Use splitter to
transform Q->Q alternatives to *clc pattern.
("*clc"): Move.
("movti", "*movdi_64", "*movdi_31", "*movsi_zarch", "*movsi_esa",
"*movhi", "*movqi", "*movdf_64", "*movdf_31", "movsf"): Use splitter
to transform Q->Q alternatives to *mvc pattern.
("*mvc"): Move.  Add peephole to merge adjacent MVCs.
("*anddi3", "*andsi3_zarch", "*andsi3_esa", "*andhi3_zarch",
"*andhi3_esa", "*andqi3_zarch", "*andqi3_esa"): Use splitter to
transform Q->Q alternatives to *nc pattern.
("*nc"): New insn.  New peephole to merge adjacent NCs.
("*iordi3", "*iorsi3_zarch", "*iorsi3_esa", "*iorhi3_zarch",
"*iorhi3_esa", "*iorqi3_zarch", "*iorqi3_esa"): Use splitter to
transform Q->Q alternatives to *oc pattern.
("*oc"): New insn.  New peephole to merge adjacent OCs.
("*xordi3", "*xorsi3", "*xorhi3", "*xorqi3"): Use splitter to
transform Q->Q alternatives to *xc pattern.
("*xc"): New insn.  New peephole to merge adjacent XCs.
("*xc_zero"): Move.  Add peephole to merge adjacent XCs.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88878 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 5b3d9d1..4df3fea 100644 (file)
@@ -1,3 +1,28 @@
+2004-10-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390-protos.h (s390_offset_p): Add prototype.
+       * config/s390/s390.c (s390_offset_p): New function.
+       * config/s390/s390.md ("*cmpdi_cct", "*cmpsi_cct", "*cmpdi_ccu",
+       "*cmpsi_ccu", "*cmphi_ccu", "*cmpqi_ccu"): Use splitter to
+       transform Q->Q alternatives to *clc pattern.
+       ("*clc"): Move.
+       ("movti", "*movdi_64", "*movdi_31", "*movsi_zarch", "*movsi_esa",
+       "*movhi", "*movqi", "*movdf_64", "*movdf_31", "movsf"): Use splitter
+       to transform Q->Q alternatives to *mvc pattern.
+       ("*mvc"): Move.  Add peephole to merge adjacent MVCs.
+       ("*anddi3", "*andsi3_zarch", "*andsi3_esa", "*andhi3_zarch",
+       "*andhi3_esa", "*andqi3_zarch", "*andqi3_esa"): Use splitter to
+       transform Q->Q alternatives to *nc pattern.
+       ("*nc"): New insn.  New peephole to merge adjacent NCs.
+       ("*iordi3", "*iorsi3_zarch", "*iorsi3_esa", "*iorhi3_zarch",
+       "*iorhi3_esa", "*iorqi3_zarch", "*iorqi3_esa"): Use splitter to
+       transform Q->Q alternatives to *oc pattern.
+       ("*oc"): New insn.  New peephole to merge adjacent OCs.
+       ("*xordi3", "*xorsi3", "*xorhi3", "*xorqi3"): Use splitter to
+       transform Q->Q alternatives to *xc pattern.
+       ("*xc"): New insn.  New peephole to merge adjacent XCs.
+       ("*xc_zero"): Move.  Add peephole to merge adjacent XCs.
+
 2004-10-11  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * gimplify.c (gimple_push_condition): Make sure that we don't
index 4e88c1d..4b405f2 100644 (file)
@@ -44,6 +44,7 @@ extern int store_multiple_operation (rtx, enum machine_mode);
 extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
 extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
 extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
+extern bool s390_offset_p (rtx, rtx, rtx);
 extern int tls_symbolic_operand (rtx);
 
 extern int s390_match_ccmode (rtx, enum machine_mode);
index 1d4d813..2a65365 100644 (file)
@@ -1096,6 +1096,28 @@ s390_split_ok_p (rtx dst, rtx src, enum machine_mode mode, int first_subword)
   return true;
 }
 
+/* Check whether the address of memory reference MEM2 equals exactly
+   the address of memory reference MEM1 plus DELTA.  Return true if
+   we can prove this to be the case, false otherwise.  */
+
+bool
+s390_offset_p (rtx mem1, rtx mem2, rtx delta)
+{
+  rtx addr1, addr2, addr_delta;
+
+  if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
+    return false;
+
+  addr1 = XEXP (mem1, 0);
+  addr2 = XEXP (mem2, 0);
+
+  addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
+  if (!addr_delta || !rtx_equal_p (addr_delta, delta))
+    return false;
+
+  return true;
+}
+
 /* Expand logical operator CODE in mode MODE with operands OPERANDS.  */
 
 void
index 7d59f0c..8d43779 100644 (file)
    cghi\t%0,%c1
    cg\t%0,%1
    cg\t%1,%0
-   clc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RRE,RI,RXY,RXY,SS")])
 
 (define_insn "*cmpsi_cct"
    cy\t%0,%1
    c\t%1,%0
    cy\t%1,%0
-   clc\t%O0(4,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")])
 
 
   "@
    clgr\t%0,%1
    clg\t%0,%1
-   clc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RRE,RXY,SS")])
 
 (define_insn "*cmpsi_ccu"
    clr\t%0,%1
    cl\t%0,%1
    cly\t%0,%1
-   clc\t%O0(4,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RX,RXY,SS")])
 
 (define_insn "*cmphi_ccu"
   "@
    clm\t%0,3,%1
    clmy\t%0,3,%1
-   clc\t%O0(2,%R0),%1"
+   #"
   [(set_attr "op_type" "RS,RSY,SS")])
 
 (define_insn "*cmpqi_ccu"
    clmy\t%0,1,%1
    cli\t%0,%b1
    cliy\t%0,%b1
-   clc\t%O0(1,%R0),%1"
+   #"
   [(set_attr "op_type" "RS,RSY,SI,SIY,SS")])
 
 
+; Block compare (CLC) instruction patterns.
+
+(define_insn "*clc"
+  [(set (reg 33)
+        (compare (match_operand:BLK 0 "memory_operand" "=Q")
+                 (match_operand:BLK 1 "memory_operand" "Q")))
+   (use (match_operand 2 "const_int_operand" "n"))]
+  "s390_match_ccmode (insn, CCUmode)
+   && INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+  "clc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_split
+  [(set (reg 33)
+        (compare (match_operand 0 "memory_operand" "")
+                 (match_operand 1 "memory_operand" "")))]
+  "reload_completed
+   && s390_match_ccmode (insn, CCUmode)
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+  [(parallel
+    [(set (match_dup 0) (match_dup 1))
+     (use (match_dup 2))])]
+{
+  operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+  operands[0] = adjust_address (operands[0], BLKmode, 0);
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+
+  operands[1] = gen_rtx_COMPARE (GET_MODE (SET_DEST (PATTERN (curr_insn))),
+                                operands[0], operands[1]);
+  operands[0] = SET_DEST (PATTERN (curr_insn));
+})
+
+
 ; DF instructions
 
 (define_insn "*cmpdf_ccs_0"
    stmg\t%1,%N1,%0
    #
    #
-   mvc\t%O0(16,%R0),%1"
+   #"
   [(set_attr "op_type" "RSY,RSY,NN,NN,SS")
    (set_attr "type" "lm,stm,*,*,cs")])
 
    ldy\t%0,%1
    std\t%1,%0
    stdy\t%1,%0
-   mvc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,RR,RX,RXY,RX,RXY,SS")
    (set_attr "type" "*,*,*,*,*,la,lr,load,store,floadd,floadd,floadd,
                      fstored,fstored,cs")])
    ldy\t%0,%1
    std\t%1,%0
    stdy\t%1,%0
-   mvc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RXY,RX,RXY,SS")
    (set_attr "type" "lm,stm,*,*,floadd,floadd,floadd,fstored,fstored,cs")])
 
    ley\t%0,%1
    ste\t%1,%0
    stey\t%1,%0
-   mvc\t%O0(4,%R0),%1"
+   #"
   [(set_attr "op_type" "RI,RI,RI,RXY,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
    (set_attr "type" "*,*,*,la,lr,load,load,store,store,floads,floads,floads,fstores,fstores,cs")])
 
    ler\t%0,%1
    le\t%0,%1
    ste\t%1,%0
-   mvc\t%O0(4,%R0),%1"
+   #"
   [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,SS")
    (set_attr "type" "*,lr,load,store,floads,floads,fstores,cs")])
 
    lhy\t%0,%1
    sth\t%1,%0
    sthy\t%1,%0
-   mvc\t%O0(2,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")
    (set_attr "type" "lr,*,*,*,store,store,cs")])
 
    stcy\t%1,%0
    mvi\t%0,%b1
    mviy\t%0,%b1
-   mvc\t%O0(1,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SI,SIY,SS")
    (set_attr "type" "lr,*,*,*,store,store,store,store,cs")])
 
    lgr\t%0,%1
    lg\t%0,%1
    stg\t%1,%0
-   mvc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RRE,RXY,RXY,SS")
    (set_attr "type" "floadd,floadd,floadd,fstored,fstored,lr,load,store,cs")])
 
    stm\t%1,%N1,%0
    #
    #
-   mvc\t%O0(8,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RS,RS,NN,NN,SS")
    (set_attr "type" "floadd,floadd,floadd,fstored,fstored,lm,stm,*,*,cs")])
 
    ly\t%0,%1
    st\t%1,%0
    sty\t%1,%0
-   mvc\t%O0(4,%R0),%1"
+   #"
   [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
    (set_attr "type" "floads,floads,floads,fstores,fstores,lr,load,load,store,store,cs")])
 
 ;
+; Block move (MVC) patterns.
+;
+
+(define_insn "*mvc"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (match_operand:BLK 1 "memory_operand" "Q"))
+   (use (match_operand 2 "const_int_operand" "n"))]
+  "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+  "mvc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_split
+  [(set (match_operand 0 "memory_operand" "")
+        (match_operand 1 "memory_operand" ""))]
+  "reload_completed
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+  [(parallel
+    [(set (match_dup 0) (match_dup 1))
+     (use (match_dup 2))])]
+{
+  operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+  operands[0] = adjust_address (operands[0], BLKmode, 0);
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (match_operand:BLK 1 "memory_operand" ""))
+     (use (match_operand 2 "const_int_operand" ""))])
+   (parallel
+    [(set (match_operand:BLK 3 "memory_operand" "")
+          (match_operand:BLK 4 "memory_operand" ""))
+     (use (match_operand 5 "const_int_operand" ""))])]
+  "s390_offset_p (operands[0], operands[3], operands[2])
+   && s390_offset_p (operands[1], operands[4], operands[2])
+   && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+  [(parallel
+    [(set (match_dup 6) (match_dup 7))
+     (use (match_dup 8))])]
+  "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+   operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+   operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
+
+;
 ; load_multiple pattern(s).
 ;
 ; ??? Due to reload problems with replacing registers inside match_parallel
      (use (const_int 1))])]
   "operands[4] = gen_label_rtx ();")
 
-(define_insn "*mvc"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q")
-        (match_operand:BLK 1 "memory_operand" "Q"))
-   (use (match_operand 2 "const_int_operand" "n"))]
-  ""
-  "mvc\t%O0(%2,%R0),%1"
-  [(set_attr "op_type" "SS")
-   (set_attr "type"    "cs")])
-
 ; Move a block of arbitrary length.
 
 (define_expand "movmem_long"
      (clobber (reg:CC 33))])]
   "operands[3] = gen_label_rtx ();")
 
-(define_insn "*xc_zero"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q")
-        (const_int 0))
-   (use (match_operand 1 "const_int_operand" "n"))
-   (clobber (reg:CC 33))]
-  ""
-  "xc\t%O0(%1,%R0),%0"
-  [(set_attr "op_type" "SS")
-   (set_attr "type"    "cs")])
-
 ; Clear a block of arbitrary length.
 
 (define_expand "clrmem_long"
      (use (const_int 1))])]
   "operands[4] = gen_label_rtx ();")
 
-(define_insn "*clc"
-  [(set (reg:CCU 33)
-        (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q")
-                     (match_operand:BLK 1 "memory_operand" "Q")))
-   (use (match_operand 2 "const_int_operand" "n"))]
-  ""
-  "clc\t%O0(%2,%R0),%1"
-  [(set_attr "op_type" "SS")
-   (set_attr "type"    "cs")])
-
 ; Compare a block of arbitrary length.
 
 (define_expand "cmpmem_long"
    ngr\t%0,%2
    ng\t%0,%2
    #
-   nc\t%O0(8,%R0),%2"
+   #"
   [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY,SI,SS")])
 
 (define_split
    n\t%0,%2
    ny\t%0,%2
    #
-   nc\t%O0(4,%R0),%2"
+   #"
   [(set_attr "op_type"  "RRE,RXE,RI,RI,RR,RX,RXY,SI,SS")])
 
 (define_insn "*andsi3_esa"
    nr\t%0,%2
    n\t%0,%2
    #
-   nc\t%O0(4,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RX,SI,SS")])
 
 (define_split
    nr\t%0,%2
    nill\t%0,%x2
    #
-   nc\t%O0(2,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RI,SI,SS")])
 
 (define_insn "*andhi3_esa"
   "@
    nr\t%0,%2
    #
-   nc\t%O0(2,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SS")])
 
 (define_split
    nill\t%0,%b2
    ni\t%0,%b2
    niy\t%0,%b2
-   nc\t%O0(1,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RI,SI,SIY,SS")])
 
 (define_insn "*andqi3_esa"
   "@
    nr\t%0,%2
    ni\t%0,%b2
-   nc\t%O0(1,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SS")])
 
 (define_expand "andqi3"
   ""
   "s390_expand_logical_operator (AND, QImode, operands); DONE;")
 
+;
+; Block and (NC) patterns.
+;
+
+(define_insn "*nc"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (and:BLK (match_dup 0)
+                 (match_operand:BLK 1 "memory_operand" "Q")))
+   (use (match_operand 2 "const_int_operand" "n"))
+   (clobber (reg:CC 33))]
+  "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+  "nc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_split
+  [(set (match_operand 0 "memory_operand" "")
+        (and (match_dup 0)
+             (match_operand 1 "memory_operand" "")))
+   (clobber (reg:CC 33))]
+  "reload_completed
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+  [(parallel
+    [(set (match_dup 0) (and:BLK (match_dup 0) (match_dup 1)))
+     (use (match_dup 2))
+     (clobber (reg:CC 33))])]
+{
+  operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+  operands[0] = adjust_address (operands[0], BLKmode, 0);
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (and:BLK (match_dup 0)
+                   (match_operand:BLK 1 "memory_operand" "")))
+     (use (match_operand 2 "const_int_operand" ""))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_operand:BLK 3 "memory_operand" "")
+          (and:BLK (match_dup 3)
+                   (match_operand:BLK 4 "memory_operand" "")))
+     (use (match_operand 5 "const_int_operand" ""))
+     (clobber (reg:CC 33))])]
+  "s390_offset_p (operands[0], operands[3], operands[2])
+   && s390_offset_p (operands[1], operands[4], operands[2])
+   && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+  [(parallel
+    [(set (match_dup 6) (and:BLK (match_dup 6) (match_dup 7)))
+     (use (match_dup 8))
+     (clobber (reg:CC 33))])]
+  "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+   operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+   operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
 
 ;;
 ;;- Bit set (inclusive or) instructions.
    ogr\t%0,%2
    og\t%0,%2
    #
-   oc\t%O0(8,%R0),%2"
+   #"
   [(set_attr "op_type"  "RI,RI,RI,RI,RRE,RXY,SI,SS")])
 
 (define_split
    o\t%0,%2
    oy\t%0,%2
    #
-   oc\t%O0(4,%R0),%2"
+   #"
   [(set_attr "op_type"  "RI,RI,RR,RX,RXY,SI,SS")])
 
 (define_insn "*iorsi3_esa"
    or\t%0,%2
    o\t%0,%2
    #
-   oc\t%O0(4,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RX,SI,SS")])
 
 (define_split
    or\t%0,%2
    oill\t%0,%x2
    #
-   oc\t%O0(2,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RI,SI,SS")])
 
 (define_insn "*iorhi3_esa"
   "@
    or\t%0,%2
    #
-   oc\t%O0(2,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SS")])
 
 (define_split
    oill\t%0,%b2
    oi\t%0,%b2
    oiy\t%0,%b2
-   oc\t%O0(1,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RI,SI,SIY,SS")])
 
 (define_insn "*iorqi3_esa"
   "@
    or\t%0,%2
    oi\t%0,%b2
-   oc\t%O0(1,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SS")])
 
 (define_expand "iorqi3"
   ""
   "s390_expand_logical_operator (IOR, QImode, operands); DONE;")
 
+;
+; Block inclusive or (OC) patterns.
+;
+
+(define_insn "*oc"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (ior:BLK (match_dup 0)
+                 (match_operand:BLK 1 "memory_operand" "Q")))
+   (use (match_operand 2 "const_int_operand" "n"))
+   (clobber (reg:CC 33))]
+  "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+  "oc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_split
+  [(set (match_operand 0 "memory_operand" "")
+        (ior (match_dup 0)
+             (match_operand 1 "memory_operand" "")))
+   (clobber (reg:CC 33))]
+  "reload_completed
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+  [(parallel
+    [(set (match_dup 0) (ior:BLK (match_dup 0) (match_dup 1)))
+     (use (match_dup 2))
+     (clobber (reg:CC 33))])]
+{
+  operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+  operands[0] = adjust_address (operands[0], BLKmode, 0);
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (ior:BLK (match_dup 0)
+                   (match_operand:BLK 1 "memory_operand" "")))
+     (use (match_operand 2 "const_int_operand" ""))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_operand:BLK 3 "memory_operand" "")
+          (ior:BLK (match_dup 3)
+                   (match_operand:BLK 4 "memory_operand" "")))
+     (use (match_operand 5 "const_int_operand" ""))
+     (clobber (reg:CC 33))])]
+  "s390_offset_p (operands[0], operands[3], operands[2])
+   && s390_offset_p (operands[1], operands[4], operands[2])
+   && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+  [(parallel
+    [(set (match_dup 6) (ior:BLK (match_dup 6) (match_dup 7)))
+     (use (match_dup 8))
+     (clobber (reg:CC 33))])]
+  "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+   operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+   operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
 
 ;;
 ;;- Xor instructions.
    xgr\t%0,%2
    xg\t%0,%2
    #
-   xc\t%O0(8,%R0),%2"
+   #"
   [(set_attr "op_type"  "RRE,RXY,SI,SS")])
 
 (define_split
    x\t%0,%2
    xy\t%0,%2
    #
-   xc\t%O0(4,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,RX,RXY,SI,SS")])
 
 (define_split
   "@
    xr\t%0,%2
    #
-   xc\t%O0(2,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SS")])
 
 (define_split
    xr\t%0,%2
    xi\t%0,%b2
    xiy\t%0,%b2
-   xc\t%O0(1,%R0),%2"
+   #"
   [(set_attr "op_type"  "RR,SI,SIY,SS")])
 
 (define_expand "xorqi3"
   ""
   "s390_expand_logical_operator (XOR, QImode, operands); DONE;")
 
+;
+; Block exclusive or (XC) patterns.
+;
+
+(define_insn "*xc"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (xor:BLK (match_dup 0)
+                 (match_operand:BLK 1 "memory_operand" "Q")))
+   (use (match_operand 2 "const_int_operand" "n"))
+   (clobber (reg:CC 33))]
+  "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+  "xc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_split
+  [(set (match_operand 0 "memory_operand" "")
+        (xor (match_dup 0)
+             (match_operand 1 "memory_operand" "")))
+   (clobber (reg:CC 33))]
+  "reload_completed
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+  [(parallel
+    [(set (match_dup 0) (xor:BLK (match_dup 0) (match_dup 1)))
+     (use (match_dup 2))
+     (clobber (reg:CC 33))])]
+{
+  operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+  operands[0] = adjust_address (operands[0], BLKmode, 0);
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (xor:BLK (match_dup 0)
+                   (match_operand:BLK 1 "memory_operand" "")))
+     (use (match_operand 2 "const_int_operand" ""))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_operand:BLK 3 "memory_operand" "")
+          (xor:BLK (match_dup 3)
+                   (match_operand:BLK 4 "memory_operand" "")))
+     (use (match_operand 5 "const_int_operand" ""))
+     (clobber (reg:CC 33))])]
+  "s390_offset_p (operands[0], operands[3], operands[2])
+   && s390_offset_p (operands[1], operands[4], operands[2])
+   && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+  [(parallel
+    [(set (match_dup 6) (xor:BLK (match_dup 6) (match_dup 7)))
+     (use (match_dup 8))
+     (clobber (reg:CC 33))])]
+  "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+   operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+   operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
+;
+; Block xor (XC) patterns with src == dest.
+;
+
+(define_insn "*xc_zero"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (const_int 0))
+   (use (match_operand 1 "const_int_operand" "n"))
+   (clobber (reg:CC 33))]
+  "INTVAL (operands[1]) >= 1 && INTVAL (operands[1]) <= 256"
+  "xc\t%O0(%1,%R0),%0"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
+
+(define_peephole2
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (const_int 0))
+     (use (match_operand 1 "const_int_operand" ""))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_operand:BLK 2 "memory_operand" "")
+          (const_int 0))
+     (use (match_operand 3 "const_int_operand" ""))
+     (clobber (reg:CC 33))])]
+  "s390_offset_p (operands[0], operands[2], operands[1])
+   && INTVAL (operands[1]) + INTVAL (operands[3]) <= 256"
+  [(parallel
+    [(set (match_dup 4) (const_int 0))
+     (use (match_dup 5))
+     (clobber (reg:CC 33))])]
+  "operands[4] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+   operands[5] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[3]));")
+
 
 ;;
 ;;- Negate instructions.