aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2005-11-02 23:16:31 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2005-11-02 23:16:31 +0000
commitd98ad4101fa724d2d7f7364405f31fd3e8090371 (patch)
tree292c78d7d1f4715de0268e2e75d7ed0d2e075510 /gcc
parentf55b94653531277c15fbda2a69b5fa61dccbd589 (diff)
downloadgcc-d98ad4101fa724d2d7f7364405f31fd3e8090371.zip
gcc-d98ad4101fa724d2d7f7364405f31fd3e8090371.tar.gz
gcc-d98ad4101fa724d2d7f7364405f31fd3e8090371.tar.bz2
re PR target/24615 (internal compiler error: in print_shift_count_operand, at config/s390/s390.c:4025)
ChangeLog: 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. From-SVN: r106405
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/s390/predicates.md68
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c101
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr24615.c27
6 files changed, 127 insertions, 85 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e590fff..5965473 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 9f8f823..a921d1f 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -80,35 +80,17 @@
(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
@@ -124,35 +106,17 @@
(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
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 3ae43ea..42eecdb 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -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 */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 009c178..03e5a0e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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'. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b0e73c3..5fee48f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..9699d8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr24615.c
@@ -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;
+}
+