Commit 37b1db4c authored by Christoph Mallon's avatar Christoph Mallon
Browse files

be: Factor out code to get the Projs of conditional branches.

parent ac97d7f3
......@@ -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(projs.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(projs.t, "jp %L");
} else {
amd64_emitf(proj_false, "jp %L");
amd64_emitf(projs.f, "jp %L");
}
}
/* emit the true proj */
amd64_emitf(proj_true, "j%PX %L", (int)cc);
amd64_emitf(projs.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(projs.f);
if (be_emit_get_prev_block(false_target) != block) {
amd64_emitf(proj_false, "jmp %L");
amd64_emitf(projs.f, "jmp %L");
} else if (be_options.verbose_asm) {
amd64_emitf(proj_false, "/* fallthrough to %L */");
amd64_emitf(projs.f, "/* fallthrough to %L */");
}
}
......
......@@ -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(projs.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, projs.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(projs.f);
if (be_emit_get_prev_block(false_target) != block) {
arm_emitf(irn, "b %t", proj_false);
arm_emitf(irn, "b %t", projs.f);
} else if (be_options.verbose_asm) {
arm_emitf(irn, "/* fallthrough to %t */", proj_false);
arm_emitf(irn, "/* fallthrough to %t */", projs.f);
}
}
......
......@@ -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;
}
......@@ -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
......@@ -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(projs.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 = projs.t;
projs.t = projs.f;
projs.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(projs.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(projs.f, "jp 1f");
} else {
ia32_emitf(proj_false, "jp %L");
ia32_emitf(projs.f, "jp %L");
}
}
}
ia32_emitf(proj_true, "j%PX %L", (int)cc);
ia32_emitf(projs.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(projs.f, "jmp %L");
} else if (be_options.verbose_asm) {
ia32_emitf(proj_false, "/* fallthrough to %L */");
ia32_emitf(projs.f, "/* fallthrough to %L */");
}
}
......
......@@ -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(projs.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 = projs.t;
projs.t = projs.f;
projs.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, projs.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, projs.f);
}
}
}
enc_jcc(cc, proj_true);
enc_jcc(cc, projs.t);
/* the second Proj might be a fallthrough */
if (fallthrough) {
/* it's a fallthrough */
} else {
enc_jmp(proj_false);
enc_jmp(projs.f);
}
}
......
......@@ -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(projs.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(projs.t, pn_sparc_Bicc_false);
set_Proj_num(projs.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), projs.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(projs.f);
if (be_emit_get_prev_block(proj_target) != block) {
sparc_emitf(node, "ba %L", proj_false);
sparc_emitf(node, "ba %L", projs.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 */", projs.f);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment