OSDN Git Service

ChangeLog:
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2005 23:16:31 +0000 (23:16 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2005 23:16:31 +0000 (23:16 +0000)
PR target/24615
* config/s390/s390-protos.h (s390_decompose_shift_count): Declare.
* config/s390/s390.c (s390_decompose_shift_count): New function.
(s390_extra_constraint_str) ['Y']: Use s390_decompose_shift_count.
(print_shift_count_operand): Use s390_decompose_shift_count.
* config/s390/predicates.md ("setmem_operand", "shift_count_operand"):
Use s390_decompose_shift_count.  Do not accept any non-base hard regs.

testsuite/ChangeLog:

PR target/24615
* gcc.dg/pr24615.c: New test.

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

gcc/ChangeLog
gcc/config/s390/predicates.md
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr24615.c [new file with mode: 0644]

index e590fff..5965473 100644 (file)
@@ -1,5 +1,15 @@
 2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
+       PR target/24615
+       * config/s390/s390-protos.h (s390_decompose_shift_count): Declare.
+       * config/s390/s390.c (s390_decompose_shift_count): New function.
+       (s390_extra_constraint_str) ['Y']: Use s390_decompose_shift_count.
+       (print_shift_count_operand): Use s390_decompose_shift_count.
+       * config/s390/predicates.md ("setmem_operand", "shift_count_operand"):
+       Use s390_decompose_shift_count.  Do not accept any non-base hard regs.
+
+2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
+
        PR target/24600
        * loop.c (loop_givs_rescan): Use force_operand to expand
        complex GIVs.
index 9f8f823..a921d1f 100644 (file)
 (define_predicate "setmem_operand"
   (match_code "reg, subreg, plus, const_int")
 {
-  HOST_WIDE_INT offset = 0;
+  HOST_WIDE_INT offset;
+  rtx base;
 
-  /* 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)
+  /* Extract base register and offset.  Use 8 significant bits.  */
+  if (!s390_decompose_shift_count (op, &base, &offset, 8))
     return false;
 
-  if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
-      && !GENERAL_REGNO_P (REGNO (op)))
+  /* Don't allow any non-base hard registers.  Doing so without
+     confusing reload and/or regrename would be tricky, and doesn't
+     buy us much anyway.  */
+  if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
     return false;
 
   /* Unfortunately we have to reject constants that are invalid
 (define_predicate "shift_count_operand"
   (match_code "reg, subreg, plus, const_int, and")
 {
-  HOST_WIDE_INT offset = 0;
+  HOST_WIDE_INT offset;
+  rtx base;
 
-  /* 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
-     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)
+  /* Extract base register and offset.  Use 6 significant bits.  */
+  if (!s390_decompose_shift_count (op, &base, &offset, 6))
     return false;
 
-  if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
-      && !GENERAL_REGNO_P (REGNO (op)))
+  /* Don't allow any non-base hard registers.  Doing so without
+     confusing reload and/or regrename would be tricky, and doesn't
+     buy us much anyway.  */
+  if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
     return false;
 
   /* Unfortunately we have to reject constants that are invalid
index 3ae43ea..42eecdb 100644 (file)
@@ -97,6 +97,7 @@ extern rtx 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 bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *, int);
 extern int s390_branch_condition_mask (rtx);
 
 #endif /* RTX_CODE */
index 009c178..03e5a0e 100644 (file)
@@ -1721,6 +1721,58 @@ s390_decompose_address (rtx addr, struct s390_address *out)
   return true;
 }
 
+/* Decompose a RTL expression OP for a shift count into its components,
+   and return the base register in BASE and the offset in OFFSET.
+
+   If BITS is non-zero, the expression is used in a context where only
+   that number to low-order bits is significant.  We then allow OP to
+   contain and outer AND that does not affect significant bits.  If BITS
+   is zero, we allow OP to contain any outer AND with a constant.
+
+   Return true if OP is a valid shift count, false if not.  */
+
+bool
+s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset, int bits)
+{
+  HOST_WIDE_INT off = 0;
+
+  /* Drop outer ANDs.  */
+  if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT)
+    {
+      HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << bits) - 1;
+      if ((INTVAL (XEXP (op, 1)) & mask) != mask)
+       return false;
+
+      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)
+    {
+      off = INTVAL (op);
+      op = NULL_RTX;
+    }
+  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+    {
+      off = 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;
+
+  if (offset)
+    *offset = off;
+  if (base)
+    *base = op;
+
+   return true;
+}
+
+
 /* Return true if CODE is a valid address without index.  */
 
 bool
@@ -1851,7 +1903,11 @@ s390_extra_constraint_str (rtx op, int c, const char * str)
       break;
 
     case 'Y':
-      return shift_count_operand (op, VOIDmode);
+      /* Simply check for the basic form of a shift count.  Reload will
+        take care of making sure we have a proper base register.  */
+      if (!s390_decompose_shift_count (op, NULL, NULL, 0))
+       return 0;
+      break;
 
     default:
       return 0;
@@ -3978,46 +4034,25 @@ s390_delegitimize_address (rtx orig_x)
 static void
 print_shift_count_operand (FILE *file, rtx op)
 {
-  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);
-    }
+  HOST_WIDE_INT offset;
+  rtx base;
 
-  /* We can have an integer constant, an address register,
-     or a sum of the two.  */
-  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);
+  /* Extract base register and offset.  */
+  if (!s390_decompose_shift_count (op, &base, &offset, 0))
+    gcc_unreachable ();
 
   /* Sanity check.  */
-  if (op)
+  if (base)
     {
-      gcc_assert (GET_CODE (op) == REG);
-      gcc_assert (REGNO (op) < FIRST_PSEUDO_REGISTER);
-      gcc_assert (REGNO_REG_CLASS (REGNO (op)) == ADDR_REGS);
+      gcc_assert (GET_CODE (base) == REG);
+      gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
+      gcc_assert (REGNO_REG_CLASS (REGNO (base)) == ADDR_REGS);
     }
 
   /* Offsets are constricted to twelve bits.  */
   fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & ((1 << 12) - 1));
-  if (op)
-    fprintf (file, "(%s)", reg_names[REGNO (op)]);
+  if (base)
+    fprintf (file, "(%s)", reg_names[REGNO (base)]);
 }
 
 /* See 'get_some_local_dynamic_name'.  */
index b0e73c3..5fee48f 100644 (file)
@@ -1,5 +1,10 @@
 2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
+       PR target/24615
+       * gcc.dg/pr24615.c: New test.
+
+2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
+
        PR target/24600
        * gcc.dg/pr24600.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/pr24615.c b/gcc/testsuite/gcc.dg/pr24615.c
new file mode 100644 (file)
index 0000000..9699d8e
--- /dev/null
@@ -0,0 +1,27 @@
+
+/* { dg-do compile } */
+/* { dg-options "-Os -fPIC" } */
+
+void *memset (void *, int, __SIZE_TYPE__);
+void *memcpy (void *, const void *, __SIZE_TYPE__);
+
+char *alloc (int);
+
+char *
+test (int type, int size, char *data, int len)
+{
+  char *block = alloc (size);
+  char *bp = block;
+
+  *bp++ = type;
+  switch (type)
+    {
+    case 0:
+    case 1:
+      memset (bp, type == 0 ? 0x00 : 0xff, size);
+      memcpy (bp, data, len);
+    }
+
+  return block;
+}
+