From 367d32f33c7e2ad7d28157cbb940e3a8cb78fb27 Mon Sep 17 00:00:00 2001
From: Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
Date: Thu, 5 Jul 2012 10:46:19 +0000
Subject: [PATCH] 2012-07-05  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* config/s390/s390-protos.h (s390_expand_movmem)
	(s390_expand_cmpmem): Add return value.
	* config/s390/s390.c (s390_expand_movmem, s390_expand_cmpmem):
	Return FALSE to use the library function in some cases.
	* config/s390/s390.md (movmem, cmpmem): Evaluate return value of C
	helper functions.

From-SVN: r189288
---
 gcc/ChangeLog                 |  9 +++++++++
 gcc/config/s390/s390-protos.h |  4 ++--
 gcc/config/s390/s390.c        | 20 ++++++++++++++++++--
 gcc/config/s390/s390.md       | 16 +++++++++++++---
 4 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eeec49d4022d..d8ae41567a03 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2012-07-05  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+	* config/s390/s390-protos.h (s390_expand_movmem)
+	(s390_expand_cmpmem): Add return value.
+	* config/s390/s390.c (s390_expand_movmem, s390_expand_cmpmem):
+	Return FALSE to use the library function in some cases.
+	* config/s390/s390.md (movmem, cmpmem): Evaluate return value of C
+	helper functions.
+
 2012-07-05  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
 	* config.gcc: Enable ifunc attribute by default on s390 and s390x.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 01a3584fe867..4f1eb42a73f2 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -80,9 +80,9 @@ extern void s390_reload_symref_address (rtx , rtx , rtx , bool);
 extern void s390_expand_plus_operand (rtx, rtx, rtx);
 extern void emit_symbolic_move (rtx *);
 extern void s390_load_address (rtx, rtx);
-extern void s390_expand_movmem (rtx, rtx, rtx);
+extern bool s390_expand_movmem (rtx, rtx, rtx);
 extern void s390_expand_setmem (rtx, rtx, rtx);
-extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
+extern bool s390_expand_cmpmem (rtx, rtx, rtx, rtx);
 extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
 extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
 extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index ca33d4e34981..f72f49fd023f 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3986,9 +3986,16 @@ legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
 
 /* Emit code to move LEN bytes from DST to SRC.  */
 
-void
+bool
 s390_expand_movmem (rtx dst, rtx src, rtx len)
 {
+  /* When tuning for z10 or higher we rely on the Glibc functions to
+     do the right thing. Only for constant lengths below 64k we will
+     generate inline code.  */
+  if (s390_tune >= PROCESSOR_2097_Z10
+      && (GET_CODE (len) != CONST_INT || INTVAL (len) > (1<<16)))
+    return false;
+
   if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
     {
       if (INTVAL (len) > 0)
@@ -4080,6 +4087,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
 				   convert_to_mode (Pmode, count, 1)));
       emit_label (end_label);
     }
+  return true;
 }
 
 /* Emit code to set LEN bytes at DST to VAL.
@@ -4218,12 +4226,19 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
 /* Emit code to compare LEN bytes at OP0 with those at OP1,
    and return the result in TARGET.  */
 
-void
+bool
 s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 {
   rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM);
   rtx tmp;
 
+  /* When tuning for z10 or higher we rely on the Glibc functions to
+     do the right thing. Only for constant lengths below 64k we will
+     generate inline code.  */
+  if (s390_tune >= PROCESSOR_2097_Z10
+      && (GET_CODE (len) != CONST_INT || INTVAL (len) > (1<<16)))
+    return false;
+
   /* As the result of CMPINT is inverted compared to what we need,
      we have to swap the operands.  */
   tmp = op0; op0 = op1; op1 = tmp;
@@ -4331,6 +4346,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 
       emit_insn (gen_cmpint (target, ccreg));
     }
+  return true;
 }
 
 
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index a467d4a10ec6..096f26655342 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -2640,7 +2640,12 @@
    (use (match_operand:GPR 2 "general_operand" "")) ; count
    (match_operand 3 "" "")]
   ""
-  "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
+{
+  if (s390_expand_movmem (operands[0], operands[1], operands[2]))
+    DONE;
+  else
+    FAIL;
+})
 
 ; Move a block that is up to 256 bytes in length.
 ; The block length is taken as (operands[2] % 256) + 1.
@@ -3017,8 +3022,13 @@
    (use (match_operand:SI 3 "general_operand" ""))
    (use (match_operand:SI 4 "" ""))]
   ""
-  "s390_expand_cmpmem (operands[0], operands[1],
-                       operands[2], operands[3]); DONE;")
+{
+  if (s390_expand_cmpmem (operands[0], operands[1],
+                          operands[2], operands[3]))
+    DONE;
+  else
+    FAIL;
+})
 
 ; Compare a block that is up to 256 bytes in length.
 ; The block length is taken as (operands[2] % 256) + 1.
-- 
GitLab