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
37b1db4c
Commit
37b1db4c
authored
Oct 28, 2016
by
Christoph Mallon
Browse files
be: Factor out code to get the Projs of conditional branches.
parent
ac97d7f3
Changes
7
Hide whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
37b1db4c
...
...
@@ -673,51 +673,40 @@ static x86_condition_code_t determine_final_cc(ir_node const *const flags,
*/
static
void
emit_amd64_jcc
(
const
ir_node
*
irn
)
{
const
ir_node
*
proj_true
=
NULL
;
const
ir_node
*
proj_false
=
NULL
;
const
ir_node
*
flags
=
get_irn_n
(
irn
,
n_amd64_jcc_eflags
);
const
amd64_cc_attr_t
*
attr
=
get_amd64_cc_attr_const
(
irn
);
x86_condition_code_t
cc
=
determine_final_cc
(
flags
,
attr
->
cc
);
foreach_out_edge
(
irn
,
edge
)
{
ir_node
*
proj
=
get_edge_src_irn
(
edge
);
unsigned
nr
=
get_Proj_num
(
proj
);
if
(
nr
==
pn_Cond_true
)
{
proj_true
=
proj
;
}
else
{
proj_false
=
proj
;
}
}
be_cond_branch_projs_t
projs
=
be_get_cond_branch_projs
(
irn
);
ir_node
const
*
const
block
=
get_nodes_block
(
irn
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
_true
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
s
.
t
);
if
(
be_emit_get_prev_block
(
true_target
)
==
block
)
{
/* exchange both proj's so the second one can be omitted */
const
ir_node
*
t
=
proj_true
;
proj_true
=
proj_false
;
proj_false
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
ir_node
*
const
t
=
projs
.
t
;
projs
.
t
=
projs
.
f
;
projs
.
f
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
}
if
(
cc
&
x86_cc_float_parity_cases
)
{
/* Some floating point comparisons require a test of the parity flag,
* which indicates that the result is unordered */
if
(
cc
&
x86_cc_negated
)
{
amd64_emitf
(
proj
_true
,
"jp %L"
);
amd64_emitf
(
proj
s
.
t
,
"jp %L"
);
}
else
{
amd64_emitf
(
proj
_false
,
"jp %L"
);
amd64_emitf
(
proj
s
.
f
,
"jp %L"
);
}
}
/* emit the true proj */
amd64_emitf
(
proj
_true
,
"j%PX %L"
,
(
int
)
cc
);
amd64_emitf
(
proj
s
.
t
,
"j%PX %L"
,
(
int
)
cc
);
ir_node
const
*
const
false_target
=
be_emit_get_cfop_target
(
proj
_false
);
ir_node
const
*
const
false_target
=
be_emit_get_cfop_target
(
proj
s
.
f
);
if
(
be_emit_get_prev_block
(
false_target
)
!=
block
)
{
amd64_emitf
(
proj
_false
,
"jmp %L"
);
amd64_emitf
(
proj
s
.
f
,
"jmp %L"
);
}
else
if
(
be_options
.
verbose_asm
)
{
amd64_emitf
(
proj
_false
,
"/* fallthrough to %L */"
);
amd64_emitf
(
proj
s
.
f
,
"/* fallthrough to %L */"
);
}
}
...
...
ir/be/arm/arm_emitter.c
View file @
37b1db4c
...
...
@@ -393,17 +393,7 @@ static void emit_arm_fConst(const ir_node *irn)
*/
static
void
emit_arm_B
(
const
ir_node
*
irn
)
{
const
ir_node
*
proj_true
=
NULL
;
const
ir_node
*
proj_false
=
NULL
;
foreach_out_edge
(
irn
,
edge
)
{
ir_node
*
proj
=
get_edge_src_irn
(
edge
);
unsigned
nr
=
get_Proj_num
(
proj
);
if
(
nr
==
pn_Cond_true
)
{
proj_true
=
proj
;
}
else
{
proj_false
=
proj
;
}
}
be_cond_branch_projs_t
projs
=
be_get_cond_branch_projs
(
irn
);
ir_node
*
const
op1
=
get_irn_n
(
irn
,
n_arm_B_flags
);
assert
(
is_arm_Cmn
(
op1
)
||
is_arm_Cmp
(
op1
)
||
is_arm_Tst
(
op1
));
...
...
@@ -418,14 +408,13 @@ static void emit_arm_B(const ir_node *irn)
assert
(
relation
!=
ir_relation_true
);
ir_node
const
*
const
block
=
get_nodes_block
(
irn
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
_true
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
s
.
t
);
if
(
be_emit_get_prev_block
(
true_target
)
==
block
)
{
/* exchange both proj's so the second one can be omitted */
const
ir_node
*
t
=
proj_true
;
proj_true
=
proj_false
;
proj_false
=
t
;
relation
=
get_negated_relation
(
relation
);
ir_node
*
const
t
=
projs
.
t
;
projs
.
t
=
projs
.
f
;
projs
.
f
=
t
;
relation
=
get_negated_relation
(
relation
);
}
char
const
*
suffix
;
...
...
@@ -442,13 +431,13 @@ static void emit_arm_B(const ir_node *irn)
}
/* emit the true proj */
arm_emitf
(
irn
,
"b%s %t"
,
suffix
,
proj
_true
);
arm_emitf
(
irn
,
"b%s %t"
,
suffix
,
proj
s
.
t
);
ir_node
const
*
const
false_target
=
be_emit_get_cfop_target
(
proj
_false
);
ir_node
const
*
const
false_target
=
be_emit_get_cfop_target
(
proj
s
.
f
);
if
(
be_emit_get_prev_block
(
false_target
)
!=
block
)
{
arm_emitf
(
irn
,
"b %t"
,
proj
_false
);
arm_emitf
(
irn
,
"b %t"
,
proj
s
.
f
);
}
else
if
(
be_options
.
verbose_asm
)
{
arm_emitf
(
irn
,
"/* fallthrough to %t */"
,
proj
_false
);
arm_emitf
(
irn
,
"/* fallthrough to %t */"
,
proj
s
.
f
);
}
}
...
...
ir/be/beemithlp.c
View file @
37b1db4c
...
...
@@ -17,6 +17,7 @@
#include "dbginfo.h"
#include "debug.h"
#include "firm_types.h"
#include "iredges.h"
#include "irnode_t.h"
#include "irop_t.h"
#include "util.h"
...
...
@@ -68,3 +69,19 @@ void be_emit_init_cf_links(ir_node **const block_schedule)
prev
=
block
;
}
}
be_cond_branch_projs_t
be_get_cond_branch_projs
(
ir_node
const
*
const
node
)
{
be_cond_branch_projs_t
projs
=
{
NULL
,
NULL
};
foreach_out_edge
(
node
,
edge
)
{
ir_node
*
const
proj
=
get_edge_src_irn
(
edge
);
unsigned
const
pn
=
get_Proj_num
(
proj
);
switch
(
pn
)
{
case
pn_Cond_false
:
projs
.
f
=
proj
;
continue
;
case
pn_Cond_true
:
projs
.
t
=
proj
;
continue
;
}
panic
(
"invalid Proj for branch"
);
}
assert
(
projs
.
f
&&
projs
.
t
);
return
projs
;
}
ir/be/beemithlp.h
View file @
37b1db4c
...
...
@@ -71,4 +71,11 @@ static inline ir_node *be_emit_get_prev_block(ir_node const *const block)
return
(
ir_node
*
)
get_irn_link
(
block
);
}
typedef
struct
be_cond_branch_projs_t
{
ir_node
*
f
;
ir_node
*
t
;
}
be_cond_branch_projs_t
;
be_cond_branch_projs_t
be_get_cond_branch_projs
(
ir_node
const
*
node
);
#endif
ir/be/ia32/ia32_emitter.c
View file @
37b1db4c
...
...
@@ -689,20 +689,18 @@ static void emit_ia32_Jcc(const ir_node *node)
{
x86_condition_code_t
cc
=
ia32_determine_final_cc
(
node
,
n_ia32_Jcc_eflags
);
/* get both Projs */
ir_node
const
*
proj_true
=
get_Proj_for_pn
(
node
,
pn_ia32_Jcc_true
);
ir_node
const
*
target_true
=
be_emit_get_cfop_target
(
proj_true
);
ir_node
const
*
proj_false
=
get_Proj_for_pn
(
node
,
pn_ia32_Jcc_false
);
be_cond_branch_projs_t
projs
=
be_get_cond_branch_projs
(
node
);
ir_node
const
*
target_true
=
be_emit_get_cfop_target
(
projs
.
t
);
ir_node
const
*
block
=
get_nodes_block
(
node
);
if
(
fallthrough_possible
(
block
,
target_true
))
{
/* exchange both proj's so the second one can be omitted */
const
ir_node
*
t
=
proj_true
;
proj_true
=
proj_false
;
proj_false
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
ir_node
*
const
t
=
projs
.
t
;
projs
.
t
=
projs
.
f
;
projs
.
f
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
}
const
ir_node
*
target_false
=
be_emit_get_cfop_target
(
proj
_false
);
const
ir_node
*
target_false
=
be_emit_get_cfop_target
(
proj
s
.
f
);
bool
fallthrough
=
fallthrough_possible
(
block
,
target_false
);
/* if we can't have a fallthrough anyway, put the more likely case first */
if
(
!
fallthrough
)
{
...
...
@@ -711,10 +709,10 @@ static void emit_ia32_Jcc(const ir_node *node)
double
freq_true
=
get_block_execfreq
(
target_true
);
double
freq_false
=
get_block_execfreq
(
target_false
);
if
(
freq_false
>
freq_true
)
{
const
ir_node
*
t
=
proj
_true
;
proj
_true
=
proj
_false
;
proj
_false
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
ir_node
*
const
t
=
proj
s
.
t
;
proj
s
.
t
=
proj
s
.
f
;
proj
s
.
f
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
}
}
...
...
@@ -723,19 +721,19 @@ static void emit_ia32_Jcc(const ir_node *node)
/* Some floating point comparisons require a test of the parity flag,
* which indicates that the result is unordered */
if
(
cc
&
x86_cc_negated
)
{
ia32_emitf
(
proj
_true
,
"jp %L"
);
ia32_emitf
(
proj
s
.
t
,
"jp %L"
);
}
else
{
/* we need a local label if the false proj is a fallthrough
* as the falseblock might have no label emitted then */
if
(
fallthrough
)
{
need_parity_label
=
true
;
ia32_emitf
(
proj
_false
,
"jp 1f"
);
ia32_emitf
(
proj
s
.
f
,
"jp 1f"
);
}
else
{
ia32_emitf
(
proj
_false
,
"jp %L"
);
ia32_emitf
(
proj
s
.
f
,
"jp %L"
);
}
}
}
ia32_emitf
(
proj
_true
,
"j%PX %L"
,
(
int
)
cc
);
ia32_emitf
(
proj
s
.
t
,
"j%PX %L"
,
(
int
)
cc
);
if
(
need_parity_label
)
{
be_emit_cstring
(
"1:
\n
"
);
be_emit_write_line
();
...
...
@@ -743,9 +741,9 @@ static void emit_ia32_Jcc(const ir_node *node)
/* the second Proj might be a fallthrough */
if
(
!
fallthrough
)
{
ia32_emitf
(
proj
_false
,
"jmp %L"
);
ia32_emitf
(
proj
s
.
f
,
"jmp %L"
);
}
else
if
(
be_options
.
verbose_asm
)
{
ia32_emitf
(
proj
_false
,
"/* fallthrough to %L */"
);
ia32_emitf
(
proj
s
.
f
,
"/* fallthrough to %L */"
);
}
}
...
...
ir/be/ia32/ia32_encode.c
View file @
37b1db4c
...
...
@@ -951,21 +951,19 @@ static void enc_ia32_jcc(const ir_node *node)
{
x86_condition_code_t
cc
=
ia32_determine_final_cc
(
node
,
n_ia32_Jcc_eflags
);
/* get both Projs */
ir_node
const
*
proj_true
=
get_Proj_for_pn
(
node
,
pn_ia32_Jcc_true
);
ir_node
const
*
target_true
=
be_emit_get_cfop_target
(
proj_true
);
ir_node
const
*
proj_false
=
get_Proj_for_pn
(
node
,
pn_ia32_Jcc_false
);
be_cond_branch_projs_t
projs
=
be_get_cond_branch_projs
(
node
);
ir_node
const
*
target_true
=
be_emit_get_cfop_target
(
projs
.
t
);
ir_node
const
*
block
=
get_nodes_block
(
node
);
if
(
fallthrough_possible
(
block
,
target_true
))
{
/* exchange both proj's so the second one can be omitted */
const
ir_node
*
t
=
proj_true
;
proj_true
=
proj_false
;
proj_false
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
ir_node
*
const
t
=
projs
.
t
;
projs
.
t
=
projs
.
f
;
projs
.
f
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
}
ir_node
const
*
target_false
=
be_emit_get_cfop_target
(
proj
_false
);
ir_node
const
*
target_false
=
be_emit_get_cfop_target
(
proj
s
.
f
);
bool
const
fallthrough
=
fallthrough_possible
(
block
,
target_false
);
/* if we can't have a fallthrough anyway, put the more likely case first */
if
(
!
fallthrough
)
{
...
...
@@ -974,10 +972,10 @@ static void enc_ia32_jcc(const ir_node *node)
double
freq_true
=
get_block_execfreq
(
target_true
);
double
freq_false
=
get_block_execfreq
(
target_false
);
if
(
freq_false
>
freq_true
)
{
const
ir_node
*
t
=
proj
_true
;
proj
_true
=
proj
_false
;
proj
_false
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
ir_node
*
const
t
=
proj
s
.
t
;
proj
s
.
t
=
proj
s
.
f
;
proj
s
.
f
=
t
;
cc
=
x86_negate_condition_code
(
cc
);
}
}
...
...
@@ -985,7 +983,7 @@ static void enc_ia32_jcc(const ir_node *node)
/* Some floating point comparisons require a test of the parity flag,
* which indicates that the result is unordered */
if
(
cc
&
x86_cc_negated
)
{
enc_jp
(
false
,
proj
_true
);
enc_jp
(
false
,
proj
s
.
t
);
}
else
{
/* we need a local label if the false proj is a fallthrough
* as the falseblock might have no label emitted then */
...
...
@@ -993,17 +991,17 @@ static void enc_ia32_jcc(const ir_node *node)
be_emit8
(
0x7A
);
be_emit8
(
0x06
);
// jp + 6
}
else
{
enc_jp
(
false
,
proj
_false
);
enc_jp
(
false
,
proj
s
.
f
);
}
}
}
enc_jcc
(
cc
,
proj
_true
);
enc_jcc
(
cc
,
proj
s
.
t
);
/* the second Proj might be a fallthrough */
if
(
fallthrough
)
{
/* it's a fallthrough */
}
else
{
enc_jmp
(
proj
_false
);
enc_jmp
(
proj
s
.
f
);
}
}
...
...
ir/be/sparc/sparc_emitter.c
View file @
37b1db4c
...
...
@@ -408,30 +408,15 @@ static bool can_move_up_into_delayslot(const ir_node *node, const ir_node *to)
static
void
optimize_fallthrough
(
ir_node
*
node
)
{
ir_node
*
proj_true
=
NULL
;
ir_node
*
proj_false
=
NULL
;
assert
((
unsigned
)
pn_sparc_Bicc_false
==
(
unsigned
)
pn_sparc_fbfcc_false
);
assert
((
unsigned
)
pn_sparc_Bicc_true
==
(
unsigned
)
pn_sparc_fbfcc_true
);
foreach_out_edge
(
node
,
edge
)
{
ir_node
*
proj
=
get_edge_src_irn
(
edge
);
unsigned
pn
=
get_Proj_num
(
proj
);
if
(
pn
==
pn_sparc_Bicc_true
)
{
proj_true
=
proj
;
}
else
{
assert
(
pn
==
pn_sparc_Bicc_false
);
proj_false
=
proj
;
}
}
assert
(
proj_true
!=
NULL
&&
proj_false
!=
NULL
);
be_cond_branch_projs_t
const
projs
=
be_get_cond_branch_projs
(
node
);
ir_node
const
*
const
block
=
get_nodes_block
(
node
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
_true
);
ir_node
const
*
const
true_target
=
be_emit_get_cfop_target
(
proj
s
.
t
);
if
(
be_emit_get_prev_block
(
true_target
)
==
block
)
{
/* exchange both proj destinations so the second one can be omitted */
set_Proj_num
(
proj
_true
,
pn_sparc_Bicc_false
);
set_Proj_num
(
proj
_false
,
pn_sparc_Bicc_true
);
set_Proj_num
(
proj
s
.
t
,
pn_sparc_Bicc_false
);
set_Proj_num
(
proj
s
.
f
,
pn_sparc_Bicc_true
);
sparc_jmp_cond_attr_t
*
attr
=
get_sparc_jmp_cond_attr
(
node
);
attr
->
relation
=
get_negated_relation
(
attr
->
relation
);
...
...
@@ -1135,36 +1120,23 @@ static void emit_sparc_branch(const ir_node *node, get_cc_func get_cc)
{
const
sparc_jmp_cond_attr_t
*
attr
=
get_sparc_jmp_cond_attr_const
(
node
);
ir_relation
relation
=
attr
->
relation
;
const
ir_node
*
proj_true
=
NULL
;
const
ir_node
*
proj_false
=
NULL
;
assert
((
unsigned
)
pn_sparc_Bicc_false
==
(
unsigned
)
pn_sparc_fbfcc_false
);
assert
((
unsigned
)
pn_sparc_Bicc_true
==
(
unsigned
)
pn_sparc_fbfcc_true
);
foreach_out_edge
(
node
,
edge
)
{
ir_node
*
proj
=
get_edge_src_irn
(
edge
);
unsigned
nr
=
get_Proj_num
(
proj
);
if
(
nr
==
pn_sparc_Bicc_true
)
{
proj_true
=
proj
;
}
else
{
assert
(
nr
==
pn_sparc_Bicc_false
);
proj_false
=
proj
;
}
}
be_cond_branch_projs_t
const
projs
=
be_get_cond_branch_projs
(
node
);
/* emit the true proj */
sparc_emitf
(
node
,
"%s%A %L"
,
get_cc
(
relation
),
proj
_true
);
sparc_emitf
(
node
,
"%s%A %L"
,
get_cc
(
relation
),
proj
s
.
t
);
fill_delay_slot
(
node
);
const
ir_node
*
block
=
get_nodes_block
(
node
);
const
ir_node
*
proj_target
=
be_emit_get_cfop_target
(
proj
_false
);
const
ir_node
*
proj_target
=
be_emit_get_cfop_target
(
proj
s
.
f
);
if
(
be_emit_get_prev_block
(
proj_target
)
!=
block
)
{
sparc_emitf
(
node
,
"ba %L"
,
proj
_false
);
sparc_emitf
(
node
,
"ba %L"
,
proj
s
.
f
);
/* TODO: fill this slot as well */
emitting_delay_slot
=
true
;
sparc_emitf
(
NULL
,
"nop"
);
emitting_delay_slot
=
false
;
}
else
if
(
be_options
.
verbose_asm
)
{
sparc_emitf
(
node
,
"/* fallthrough to %L */"
,
proj
_false
);
sparc_emitf
(
node
,
"/* fallthrough to %L */"
,
proj
s
.
f
);
}
}
...
...
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