Commit d98ad410 by Ulrich Weigand Committed by Ulrich Weigand

re PR target/24615 (internal compiler error: in print_shift_count_operand, at…

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
parent f55b9465
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.
......
......@@ -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
......
......@@ -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 */
......
......@@ -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'. */
......
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.
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment