tree-optimization/112282 - wrong-code with ifcvt hoisting
The following avoids hoisting of invariants from conditionally executed parts of an if-converted loop. That now makes a difference since we perform bitfield lowering even when we do not actually if-convert the loop. if-conversion deals with resetting flow-sensitive info when necessary already. PR tree-optimization/112282 * tree-if-conv.cc (ifcvt_hoist_invariants): Only hoist from the loop header. * gcc.dg/torture/pr112282.c: New testcase.
This commit is contained in:
parent
bcef48b59e
commit
5cb8610d3a
2 changed files with 153 additions and 23 deletions
132
gcc/testsuite/gcc.dg/torture/pr112282.c
Normal file
132
gcc/testsuite/gcc.dg/torture/pr112282.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
int printf(const char *, ...);
|
||||
void __assert_fail();
|
||||
int a, g, h, i, v, w = 2, x, y, ab, ac, ad, ae, af, ag;
|
||||
static int f, j, m, n, p, r, u, aa;
|
||||
struct b {
|
||||
int c : 20;
|
||||
int d : 20;
|
||||
int e : 10;
|
||||
};
|
||||
static struct b l, o, q = {3, 3, 5};
|
||||
int s(int z) {
|
||||
struct b ah;
|
||||
int ai = 1, aj[7] = {1, 1, 1, 1, 1, 1, 1};
|
||||
ak:
|
||||
for (u = -22; u < 2; ++u) {
|
||||
struct b al[8] = {{2, 7, 9}, {8, 7, 1}, {2, 7, 9}, {8, 7, 1}, {2, 7, 9}, {8, 7, 1}, {2, 7, 9}};
|
||||
y = z = 0;
|
||||
for (; z < 2; z++) {
|
||||
int am[18], k;
|
||||
ab = ac = 0;
|
||||
for (; ac < 1; ac++)
|
||||
for (k = 0; k < 9; k++)
|
||||
am[k] = 0;
|
||||
n = 0;
|
||||
while (1) {
|
||||
v = u < 0 || a;
|
||||
h = z < ~u && 4 & q.c;
|
||||
if ((aa <= l.c) > q.d && p)
|
||||
return o.c;
|
||||
if (w)
|
||||
break;
|
||||
return q.e;
|
||||
}
|
||||
a = j;
|
||||
}
|
||||
}
|
||||
for (x = 0; x < 2; x++) {
|
||||
struct b an = {1, 8, 4};
|
||||
int ao[28] = {5, 0, 0, 9, 0, 3, 0, 5, 0, 0, 9, 0, 3, 0, 5, 0, 0, 9, 0, 3, 0, 5, 0, 0, 9, 0, 3, 0};
|
||||
if (q.e) {
|
||||
int ap = ai || l.c + q.c, aq = q.d, ar = p & f;
|
||||
q.d = q.d || ar || ap;
|
||||
p = 0;
|
||||
if (!j && ai)
|
||||
goto as;
|
||||
if (q.d) {
|
||||
printf("", l);
|
||||
q.d = f >> j;
|
||||
}
|
||||
p = l.c = aq;
|
||||
an = q;
|
||||
} else {
|
||||
int at[12][1] = {{9}, {9}, {5}, {9}, {9}, {5}, {9}, {9}, {5}, {9}, {9}, {5}};
|
||||
struct b au;
|
||||
if (o.c)
|
||||
aa = ah.e;
|
||||
if (an.d)
|
||||
ah.e = (j & (aa * m)) ^ au.d;
|
||||
o.c = m + aa;
|
||||
int av = o.c || 0, aw = ai || q.c & l.c, ax = n;
|
||||
if (q.e < ai)
|
||||
q = an;
|
||||
if (r)
|
||||
break;
|
||||
ai = aw - av;
|
||||
an.e = 0;
|
||||
if (ai) {
|
||||
an.e = l.c || 0;
|
||||
f = q.c;
|
||||
ah.e = l.c % q.d;
|
||||
q.c = au.e;
|
||||
if ((q.d && q.c) || ah.e)
|
||||
__assert_fail();
|
||||
q.c = 0;
|
||||
if (au.d > m || ah.e)
|
||||
w = au.c | (n & ah.c);
|
||||
as:
|
||||
ae = af = ah.c;
|
||||
int ay = au.d & q.e & au.c || o.c, az = 0 || o.c, ba = m & ah.d;
|
||||
if (n)
|
||||
au.c = au.e = (q.e || ah.d) ^ (o.c + (az / au.e));
|
||||
n = au.c || au.e;
|
||||
if (ba) {
|
||||
printf("", ax);
|
||||
x = q.e | m;
|
||||
continue;
|
||||
}
|
||||
m = ay;
|
||||
n = printf("", au);
|
||||
}
|
||||
if (ah.d)
|
||||
o.c = l.c & o.c & q.c;
|
||||
if (q.d)
|
||||
__assert_fail();
|
||||
printf("", an);
|
||||
printf("", q);
|
||||
printf("", au);
|
||||
if (ah.e)
|
||||
while (u++) {
|
||||
struct b al[7] = {{7, 9, 8}, {7, 1, 2}, {7, 9, 8}, {7, 1, 2}, {7, 9, 8}, {7, 1, 2}, {7, 9, 0}};
|
||||
if (an.d) {
|
||||
int d[8] = {0, 1, 0, 1, 0, 1, 0, 1};
|
||||
if (ad)
|
||||
goto ak;
|
||||
while (ag)
|
||||
g = an.d = i = m;
|
||||
f = j;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
f = q.d;
|
||||
}
|
||||
if (l.c && m) {
|
||||
int d[7] = {1, 0, 1, 0, 1, 0, 1};
|
||||
if (x)
|
||||
h = an.d;
|
||||
else
|
||||
g = 0;
|
||||
}
|
||||
}
|
||||
int bb = (q.d ^ ah.c) | aa | (q.e & q.c) | (f & ah.d);
|
||||
if (bb)
|
||||
return x;
|
||||
return 0;
|
||||
}
|
||||
int main() {
|
||||
j = 1;
|
||||
s(0);
|
||||
return 0;
|
||||
}
|
|
@ -3468,30 +3468,28 @@ ifcvt_can_hoist (class loop *loop, edge pe, gimple *stmt)
|
|||
static void
|
||||
ifcvt_hoist_invariants (class loop *loop, edge pe)
|
||||
{
|
||||
/* Only hoist from the now unconditionally executed part of the loop. */
|
||||
basic_block bb = loop->header;
|
||||
gimple_stmt_iterator hoist_gsi = {};
|
||||
unsigned int num_blocks = loop->num_nodes;
|
||||
basic_block *body = get_loop_body (loop);
|
||||
for (unsigned int i = 0; i < num_blocks; ++i)
|
||||
for (gimple_stmt_iterator gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);)
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
if (ifcvt_can_hoist (loop, pe, stmt))
|
||||
{
|
||||
/* Once we've hoisted one statement, insert other statements
|
||||
after it. */
|
||||
gsi_remove (&gsi, false);
|
||||
if (hoist_gsi.ptr)
|
||||
gsi_insert_after (&hoist_gsi, stmt, GSI_NEW_STMT);
|
||||
else
|
||||
{
|
||||
gsi_insert_on_edge_immediate (pe, stmt);
|
||||
hoist_gsi = gsi_for_stmt (stmt);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
gsi_next (&gsi);
|
||||
}
|
||||
free (body);
|
||||
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
if (ifcvt_can_hoist (loop, pe, stmt))
|
||||
{
|
||||
/* Once we've hoisted one statement, insert other statements
|
||||
after it. */
|
||||
gsi_remove (&gsi, false);
|
||||
if (hoist_gsi.ptr)
|
||||
gsi_insert_after (&hoist_gsi, stmt, GSI_NEW_STMT);
|
||||
else
|
||||
{
|
||||
gsi_insert_on_edge_immediate (pe, stmt);
|
||||
hoist_gsi = gsi_for_stmt (stmt);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
gsi_next (&gsi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the DECL_FIELD_BIT_OFFSET of the bitfield accesse in stmt iff its
|
||||
|
|
Loading…
Add table
Reference in a new issue