flow.c (ior_reg_cond): Return NULL if ! add and rtx wasn't optimized.

* flow.c (ior_reg_cond): Return NULL if ! add and rtx wasn't optimized.
	Return correct value if one of the subexpressions was optimized to
	0 resp. 1.  Optimize (x | A) | x and (x & A) | x.
	(and_reg_cond): Similarly.

	* gcc.c-torture/compile/20011130-2.c: New test.

From-SVN: r47602
This commit is contained in:
Jakub Jelinek 2001-12-04 10:33:17 +01:00 committed by Jakub Jelinek
parent 108b7d3d31
commit b318748ff4
4 changed files with 126 additions and 50 deletions

View File

@ -1,3 +1,10 @@
2001-12-04 Jakub Jelinek <jakub@redhat.com>
* flow.c (ior_reg_cond): Return NULL if ! add and rtx wasn't optimized.
Return correct value if one of the subexpressions was optimized to
0 resp. 1. Optimize (x | A) | x and (x & A) | x.
(and_reg_cond): Similarly.
2001-12-04 Jakub Jelinek <jakub@redhat.com>
* function.c (assign_parms): Set last_named only for last named

View File

@ -2796,7 +2796,7 @@ flush_reg_cond_reg (pbi, regno)
For ior/and, the ADD flag determines whether we want to add the new
condition X to the old one unconditionally. If it is zero, we will
only return a new expression if X allows us to simplify part of
OLD, otherwise we return OLD unchanged to the caller.
OLD, otherwise we return NULL to the caller.
If ADD is nonzero, we will return a new condition in all cases. The
toplevel caller of one of these functions should always pass 1 for
ADD. */
@ -2818,7 +2818,7 @@ ior_reg_cond (old, x, add)
&& REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
return old;
if (! add)
return old;
return NULL;
return gen_rtx_IOR (0, old, x);
}
@ -2827,51 +2827,63 @@ ior_reg_cond (old, x, add)
case IOR:
op0 = ior_reg_cond (XEXP (old, 0), x, 0);
op1 = ior_reg_cond (XEXP (old, 1), x, 0);
if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
if (op0 != NULL || op1 != NULL)
{
if (op0 == const0_rtx)
return op1;
return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
if (op1 == const0_rtx)
return op0;
return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
if (op0 == const1_rtx || op1 == const1_rtx)
return const1_rtx;
if (op0 == XEXP (old, 0))
op0 = gen_rtx_IOR (0, op0, x);
else
op1 = gen_rtx_IOR (0, op1, x);
if (op0 == NULL)
op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
else if (rtx_equal_p (x, op0))
/* (x | A) | x ~ (x | A). */
return old;
if (op1 == NULL)
op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
else if (rtx_equal_p (x, op1))
/* (A | x) | x ~ (A | x). */
return old;
return gen_rtx_IOR (0, op0, op1);
}
if (! add)
return old;
return NULL;
return gen_rtx_IOR (0, old, x);
case AND:
op0 = ior_reg_cond (XEXP (old, 0), x, 0);
op1 = ior_reg_cond (XEXP (old, 1), x, 0);
if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
if (op0 != NULL || op1 != NULL)
{
if (op0 == const1_rtx)
return op1;
return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
if (op1 == const1_rtx)
return op0;
return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
if (op0 == const0_rtx || op1 == const0_rtx)
return const0_rtx;
if (op0 == XEXP (old, 0))
op0 = gen_rtx_IOR (0, op0, x);
else
op1 = gen_rtx_IOR (0, op1, x);
if (op0 == NULL)
op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
else if (rtx_equal_p (x, op0))
/* (x & A) | x ~ x. */
return op0;
if (op1 == NULL)
op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
else if (rtx_equal_p (x, op1))
/* (A & x) | x ~ x. */
return op1;
return gen_rtx_AND (0, op0, op1);
}
if (! add)
return old;
return NULL;
return gen_rtx_IOR (0, old, x);
case NOT:
op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
if (op0 != XEXP (old, 0))
if (op0 != NULL)
return not_reg_cond (op0);
if (! add)
return old;
return NULL;
return gen_rtx_IOR (0, old, x);
default:
@ -2921,7 +2933,7 @@ and_reg_cond (old, x, add)
&& REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
return old;
if (! add)
return old;
return NULL;
return gen_rtx_AND (0, old, x);
}
@ -2930,62 +2942,63 @@ and_reg_cond (old, x, add)
case IOR:
op0 = and_reg_cond (XEXP (old, 0), x, 0);
op1 = and_reg_cond (XEXP (old, 1), x, 0);
if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
if (op0 != NULL || op1 != NULL)
{
if (op0 == const0_rtx)
return op1;
return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
if (op1 == const0_rtx)
return op0;
return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
if (op0 == const1_rtx || op1 == const1_rtx)
return const1_rtx;
if (op0 == XEXP (old, 0))
op0 = gen_rtx_AND (0, op0, x);
else
op1 = gen_rtx_AND (0, op1, x);
if (op0 == NULL)
op0 = gen_rtx_AND (0, XEXP (old, 0), x);
else if (rtx_equal_p (x, op0))
/* (x | A) & x ~ x. */
return op0;
if (op1 == NULL)
op1 = gen_rtx_AND (0, XEXP (old, 1), x);
else if (rtx_equal_p (x, op1))
/* (A | x) & x ~ x. */
return op1;
return gen_rtx_IOR (0, op0, op1);
}
if (! add)
return old;
return NULL;
return gen_rtx_AND (0, old, x);
case AND:
op0 = and_reg_cond (XEXP (old, 0), x, 0);
op1 = and_reg_cond (XEXP (old, 1), x, 0);
if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
if (op0 != NULL || op1 != NULL)
{
if (op0 == const1_rtx)
return op1;
return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
if (op1 == const1_rtx)
return op0;
return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
if (op0 == const0_rtx || op1 == const0_rtx)
return const0_rtx;
if (op0 == XEXP (old, 0))
op0 = gen_rtx_AND (0, op0, x);
else
op1 = gen_rtx_AND (0, op1, x);
if (op0 == NULL)
op0 = gen_rtx_AND (0, XEXP (old, 0), x);
else if (rtx_equal_p (x, op0))
/* (x & A) & x ~ (x & A). */
return old;
if (op1 == NULL)
op1 = gen_rtx_AND (0, XEXP (old, 1), x);
else if (rtx_equal_p (x, op1))
/* (A & x) & x ~ (A & x). */
return old;
return gen_rtx_AND (0, op0, op1);
}
if (! add)
return old;
/* If X is identical to one of the existing terms of the AND,
then just return what we already have. */
/* ??? There really should be some sort of recursive check here in
case there are nested ANDs. */
if ((GET_CODE (XEXP (old, 0)) == GET_CODE (x)
&& REGNO (XEXP (XEXP (old, 0), 0)) == REGNO (XEXP (x, 0)))
|| (GET_CODE (XEXP (old, 1)) == GET_CODE (x)
&& REGNO (XEXP (XEXP (old, 1), 0)) == REGNO (XEXP (x, 0))))
return old;
return NULL;
return gen_rtx_AND (0, old, x);
case NOT:
op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
if (op0 != XEXP (old, 0))
if (op0 != NULL)
return not_reg_cond (op0);
if (! add)
return old;
return NULL;
return gen_rtx_AND (0, old, x);
default:

