Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
8ea5207a
Commit
8ea5207a
authored
May 05, 2011
by
Matthias Braun
Browse files
cfopt: fix countless bugs introduced when changing unreachable code elimination
parent
385ddac3
Changes
1
Hide whitespace changes
Inline
Side-by-side
ir/opt/cfopt.c
View file @
8ea5207a
...
...
@@ -101,6 +101,8 @@ static void collect_nodes(ir_node *n, void *ctx)
set_irn_link
(
n
,
get_irn_link
(
block
));
set_irn_link
(
block
,
n
);
}
else
if
(
is_Block
(
n
))
{
if
(
has_Block_entity
(
n
))
set_Block_removable
(
n
,
false
);
return
;
}
else
if
(
!
is_Jmp
(
n
))
{
/* Check for non-empty block. */
ir_node
*
block
=
get_nodes_block
(
n
);
...
...
@@ -134,6 +136,20 @@ static bool is_pred_of(ir_node *pred, ir_node *b)
return
false
;
}
static
unsigned
count_non_bad_inputs
(
const
ir_node
*
node
)
{
int
arity
=
get_irn_arity
(
node
);
unsigned
result
=
0
;
int
i
;
for
(
i
=
0
;
i
<
arity
;
++
i
)
{
ir_node
*
in
=
get_irn_n
(
node
,
i
);
if
(
!
is_Bad
(
in
))
++
result
;
}
return
result
;
}
/** Test whether we can optimize away pred block pos of b.
*
* @param b A block node.
...
...
@@ -163,48 +179,61 @@ static bool is_pred_of(ir_node *pred, ir_node *b)
**/
static
unsigned
test_whether_dispensable
(
ir_node
*
b
,
int
pos
)
{
i
nt
i
,
j
,
n_preds
=
1
;
ir_node
*
pred
=
get_
Block_cfgpred
_block
(
b
,
pos
);
i
r_node
*
pred
=
get_Block_cfgpred
(
b
,
pos
)
;
ir_node
*
pred
b
=
get_
nodes
_block
(
pred
);
/* Bad blocks will be optimized away, so we don't need space for them */
if
(
is_Bad
(
pred
))
return
0
;
if
(
is_Block_removable
(
pred
))
{
/* Seems to be empty. At least we detected this in collect_nodes. */
if
(
get_irn_link
(
b
)
==
NULL
)
{
/* There are no Phi nodes ==> all predecessors are dispensable. */
n_preds
=
get_Block_n_cfgpreds
(
pred
);
}
else
{
/* b's pred blocks and pred's pred blocks must be pairwise disjunct.
Handle all pred blocks with preds < pos as if they were already removed. */
for
(
i
=
0
;
i
<
pos
;
i
++
)
{
ir_node
*
b_pred
=
get_Block_cfgpred_block
(
b
,
i
);
if
(
!
is_Bad
(
b_pred
)
&&
is_Block_removable
(
b_pred
))
{
for
(
j
=
get_Block_n_cfgpreds
(
b_pred
)
-
1
;
j
>=
0
;
--
j
)
{
ir_node
*
b_pred_pred
=
get_Block_cfgpred_block
(
b_pred
,
j
);
if
(
is_pred_of
(
b_pred_pred
,
pred
))
goto
non_dispensable
;
}
}
else
{
if
(
is_pred_of
(
b_pred
,
pred
))
if
(
!
is_Block_removable
(
predb
))
return
1
;
/* can't remove self-loops */
if
(
predb
==
b
)
goto
non_dispensable
;
if
(
is_unknown_jump
(
pred
))
goto
non_dispensable
;
/* Seems to be empty. At least we detected this in collect_nodes. */
if
(
get_irn_link
(
b
)
!=
NULL
)
{
int
n_cfgpreds
=
get_Block_n_cfgpreds
(
b
);
int
i
;
/* there are Phi nodes */
/* b's pred blocks and pred's pred blocks must be pairwise disjunct.
* Handle all pred blocks with preds < pos as if they were already
* removed. */
for
(
i
=
0
;
i
<
pos
;
i
++
)
{
ir_node
*
other_pred
=
get_Block_cfgpred
(
b
,
i
);
ir_node
*
other_predb
=
get_nodes_block
(
other_pred
);
if
(
is_Bad
(
other_pred
))
continue
;
if
(
is_Block_removable
(
other_predb
)
&&
!
Block_block_visited
(
other_predb
))
{
int
j
;
for
(
j
=
get_Block_n_cfgpreds
(
other_predb
)
-
1
;
j
>=
0
;
--
j
)
{
ir_node
*
other_predpred
=
get_Block_cfgpred_block
(
other_predb
,
j
);
if
(
is_pred_of
(
other_predpred
,
predb
))
goto
non_dispensable
;
}
}
else
if
(
is_pred_of
(
other_predb
,
predb
))
{
goto
non_dispensable
;
}
for
(
i
=
pos
+
1
;
i
<
get_Block_n_cfgpreds
(
b
);
i
++
)
{
ir_node
*
b_pred
=
get_Block_cfgpred_block
(
b
,
i
);
if
(
is_pred_of
(
b_pred
,
pred
))
goto
non_dispensable
;
}
/* if we get here, the block is dispensable */
n_preds
=
get_Block_n_cfgpreds
(
pred
);
}
for
(
i
=
pos
+
1
;
i
<
n_cfgpreds
;
i
++
)
{
ir_node
*
other_predb
=
get_Block_cfgpred_block
(
b
,
i
);
if
(
is_pred_of
(
other_predb
,
predb
))
goto
non_dispensable
;
}
}
return
n_preds
;
/* we will not dispense already visited blocks */
if
(
Block_block_visited
(
predb
))
return
1
;
/* if we get here, the block is dispensable, count useful preds */
return
count_non_bad_inputs
(
predb
);
non_dispensable:
set_Block_removable
(
pred
,
false
);
set_Block_removable
(
pred
b
,
false
);
return
1
;
}
...
...
@@ -287,18 +316,20 @@ static void optimize_blocks(ir_node *b, void *ctx)
ir_node
*
phi_pred
=
get_Phi_pred
(
phi
,
i
);
for
(
j
=
0
,
k
=
get_Block_n_cfgpreds
(
pred
);
j
<
k
;
j
++
)
{
ir_node
*
pred_pred
=
get_Block_cfgpred
(
pred
,
j
);
/* because of breaking loops, not all predecessors are
* Bad-clean, so we must check this here again */
if
(
!
is_Bad
(
get_Block_cfgpred
(
pred
,
j
)))
{
if
(
get_nodes_block
(
phi_pred
)
==
pred
)
{
/* case Phi 2a: */
assert
(
is_Phi
(
phi_pred
));
/* Block is empty!! */
if
(
is_Bad
(
pred_pred
))
continue
;
in
[
p_preds
++
]
=
get_Phi_pred
(
phi_pred
,
j
);
}
else
{
/* case Phi 2b: */
in
[
p_preds
++
]
=
phi_pred
;
}
if
(
get_nodes_block
(
phi_pred
)
==
pred
)
{
/* case Phi 2a: */
assert
(
is_Phi
(
phi_pred
));
/* Block is empty!! */
in
[
p_preds
++
]
=
get_Phi_pred
(
phi_pred
,
j
);
}
else
{
/* case Phi 2b: */
in
[
p_preds
++
]
=
phi_pred
;
}
}
}
else
{
...
...
@@ -306,7 +337,7 @@ static void optimize_blocks(ir_node *b, void *ctx)
in
[
p_preds
++
]
=
get_Phi_pred
(
phi
,
i
);
}
}
assert
(
p_preds
<
=
max_preds
);
assert
(
p_preds
=
=
max_preds
);
/* Fix the node */
if
(
p_preds
==
1
)
...
...
@@ -321,9 +352,9 @@ static void optimize_blocks(ir_node *b, void *ctx)
Moreover, it is only needed if predb is the direct dominator of b,
else there can be no uses of the Phi's in predb ... -*/
for
(
k
=
0
,
n
=
get_Block_n_cfgpreds
(
b
);
k
<
n
;
++
k
)
{
ir_node
*
pred
b
=
get_nodes_block
(
get_Block_cfgpred
(
b
,
k
)
)
;
if
(
is_Bad
(
pred
b
))
ir_node
*
pred
=
get_Block_cfgpred
(
b
,
k
);
ir_node
*
predb
=
get_nodes_block
(
pred
);
if
(
is_Bad
(
pred
))
continue
;
if
(
is_Block_removable
(
predb
)
&&
!
Block_block_visited
(
predb
))
{
...
...
@@ -406,35 +437,38 @@ static void optimize_blocks(ir_node *b, void *ctx)
/*- Fix the block -*/
n_preds
=
0
;
for
(
i
=
0
;
i
<
get_Block_n_cfgpreds
(
b
);
i
++
)
{
pred
=
get_Block_cfgpred_block
(
b
,
i
);
ir_node
*
pred
=
get_Block_cfgpred
(
b
,
i
);
ir_node
*
predb
=
get_nodes_block
(
pred
);
if
(
is_Bad
(
pred
))
{
/* case 1: Do nothing */
}
else
if
(
is_Block_removable
(
pred
)
&&
!
Block_block_visited
(
pred
))
{
/* case 1: Do nothing */
if
(
is_Bad
(
pred
))
continue
;
if
(
is_Block_removable
(
predb
)
&&
!
Block_block_visited
(
predb
))
{
/* case 2: It's an empty block and not yet visited. */
assert
(
get_Block_n_cfgpreds
(
b
)
>
1
||
has_Block_entity
(
b
));
/* Else it should be optimized by equivalent_node. */
for
(
j
=
0
;
j
<
get_Block_n_cfgpreds
(
pred
);
j
++
)
{
ir_node
*
pred_X
=
get_Block_cfgpred
(
pred
,
j
);
/* because of breaking loops, not all predecessors are Bad-clean,
* so we must check this here again */
if
(
!
is_Bad
(
pred_X
))
in
[
n_preds
++
]
=
pred_X
;
for
(
j
=
0
;
j
<
get_Block_n_cfgpreds
(
predb
);
j
++
)
{
ir_node
*
predpred
=
get_Block_cfgpred
(
predb
,
j
);
/* because of breaking loops, not all predecessors are
* Bad-clean, so we must check this here again */
if
(
is_Bad
(
predpred
))
continue
;
in
[
n_preds
++
]
=
predpred
;
}
/* Remove block as it might be kept alive. */
exchange
(
pred
,
b
/*get_irg_bad(irg)*/
);
/* Remove block+jump as it might be kept alive. */
exchange
(
pred
,
get_irg_bad
(
get_irn_irg
(
b
)));
exchange
(
predb
,
get_irg_bad
(
get_irn_irg
(
b
)));
}
else
{
/* case 3: */
in
[
n_preds
++
]
=
get_Block_cfgpred
(
b
,
i
)
;
in
[
n_preds
++
]
=
pred
;
}
}
assert
(
n_preds
<
=
max_preds
);
assert
(
n_preds
=
=
max_preds
);
set_irn_in
(
b
,
n_preds
,
in
);
env
->
changed
=
true
;
assert
(
get_irn_link
(
b
)
==
NULL
||
p_preds
==
-
1
||
(
n_preds
==
p_preds
&&
"Wrong Phi Fix"
));
/* see if phi-fix was correct */
assert
(
get_irn_link
(
b
)
==
NULL
||
p_preds
==
-
1
||
(
n_preds
==
p_preds
));
xfree
(
in
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment