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.
(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
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 */
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
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;
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'. */
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.
--- /dev/null
+
+/* { 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;
+}
+