View File

@ -2,6 +2,8 @@
* g++.dg/other/stdarg1.C: New test.
* gcc.c-torture/compile/20011130-2.c: New test.
2001-12-03 Janis Johnson <janis187@us.ibm.com>
* gcc.c-torture/execute/builtin-prefetch-1.c: New test.

View File

@ -0,0 +1,54 @@
/* This testcase caused infinite loop in life info computation
after if conversion on IA-64. Conditional register dead for
pseudo holding sign-extended k was improperly computed,
resulting in this pseudo beeing live at start of bb if it was
dead at the end and vice versa; as it was a bb which had edge
to itself, this resulted in alternative propagating this basic
block forever. */
typedef struct {
unsigned char a;
unsigned char b;
} S0;
typedef struct {
S0 *c;
int d;
unsigned int e;
unsigned char *f[3];
void *g;
} S1;
int bar (int, void *);
int foo (S1 *x, float y)
{
S0 *h;
int i, j, k, l, m;
float n, o, p;
unsigned char *q, *r[3];
h = x->c;
m = h->a;
l = h->b;
n = y;
o = 0.0;
if (x->d == 8)
for (j = 0; j < x->e; j++)
for (k = 0; k < 3; k++)
{
n = y;
o = 0.0;
if (m)
q = x->f[k] + x->e - 1 - j;
else
q = x->f[k] + j;
p = (*q - o) * y / (n - o);
p = 0.0 > p ? 0.0 : p;
p = y < p ? y : p;
if (l)
p = r[k][(int) p];
bar (p, x->g);
}
return 1;
}