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: shifts and setmems with implicit ANDs


Hi,

shift instructions on s390 only use the 6 least significant bits
of the shift count operand. Hence we can skip pointless ANDs. After
an unsuccessful try using TARGET_SHIFT_TRUNCATION_MASK I've modified
the shift_count_operand predicate and the print_shift_count_operand
function to omit ANDs with constants which have set these 6 bits.

Almost the same applies to the padding byte operand of mvcle which is
always truncated to the 8 least significant bits.

Bootstrapped and testsuite run without regressions on s390 and s390x.

OK for mainline?

Bye,

-Andreas-


2005-08-11  Andreas Krebbel  <krebbel1@de.ibm.com>

	* config/s390/predicates.md (setmem_operand): New predicate.
	(shift_count_operand): Accept ANDs with special constants as
	operand.
	(print_shift_count_operand): Skip ANDs with special constants.
	* config/s390/s390.md ("setmem_long", "*setmem_long"): Replaced
	shift_count_operand with setmem_operand.


Index: gcc-4.1/gcc/config/s390/predicates.md
===================================================================
--- gcc-4.1.orig/gcc/config/s390/predicates.md	2005-08-11 12:38:04.000000000 +0200
+++ gcc-4.1/gcc/config/s390/predicates.md	2005-08-11 12:38:21.000000000 +0200
@@ -75,13 +75,59 @@
        (and (match_test "mode == Pmode")
 	    (match_test "!legitimate_la_operand_p (op)"))))
 
+;; Return true if OP is a valid operand for setmem.
+
+(define_predicate "setmem_operand"
+  (match_code "reg, subreg, plus, const_int")
+{
+  HOST_WIDE_INT offset = 0;
+
+  /* The padding byte operand of the mvcle instruction is always truncated
+     to the 8 least significant bits.  */
+  if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+      && (INTVAL (XEXP (op, 1)) & 255) == 255)
+    op = XEXP (op, 0);
+
+  /* We can have an integer constant, an address register,
+     or a sum of the two.  Note that reload already checks
+     that any register present is an address register, so
+     we just check for any register here.  */
+  if (GET_CODE (op) == CONST_INT)
+    {
+      offset = INTVAL (op);
+      op = NULL_RTX;
+    }
+  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+    {
+      offset = INTVAL (XEXP (op, 1));
+      op = XEXP (op, 0);
+    }
+  while (op && GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  if (op && GET_CODE (op) != REG)
+    return false;
+
+  /* Unfortunately we have to reject constants that are invalid
+     for an address, or else reload will get confused.  */
+  if (!DISP_IN_RANGE (offset))
+    return false;
+
+  return true;
+})
+
 ;; Return true if OP is a valid shift count operand.
 
 (define_predicate "shift_count_operand"
-  (match_code "reg, subreg, plus, const_int")
+  (match_code "reg, subreg, plus, const_int, and")
 {
   HOST_WIDE_INT offset = 0;
 
+  /* Shift count operands are always truncated to the 6 least significant bits.
+     So we can accept pointless ANDs here.  */
+  if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+      && (INTVAL (XEXP (op, 1)) & 63) == 63)
+    op = XEXP (op, 0);
+
   /* We can have an integer constant, an address register,
      or a sum of the two.  Note that reload already checks
      that any register present is an address register, so
Index: gcc-4.1/gcc/config/s390/s390.c
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.c	2005-08-11 12:38:21.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.c	2005-08-11 13:29:12.000000000 +0200
@@ -3749,6 +3749,17 @@ print_shift_count_operand (FILE *file, r
 {
   HOST_WIDE_INT offset = 0;
 
+  /* Shift count operands are always truncated to the 6 least significant bits and
+     the setmem padding byte to the least 8 significant bits.  Hence we can drop
+     pointless ANDs.  */
+  if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT)
+    {
+      if ((INTVAL (XEXP (op, 1)) & 63) != 63)
+	gcc_unreachable ();
+
+      op = XEXP (op, 0);
+    }
+
   /* We can have an integer constant, an address register,
      or a sum of the two.  */
   if (GET_CODE (op) == CONST_INT)
Index: gcc-4.1/gcc/config/s390/s390.md
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.md	2005-08-11 12:38:04.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.md	2005-08-11 13:29:12.000000000 +0200
@@ -2057,7 +2057,7 @@
   [(parallel
     [(clobber (match_dup 1))
      (set (match_operand:BLK 0 "memory_operand" "")
-          (match_operand 2 "shift_count_operand" ""))
+          (match_operand 2 "setmem_operand" ""))
      (use (match_operand 1 "general_operand" ""))
      (use (match_dup 3))
      (clobber (reg:CC CC_REGNUM))])]
@@ -2083,7 +2083,7 @@
 (define_insn "*setmem_long"
   [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
    (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
-        (match_operand 2 "shift_count_operand" "Y"))
+        (match_operand 2 "setmem_operand" "Y"))
    (use (match_dup 3))
    (use (match_operand:<DBL> 1 "register_operand" "d"))
    (clobber (reg:CC CC_REGNUM))]


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