diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2005-11-02 23:16:31 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2005-11-02 23:16:31 +0000 |
commit | d98ad4101fa724d2d7f7364405f31fd3e8090371 (patch) | |
tree | 292c78d7d1f4715de0268e2e75d7ed0d2e075510 /gcc | |
parent | f55b94653531277c15fbda2a69b5fa61dccbd589 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/s390/predicates.md | 68 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 101 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr24615.c | 27 |
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; +} + |