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: Overlapping check for mem blk peepholes


Hello,

for the memcpy, AND, OR and XOR block instructions we have peepholes
merging such instructions if the blocks are consecutive. The S/390
architecture assures that such a merge stays even correct if the merged memory 
blocks are overlapping. In that case a slower implementation for the
block instruction is used.

The attached patch avoids such a merge if it can be proven that the
memory locations are overlapping. An important fact is that we consider
memory locations non-overlapping if the difference of the addresses
can't be simplified to a constant value. Otherwise such a check would
circumvent the application of these peepholes almost completely becauce
the base register is generally not the same for source and destination.
On the other hand it can be assumed that there are only rare cases where
the base register differs for src and dest and the merged memory
blocks are overlapping.


Bootstrapped on s390 and s390x. Testsuite run without regressions.

OK for mainline?

Bye,

-Andreas-


2005-09-16  Andreas Krebbel  <krebbel1@de.ibm.com>

	* config/s390/s390-protos.h (s390_overlap_p): Prototype added.
	* config/s390/s390.c (s390_overlap_p): New function.
	* config/s390/s390.md ("*mvc" peephole2, "*nc" peephole2, "*oc"
	peephole2, "*xc" peephole2): Added overlap check to the peephole2
	condition.


Index: gcc-4.1/gcc/config/s390/s390-protos.h
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390-protos.h	2005-09-14 18:49:47.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390-protos.h	2005-09-15 10:08:28.000000000 +0200
@@ -38,6 +38,7 @@ extern int s390_const_double_ok_for_cons
 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_overlap_p (rtx, rtx, HOST_WIDE_INT);
 extern bool s390_offset_p (rtx, rtx, rtx);
 extern int tls_symbolic_operand (rtx);
 
Index: gcc-4.1/gcc/config/s390/s390.c
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.c	2005-09-14 18:49:47.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.c	2005-09-15 10:08:28.000000000 +0200
@@ -1077,6 +1077,48 @@ s390_split_ok_p (rtx dst, rtx src, enum 
   return true;
 }
 
+/* Return true if it can be proven that [MEM1, MEM1 + SIZE]
+   and [MEM2, MEM2 + SIZE] do overlap and false
+   otherwise.  */
+
+bool
+s390_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
+{
+  rtx addr1, addr2, addr_delta;
+  HOST_WIDE_INT delta;
+
+  if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
+    return true;
+
+  if (size == 0)
+    return false;
+
+  addr1 = XEXP (mem1, 0);
+  addr2 = XEXP (mem2, 0);
+
+  addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
+
+  /* This overlapping check is used by peepholes merging memory block operations.
+     Overlapping operations would otherwise be recognized by the S/390 hardware
+     and would fall back to a slower implementation. Allowing overlapping 
+     operations would lead to slow code but not to wrong code. Therefore we are
+     somewhat optimistict if we cannot prove that the memory blocks are 
+     overlapping.
+     That's why we return false here although this may accept operations on
+     overlapping memory areas.  */
+  if (!addr_delta || GET_CODE (addr_delta) != CONST_INT)
+    return false;
+
+  delta = INTVAL (addr_delta);
+
+  if (delta == 0
+      || (delta > 0 && delta < size)
+      || (delta < 0 && -delta < size))
+    return true;
+
+  return false;
+}
+
 /* 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.  */
Index: gcc-4.1/gcc/config/s390/s390.md
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.md	2005-09-15 10:08:19.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.md	2005-09-15 10:08:28.000000000 +0200
@@ -1750,6 +1750,8 @@
      (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])
+   && !s390_overlap_p (operands[0], operands[1], 
+                       INTVAL (operands[2]) + INTVAL (operands[5]))
    && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
   [(parallel
     [(set (match_dup 6) (match_dup 7))
@@ -5224,6 +5226,8 @@
      (clobber (reg:CC CC_REGNUM))])]
   "s390_offset_p (operands[0], operands[3], operands[2])
    && s390_offset_p (operands[1], operands[4], operands[2])
+   && !s390_overlap_p (operands[0], operands[1], 
+                       INTVAL (operands[2]) + INTVAL (operands[5]))
    && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
   [(parallel
     [(set (match_dup 6) (and:BLK (match_dup 6) (match_dup 7)))
@@ -5512,6 +5516,8 @@
      (clobber (reg:CC CC_REGNUM))])]
   "s390_offset_p (operands[0], operands[3], operands[2])
    && s390_offset_p (operands[1], operands[4], operands[2])
+   && !s390_overlap_p (operands[0], operands[1], 
+                       INTVAL (operands[2]) + INTVAL (operands[5]))
    && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
   [(parallel
     [(set (match_dup 6) (ior:BLK (match_dup 6) (match_dup 7)))
@@ -5751,6 +5757,8 @@
      (clobber (reg:CC CC_REGNUM))])]
   "s390_offset_p (operands[0], operands[3], operands[2])
    && s390_offset_p (operands[1], operands[4], operands[2])
+   && !s390_overlap_p (operands[0], operands[1], 
+                       INTVAL (operands[2]) + INTVAL (operands[5]))
    && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
   [(parallel
     [(set (match_dup 6) (xor:BLK (match_dup 6) (match_dup 7)))


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