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
c56025f3
Commit
c56025f3
authored
Oct 30, 2013
by
Matthias Braun
Browse files
cleanup, use C99
parent
dc38d853
Changes
1
Show whitespace changes
Inline
Side-by-side
ir/opt/jumpthreading.c
View file @
c56025f3
...
...
@@ -51,14 +51,8 @@ static ir_node *ssa_second_def;
static
ir_node
*
ssa_second_def_block
;
static
ir_node
*
search_def_and_create_phis
(
ir_node
*
block
,
ir_mode
*
mode
,
int
first
)
bool
first
)
{
int
i
;
int
n_cfgpreds
;
ir_graph
*
irg
;
ir_node
*
phi
;
ir_node
*
dummy
;
/* In case of a bad input to a block we need to return the bad value */
if
(
is_Bad
(
block
))
{
ir_graph
*
irg
=
get_irn_irg
(
block
);
...
...
@@ -80,15 +74,15 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode,
return
value
;
}
irg
=
get_irn_irg
(
block
);
ir_graph
*
irg
=
get_irn_irg
(
block
);
assert
(
block
!=
get_irg_start_block
(
irg
));
/* a Block with only 1 predecessor needs no Phi */
n_cfgpreds
=
get_Block_n_cfgpreds
(
block
);
int
n_cfgpreds
=
get_Block_n_cfgpreds
(
block
);
if
(
n_cfgpreds
==
1
)
{
ir_node
*
pred_block
=
get_Block_cfgpred_block
(
block
,
0
);
ir_node
*
value
=
search_def_and_create_phis
(
pred_block
,
mode
,
0
);
ir_node
*
value
=
search_def_and_create_phis
(
pred_block
,
mode
,
false
);
set_irn_link
(
block
,
value
);
mark_irn_visited
(
block
);
return
value
;
...
...
@@ -96,19 +90,19 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode,
/* create a new Phi */
ir_node
**
in
=
ALLOCAN
(
ir_node
*
,
n_cfgpreds
);
dummy
=
new_r_Dummy
(
irg
,
mode
);
for
(
i
=
0
;
i
<
n_cfgpreds
;
++
i
)
ir_node
*
dummy
=
new_r_Dummy
(
irg
,
mode
);
for
(
int
i
=
0
;
i
<
n_cfgpreds
;
++
i
)
in
[
i
]
=
dummy
;
phi
=
new_r_Phi
(
block
,
n_cfgpreds
,
in
,
mode
);
ir_node
*
phi
=
new_r_Phi
(
block
,
n_cfgpreds
,
in
,
mode
);
set_irn_link
(
block
,
phi
);
mark_irn_visited
(
block
);
/* set Phi predecessors */
for
(
i
=
0
;
i
<
n_cfgpreds
;
++
i
)
{
for
(
int
i
=
0
;
i
<
n_cfgpreds
;
++
i
)
{
ir_node
*
pred_block
=
get_Block_cfgpred_block
(
block
,
i
);
ir_node
*
pred_val
=
search_def_and_create_phis
(
pred_block
,
mode
,
0
);
ir_node
*
pred_val
=
search_def_and_create_phis
(
pred_block
,
mode
,
false
);
set_irn_n
(
phi
,
i
,
pred_val
);
}
...
...
@@ -123,17 +117,14 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode,
static
void
construct_ssa
(
ir_node
*
orig_block
,
ir_node
*
orig_val
,
ir_node
*
second_block
,
ir_node
*
second_val
)
{
ir_graph
*
irg
;
ir_mode
*
mode
;
/* no need to do anything */
if
(
orig_val
==
second_val
)
return
;
irg
=
get_irn_irg
(
orig_val
);
ir_graph
*
irg
=
get_irn_irg
(
orig_val
);
inc_irg_visited
(
irg
);
mode
=
get_irn_mode
(
orig_val
);
ir_mode
*
mode
=
get_irn_mode
(
orig_val
);
set_irn_link
(
orig_block
,
orig_val
);
mark_irn_visited
(
orig_block
);
...
...
@@ -143,26 +134,27 @@ static void construct_ssa(ir_node *orig_block, ir_node *orig_val,
/* Only fix the users of the first, i.e. the original node */
foreach_out_edge_safe
(
orig_val
,
edge
)
{
ir_node
*
user
=
get_edge_src_irn
(
edge
);
int
j
=
get_edge_src_pos
(
edge
);
ir_node
*
user_block
=
get_nodes_block
(
user
);
ir_node
*
newval
;
/* ignore keeps */
if
(
is_End
(
user
))
continue
;
DB
((
dbg
,
LEVEL_3
,
">>> Fixing user %+F (pred %d == %+F)
\n
"
,
user
,
j
,
get_irn_n
(
user
,
j
)));
int
j
=
get_edge_src_pos
(
edge
);
DB
((
dbg
,
LEVEL_3
,
">>> Fixing user %+F (pred %d == %+F)
\n
"
,
user
,
j
,
get_irn_n
(
user
,
j
)));
ir_node
*
user_block
=
get_nodes_block
(
user
);
ir_node
*
newval
;
if
(
is_Phi
(
user
))
{
ir_node
*
pred_block
=
get_Block_cfgpred_block
(
user_block
,
j
);
newval
=
search_def_and_create_phis
(
pred_block
,
mode
,
1
);
newval
=
search_def_and_create_phis
(
pred_block
,
mode
,
true
);
}
else
{
newval
=
search_def_and_create_phis
(
user_block
,
mode
,
1
);
newval
=
search_def_and_create_phis
(
user_block
,
mode
,
true
);
}
/* don't fix newly created Phis from the SSA construction */
if
(
newval
!=
user
)
{
DB
((
dbg
,
LEVEL_4
,
">>>> Setting input %d of %+F to %+F
\n
"
,
j
,
user
,
newval
));
DB
((
dbg
,
LEVEL_4
,
">>>> Setting input %d of %+F to %+F
\n
"
,
j
,
user
,
newval
));
set_irn_n
(
user
,
j
,
newval
);
}
}
...
...
@@ -181,24 +173,20 @@ static void construct_ssa(ir_node *orig_block, ir_node *orig_val,
static
void
split_critical_edge
(
ir_node
*
block
,
int
pos
)
{
ir_graph
*
irg
=
get_irn_irg
(
block
);
ir_node
*
in
[
1
];
ir_node
*
new_block
;
ir_node
*
new_jmp
;
in
[
0
]
=
get_Block_cfgpred
(
block
,
pos
);
new_block
=
new_r_Block
(
irg
,
1
,
in
);
new_jmp
=
new_r_Jmp
(
new_block
);
ir_node
*
in
[]
=
{
get_Block_cfgpred
(
block
,
pos
)
};
ir_node
*
new_block
=
new_r_Block
(
irg
,
ARRAY_SIZE
(
in
),
in
);
ir_node
*
new_jmp
=
new_r_Jmp
(
new_block
);
set_Block_cfgpred
(
block
,
pos
,
new_jmp
);
}
typedef
struct
jumpthreading_env_t
{
ir_node
*
true_block
;
ir_node
*
cmp
;
/**< The Compare node that might be partial evaluated */
ir_node
*
cmp
;
/**< The Compare node that might be partial
evaluated */
ir_relation
relation
;
/**< The Compare mode of the Compare node. */
ir_node
*
cnst
;
ir_tarval
*
tv
;
ir_visited_t
visited_nr
;
ir_node
*
cnst_pred
;
/**< the block before the constant */
int
cnst_pos
;
/**< the pos to the constant block (needed to
kill that edge later) */
...
...
@@ -208,10 +196,8 @@ static ir_node *copy_and_fix_node(const jumpthreading_env_t *env,
ir_node
*
block
,
ir_node
*
copy_block
,
int
j
,
ir_node
*
node
)
{
int
i
,
arity
;
ir_node
*
copy
;
/* we can evaluate Phis right now, all other nodes get copied */
ir_node
*
copy
;
if
(
is_Phi
(
node
))
{
copy
=
get_Phi_pred
(
node
,
j
);
/* we might have to evaluate a Phi-cascade */
...
...
@@ -221,17 +207,14 @@ static ir_node *copy_and_fix_node(const jumpthreading_env_t *env,
}
else
{
copy
=
exact_copy
(
node
);
set_nodes_block
(
copy
,
copy_block
);
assert
(
get_irn_mode
(
copy
)
!=
mode_X
);
arity
=
get_irn_arity
(
copy
);
for
(
i
=
0
;
i
<
arity
;
++
i
)
{
for
(
int
i
=
0
,
arity
=
get_irn_arity
(
copy
);
i
<
arity
;
++
i
)
{
ir_node
*
pred
=
get_irn_n
(
copy
,
i
);
ir_node
*
new_pred
;
if
(
get_nodes_block
(
pred
)
!=
block
)
continue
;
ir_node
*
new_pred
;
if
(
get_irn_visited
(
pred
)
>=
env
->
visited_nr
)
{
new_pred
=
(
ir_node
*
)
get_irn_link
(
pred
);
}
else
{
...
...
@@ -254,18 +237,14 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
/* Look at all nodes in the cond_block and copy them into pred */
foreach_out_edge
(
block
,
edge
)
{
ir_node
*
node
=
get_edge_src_irn
(
edge
);
ir_node
*
copy
;
ir_mode
*
mode
;
if
(
is_End
(
node
))
{
/* edge is a Keep edge. If the end block is unreachable via normal
* control flow, we must maintain end's reachability with Keeps.
*/
* control flow, we must maintain end's reachability with Keeps. */
keep_alive
(
copy_block
);
continue
;
}
/* ignore control flow */
mode
=
get_irn_mode
(
node
);
ir_mode
*
mode
=
get_irn_mode
(
node
);
if
(
mode
==
mode_X
||
is_Cond
(
node
)
||
is_Switch
(
node
))
continue
;
#ifdef AVOID_PHIB
...
...
@@ -287,14 +266,13 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
cmp_copy
=
exact_copy
(
pred
);
set_nodes_block
(
cmp_copy
,
user_block
);
copy
=
new_r_Proj
(
cmp_copy
,
mode_b
,
pn
);
ir_node
*
copy
=
new_r_Proj
(
cmp_copy
,
mode_b
,
pn
);
set_irn_n
(
user
,
pos
,
copy
);
}
continue
;
}
#endif
copy
=
copy_and_fix_node
(
env
,
block
,
copy_block
,
j
,
node
);
ir_node
*
copy
=
copy_and_fix_node
(
env
,
block
,
copy_block
,
j
,
node
);
/* we might hit values in blocks that have already been processed by a
* recursive find_phi_with_const() call */
...
...
@@ -309,10 +287,7 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
/* fix data-flow (and reconstruct SSA if needed) */
foreach_out_edge
(
block
,
edge
)
{
ir_node
*
node
=
get_edge_src_irn
(
edge
);
ir_node
*
copy_node
;
ir_mode
*
mode
;
mode
=
get_irn_mode
(
node
);
ir_mode
*
mode
=
get_irn_mode
(
node
);
if
(
mode
==
mode_X
||
is_Cond
(
node
)
||
is_Switch
(
node
))
continue
;
#ifdef AVOID_PHIB
...
...
@@ -322,7 +297,7 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
DB
((
dbg
,
LEVEL_2
,
">> Fixing users of %+F
\n
"
,
node
));
copy_node
=
(
ir_node
*
)
get_irn_link
(
node
);
ir_node
*
copy_node
=
(
ir_node
*
)
get_irn_link
(
node
);
construct_ssa
(
block
,
node
,
copy_block
,
copy_node
);
}
...
...
@@ -339,12 +314,12 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
}
/**
* returns whether the cmp evaluates to true or false, or can't be evaluated!
* 1: true, 0: false, -1: can't evaluate
* Returns whether the cmp evaluates to true or false, or can't be evaluated!
*
* @param relation the compare mode of the Compare
* @param tv_left the left tarval
* @param tv_right the right tarval
* @returns 1: true, 0: false, -1: can't evaluate
*/
static
int
eval_cmp_tv
(
ir_relation
relation
,
ir_tarval
*
tv_left
,
ir_tarval
*
tv_right
)
...
...
@@ -361,22 +336,22 @@ static int eval_cmp_tv(ir_relation relation, ir_tarval *tv_left,
}
/**
* returns whether the cmp evaluates to true or false, or can't be evaluated!
* 1: true, 0: false, -1: can't evaluate
* Returns whether the cmp evaluates to true or false, or can't be evaluated!
*
* @param env the environment
* @param cand the candidate node, either a Const or a Confirm
* @returns 1: true, 0: false, -1: can't evaluate
*/
static
int
eval_cmp
(
jumpthreading_env_t
*
env
,
ir_node
*
cand
)
{
if
(
is_Const
(
cand
))
{
ir_tarval
*
tv_cand
=
get_Const_tarval
(
cand
);
ir_tarval
*
tv_cmp
=
get_Const_tarval
(
env
->
cnst
);
return
eval_cmp_tv
(
env
->
relation
,
tv_cand
,
tv_cmp
);
}
else
{
/* a Confirm */
ir_tarval
*
res
=
computed_value_Cmp_Confirm
(
env
->
cmp
,
cand
,
env
->
cnst
,
env
->
relation
);
}
else
{
assert
(
is_Confirm
(
cand
));
ir_tarval
*
res
=
computed_value_Cmp_Confirm
(
env
->
cmp
,
cand
,
env
->
cnst
,
env
->
relation
);
if
(
res
==
tarval_bad
)
return
-
1
;
return
res
==
tarval_b_true
;
...
...
@@ -386,7 +361,7 @@ static int eval_cmp(jumpthreading_env_t *env, ir_node *cand)
/**
* Check for Const or Confirm with Const.
*/
static
int
is_Const_or_Confirm
(
const
ir_node
*
node
)
static
bool
is_Const_or_Confirm
(
const
ir_node
*
node
)
{
if
(
is_Confirm
(
node
))
node
=
get_Confirm_bound
(
node
);
...
...
@@ -398,30 +373,24 @@ static int is_Const_or_Confirm(const ir_node *node)
*/
static
ir_tarval
*
get_Const_or_Confirm_tarval
(
const
ir_node
*
node
)
{
if
(
is_Confirm
(
node
))
{
if
(
get_Confirm_bound
(
node
))
if
(
is_Confirm
(
node
))
node
=
get_Confirm_bound
(
node
);
}
return
get_Const_tarval
(
node
);
}
static
ir_node
*
find_const_or_confirm
(
jumpthreading_env_t
*
env
,
ir_node
*
jump
,
ir_node
*
value
)
{
ir_node
*
block
=
get_nodes_block
(
jump
);
if
(
irn_visited_else_mark
(
value
))
return
NULL
;
ir_node
*
block
=
get_nodes_block
(
jump
);
if
(
is_Const_or_Confirm
(
value
))
{
if
(
eval_cmp
(
env
,
value
)
<=
0
)
return
NULL
;
DB
((
dbg
,
LEVEL_1
,
"> Found jump threading candidate %+F->%+F
\n
"
,
block
,
env
->
true_block
));
DB
((
dbg
,
LEVEL_1
,
"> Found jump threading candidate %+F->%+F
\n
"
,
block
,
env
->
true_block
));
/* adjust true_block to point directly towards our jump */
add_pred
(
env
->
true_block
,
jump
);
...
...
@@ -430,30 +399,23 @@ static ir_node *find_const_or_confirm(jumpthreading_env_t *env, ir_node *jump,
/* we need a bigger visited nr when going back */
env
->
visited_nr
++
;
return
block
;
}
if
(
is_Phi
(
value
))
{
int
i
,
arity
;
/* the Phi has to be in the same Block as the Jmp */
if
(
get_nodes_block
(
value
)
!=
block
)
return
NULL
;
arity
=
get_irn_arity
(
value
);
for
(
i
=
0
;
i
<
arity
;
++
i
)
{
ir_node
*
copy_block
;
for
(
int
i
=
0
,
arity
=
get_irn_arity
(
value
);
i
<
arity
;
++
i
)
{
ir_node
*
phi_pred
=
get_Phi_pred
(
value
,
i
);
ir_node
*
cfgpred
=
get_Block_cfgpred
(
block
,
i
);
copy_block
=
find_const_or_confirm
(
env
,
cfgpred
,
phi_pred
);
ir_node
*
copy_block
=
find_const_or_confirm
(
env
,
cfgpred
,
phi_pred
);
if
(
copy_block
==
NULL
)
continue
;
/* copy duplicated nodes in copy_block and fix SSA */
copy_and_fix
(
env
,
block
,
copy_block
,
i
);
if
(
copy_block
==
get_nodes_block
(
cfgpred
))
{
env
->
cnst_pred
=
block
;
env
->
cnst_pos
=
i
;
...
...
@@ -470,23 +432,17 @@ static ir_node *find_const_or_confirm(jumpthreading_env_t *env, ir_node *jump,
static
ir_node
*
find_candidate
(
jumpthreading_env_t
*
env
,
ir_node
*
jump
,
ir_node
*
value
)
{
ir_node
*
block
=
get_nodes_block
(
jump
);
if
(
irn_visited_else_mark
(
value
))
{
if
(
irn_visited_else_mark
(
value
))
return
NULL
;
}
ir_node
*
block
=
get_nodes_block
(
jump
);
if
(
is_Const_or_Confirm
(
value
))
{
ir_tarval
*
tv
=
get_Const_or_Confirm_tarval
(
value
);
if
(
tv
!=
env
->
tv
)
return
NULL
;
DB
((
dbg
,
LEVEL_1
,
"> Found jump threading candidate %+F->%+F
\n
"
,
block
,
env
->
true_block
));
DB
((
dbg
,
LEVEL_1
,
"> Found jump threading candidate %+F->%+F
\n
"
,
block
,
env
->
true_block
));
/* adjust true_block to point directly towards our jump */
add_pred
(
env
->
true_block
,
jump
);
...
...
@@ -495,29 +451,22 @@ static ir_node *find_candidate(jumpthreading_env_t *env, ir_node *jump,
/* we need a bigger visited nr when going back */
env
->
visited_nr
++
;
return
block
;
}
if
(
is_Phi
(
value
))
{
int
i
,
arity
;
/* the Phi has to be in the same Block as the Jmp */
if
(
get_nodes_block
(
value
)
!=
block
)
return
NULL
;
arity
=
get_irn_arity
(
value
);
for
(
i
=
0
;
i
<
arity
;
++
i
)
{
ir_node
*
copy_block
;
for
(
int
i
=
0
,
arity
=
get_irn_arity
(
value
);
i
<
arity
;
++
i
)
{
ir_node
*
phi_pred
=
get_Phi_pred
(
value
,
i
);
ir_node
*
cfgpred
=
get_Block_cfgpred
(
block
,
i
);
copy_block
=
find_candidate
(
env
,
cfgpred
,
phi_pred
);
ir_node
*
copy_block
=
find_candidate
(
env
,
cfgpred
,
phi_pred
);
if
(
copy_block
==
NULL
)
continue
;
/* copy duplicated nodes in copy_block and fix SSA */
copy_and_fix
(
env
,
block
,
copy_block
,
i
);
if
(
copy_block
==
get_nodes_block
(
cfgpred
))
{
env
->
cnst_pred
=
block
;
env
->
cnst_pos
=
i
;
...
...
@@ -550,15 +499,13 @@ static ir_node *find_candidate(jumpthreading_env_t *env, ir_node *jump,
return
NULL
;
/* negate condition when we're looking for the false block */
if
(
env
->
tv
==
tarval_b_false
)
{
if
(
env
->
tv
==
tarval_b_false
)
relation
=
get_negated_relation
(
relation
);
}
/* (recursively) look if a pred of a Phi is a constant or a Confirm */
env
->
cmp
=
cmp
;
env
->
relation
=
relation
;
env
->
cnst
=
right
;
return
find_const_or_confirm
(
env
,
jump
,
left
);
}
...
...
@@ -580,34 +527,24 @@ static ir_node *find_candidate(jumpthreading_env_t *env, ir_node *jump,
*/
static
void
thread_jumps
(
ir_node
*
block
,
void
*
data
)
{
jumpthreading_env_t
env
;
bool
*
changed
=
(
bool
*
)
data
;
ir_node
*
selector
;
ir_node
*
projx
;
ir_node
*
cond
;
ir_node
*
copy_block
;
int
selector_evaluated
;
ir_graph
*
irg
;
ir_node
*
badX
;
int
cnst_pos
;
/* we do not deal with Phis, so restrict this to exactly one cfgpred */
if
(
get_Block_n_cfgpreds
(
block
)
!=
1
)
return
;
projx
=
get_Block_cfgpred
(
block
,
0
);
ir_node
*
projx
=
get_Block_cfgpred
(
block
,
0
);
if
(
!
is_Proj
(
projx
))
return
;
assert
(
get_irn_mode
(
projx
)
==
mode_X
);
cond
=
get_Proj_pred
(
projx
);
ir_node
*
cond
=
get_Proj_pred
(
projx
);
/* TODO handle switch Conds */
if
(
!
is_Cond
(
cond
))
return
;
/* handle cases that can be immediately evaluated */
selector
=
get_Cond_selector
(
cond
);
selector_evaluated
=
-
1
;
ir_node
*
selector
=
get_Cond_selector
(
cond
);
int
selector_evaluated
=
-
1
;
if
(
is_Cmp
(
selector
))
{
ir_node
*
left
=
get_Cmp_left
(
selector
);
ir_node
*
right
=
get_Cmp_right
(
selector
);
...
...
@@ -628,6 +565,7 @@ static void thread_jumps(ir_node* block, void* data)
}
}
jumpthreading_env_t
env
;
env
.
cnst_pred
=
NULL
;
if
(
get_Proj_proj
(
projx
)
==
pn_Cond_false
)
{
env
.
tv
=
tarval_b_false
;
...
...
@@ -654,11 +592,11 @@ static void thread_jumps(ir_node* block, void* data)
/* (recursively) look if a pred of a Phi is a constant or a Confirm */
env
.
true_block
=
block
;
irg
=
get_irn_irg
(
block
);
ir_graph
*
irg
=
get_irn_irg
(
block
);
inc_irg_visited
(
irg
);
env
.
visited_nr
=
get_irg_visited
(
irg
);
copy_block
=
find_candidate
(
&
env
,
projx
,
selector
);
ir_node
*
copy_block
=
find_candidate
(
&
env
,
projx
,
selector
);
if
(
copy_block
==
NULL
)
return
;
...
...
@@ -669,8 +607,8 @@ static void thread_jumps(ir_node* block, void* data)
/* we have to remove the edge towards the pred as the pred now
* jumps into the true_block. We also have to shorten Phis
* in our block because of this */
badX
=
new_r_Bad
(
irg
,
mode_X
);
cnst_pos
=
env
.
cnst_pos
;
ir_node
*
badX
=
new_r_Bad
(
irg
,
mode_X
);
int
cnst_pos
=
env
.
cnst_pos
;
/* shorten Phis */
foreach_out_edge_safe
(
env
.
cnst_pred
,
edge
)
{
...
...
@@ -690,9 +628,6 @@ static void thread_jumps(ir_node* block, void* data)
void
opt_jumpthreading
(
ir_graph
*
irg
)
{
bool
changed
;
bool
rerun
;
assure_irg_properties
(
irg
,
IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE
|
IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES
...
...
@@ -704,7 +639,8 @@ void opt_jumpthreading(ir_graph* irg)
ir_reserve_resources
(
irg
,
IR_RESOURCE_IRN_LINK
|
IR_RESOURCE_IRN_VISITED
);
changed
=
false
;
bool
changed
=
false
;
bool
rerun
;
do
{
rerun
=
false
;
irg_block_walk_graph
(
irg
,
thread_jumps
,
NULL
,
&
rerun
);
...
...
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