re PR target/25311 (ICE in reload_cse_simplify_operands, at postreload.c:393)

PR target/25311
	* config/s390/s390.c (struct s390_address): New field literal_pool.
	(s390_decompose_address): Compute literal_pool field.  Do not 
	assume register %r13 is always (and solely) used as pool base.
	(s390_extra_constraint_str): Use literal_pool field.

	PR target/25311
	* gcc.c-torture/compile/pr25311.c: New test.

From-SVN: r108278
This commit is contained in:
Ulrich Weigand 2005-12-09 11:20:40 +00:00 committed by Ulrich Weigand
parent fb2d50f586
commit f01cf80928
4 changed files with 93 additions and 13 deletions

View File

@ -1,3 +1,11 @@
2005-12-09 Ulrich Weigand <uweigand@de.ibm.com>
PR target/25311
* config/s390/s390.c (struct s390_address): New field literal_pool.
(s390_decompose_address): Compute literal_pool field. Do not
assume register %r13 is always (and solely) used as pool base.
(s390_extra_constraint_str): Use literal_pool field.
2005-12-09 Thiemo Seufer <ths@networkno.de>
* config/mips/mips.c (override_options): Don't allow too small

View File

@ -209,6 +209,7 @@ struct s390_address
rtx indx;
rtx disp;
bool pointer;
bool literal_pool;
};
/* Which cpu are we tuning for. */
@ -1473,6 +1474,14 @@ s390_decompose_address (rtx addr, struct s390_address *out)
bool pointer = false;
bool base_ptr = false;
bool indx_ptr = false;
bool literal_pool = false;
/* We may need to substitute the literal pool base register into the address
below. However, at this point we do not know which register is going to
be used as base, so we substitute the arg pointer register. This is going
to be treated as holding a pointer below -- it shouldn't be used for any
other purpose. */
rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);
/* Decompose address into base + index + displacement. */
@ -1545,9 +1554,9 @@ s390_decompose_address (rtx addr, struct s390_address *out)
{
/* Either base or index must be free to hold the base register. */
if (!base)
base = gen_rtx_REG (Pmode, BASE_REGNUM);
base = fake_pool_base, literal_pool = true;
else if (!indx)
indx = gen_rtx_REG (Pmode, BASE_REGNUM);
indx = fake_pool_base, literal_pool = true;
else
return false;
@ -1570,11 +1579,14 @@ s390_decompose_address (rtx addr, struct s390_address *out)
else
return false;
base = gen_rtx_REG (Pmode, BASE_REGNUM);
base = XVECEXP (base, 0, 1);
break;
case UNSPEC_LTREL_BASE:
base = gen_rtx_REG (Pmode, BASE_REGNUM);
if (XVECLEN (base, 0) == 1)
base = fake_pool_base, literal_pool = true;
else
base = XVECEXP (base, 0, 1);
break;
default:
@ -1584,8 +1596,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
return false;
if (REGNO (base) == BASE_REGNUM
|| REGNO (base) == STACK_POINTER_REGNUM
if (REGNO (base) == STACK_POINTER_REGNUM
|| REGNO (base) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
@ -1594,6 +1605,10 @@ s390_decompose_address (rtx addr, struct s390_address *out)
|| (flag_pic
&& REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
pointer = base_ptr = true;
if ((reload_completed || reload_in_progress)
&& base == cfun->machine->base_reg)
pointer = base_ptr = literal_pool = true;
}
/* Validate index register. */
@ -1610,11 +1625,14 @@ s390_decompose_address (rtx addr, struct s390_address *out)
else
return false;
indx = gen_rtx_REG (Pmode, BASE_REGNUM);
indx = XVECEXP (indx, 0, 1);
break;
case UNSPEC_LTREL_BASE:
indx = gen_rtx_REG (Pmode, BASE_REGNUM);
if (XVECLEN (indx, 0) == 1)
indx = fake_pool_base, literal_pool = true;
else
indx = XVECEXP (indx, 0, 1);
break;
default:
@ -1624,8 +1642,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
return false;
if (REGNO (indx) == BASE_REGNUM
|| REGNO (indx) == STACK_POINTER_REGNUM
if (REGNO (indx) == STACK_POINTER_REGNUM
|| REGNO (indx) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
@ -1634,6 +1651,10 @@ s390_decompose_address (rtx addr, struct s390_address *out)
|| (flag_pic
&& REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
pointer = indx_ptr = true;
if ((reload_completed || reload_in_progress)
&& indx == cfun->machine->base_reg)
pointer = indx_ptr = literal_pool = true;
}
/* Prefer to use pointer as base, not index. */
@ -1721,6 +1742,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
out->indx = indx;
out->disp = orig_disp;
out->pointer = pointer;
out->literal_pool = literal_pool;
}
return true;
@ -1809,9 +1831,7 @@ s390_extra_constraint_str (rtx op, int c, const char * str)
return 0;
if (!s390_decompose_address (XEXP (op, 0), &addr))
return 0;
if (addr.base && REG_P (addr.base) && REGNO (addr.base) == BASE_REGNUM)
return 0;
if (addr.indx && REG_P (addr.indx) && REGNO (addr.indx) == BASE_REGNUM)
if (addr.literal_pool)
return 0;
c = str[1];

View File

@ -1,3 +1,8 @@
2005-12-09 Ulrich Weigand <uweigand@de.ibm.com>
PR target/25311
* gcc.c-torture/compile/pr25311.c: New test.
2005-12-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/25039

View File

@ -0,0 +1,47 @@
struct w
{
int top;
int left;
int height;
int width;
struct w *next;
struct w *parent;
struct w *child;
};
extern struct w *Qnil;
void
set_size (struct w *w, int new_size, int nodelete, int set_height)
{
int old_size = set_height? w->height : w->width;
if (nodelete || w->parent == Qnil)
{
int last_pos, last_old_pos, pos, old_pos, first;
int div_val = old_size << 1;
struct w *c;
last_pos = first = set_height? w->top : w->left;
last_old_pos = 0;
for (c = w->child; c != Qnil; c = c->next)
{
if (set_height)
old_pos = last_old_pos + c->height;
else
old_pos = last_old_pos + c->width;
pos = (((old_pos * new_size) << 1) + old_size) / div_val;
set_size (c, pos + first - last_pos, 1, set_height);
last_pos = pos + first;
last_old_pos = old_pos;
}
if (!nodelete)
for (c = w->child; c != Qnil; c = c->next)
use (c);
}
}