aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2001-12-04 10:33:17 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2001-12-04 10:33:17 +0100
commitb318748ff4b6a9256695a3e768d4a951dd4b8ca6 (patch)
treef4cbf2a19a8962de46bab2e668b5770fcd6f9668 /gcc
parent108b7d3d316599861369de7c7f9bfaef915c7bd3 (diff)
downloadgcc-b318748ff4b6a9256695a3e768d4a951dd4b8ca6.zip
gcc-b318748ff4b6a9256695a3e768d4a951dd4b8ca6.tar.gz
gcc-b318748ff4b6a9256695a3e768d4a951dd4b8ca6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/flow.c113
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20011130-2.c54
4 files changed, 126 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dff736e..fff9d98 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
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
argument.
diff --git a/gcc/flow.c b/gcc/flow.c
index df27edc..fdf4df2 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4c7036f..76f673f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20011130-2.c b/gcc/testsuite/gcc.c-torture/compile/20011130-2.c
new file mode 100644
index 0000000..6439527
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20011130-2.c
@@ -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;
+}