Commit e2cb53cc authored by Matthias Braun's avatar Matthias Braun
Browse files

ia32: force flag users to have a condcode attribute

This also allows to cleanup the finish neg/add carry flag fix code a
big.
parent d1564f4d
......@@ -32,6 +32,15 @@
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static bool reads_carry(x86_condition_code_t code)
{
x86_condition_code_t c2 = code & ~x86_cc_negated;
return c2 == x86_cc_below || c2 == x86_cc_below_equal
|| c2 == x86_cc_float_below || c2 == x86_cc_float_below_equal
|| c2 == x86_cc_float_unordered_below_equal
|| c2 == x86_cc_float_unordered_below;
}
/**
* Transforms a Sub or xSub into Neg--Add iff OUT_REG != SRC1_REG && OUT_REG == SRC2_REG.
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
......@@ -84,10 +93,10 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
res = new_bd_ia32_xAdd(dbgi, block, noreg, noreg, nomem, res, in1);
set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
} else {
ir_node *flags_proj = NULL;
bool only_needs_value = true;
ir_node *flags_proj = NULL;
bool needs_carry = false;
/** See if someone is interested in a correctly set carry flag */
if (get_irn_mode(irn) == mode_T) {
/* collect the Proj uses */
foreach_out_edge(irn, edge) {
ir_node *proj = get_edge_src_irn(edge);
long pn = get_Proj_proj(proj);
......@@ -96,18 +105,9 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
flags_proj = proj;
foreach_out_edge(flags_proj, edge) {
ir_node *user = get_edge_src_irn(edge);
if (is_ia32_CMovcc(user) || is_ia32_Jcc(user) ||
is_ia32_Setcc(user) || is_ia32_SetccMem(user)) {
/* If the users only need the sign/zero flags,
* we just have to compute the right value. */
x86_condition_code_t cc = get_ia32_condcode(user);
if (cc != x86_cc_equal && cc != x86_cc_not_equal &&
cc != x86_cc_sign && cc != x86_cc_not_sign) {
only_needs_value = false;
break;
}
} else {
only_needs_value = false;
x86_condition_code_t cc = get_ia32_condcode(user);
if (reads_carry(cc)) {
needs_carry = true;
break;
}
}
......@@ -122,7 +122,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
carry = get_irn_n(irn, n_ia32_Sbb_eflags);
carry = new_bd_ia32_Cmc(dbgi, block, carry);
goto carry;
} else if (flags_proj != NULL && !only_needs_value) {
} else if (flags_proj != NULL && needs_carry) {
/*
* ARG, the above technique does NOT set the flags right.
* So, we must produce the following code:
......
......@@ -75,6 +75,13 @@ static const char *condition_code_name(x86_condition_code_t cc)
}
}
static bool has_ia32_condcode_attr(const ir_node *node)
{
return is_ia32_Setcc(node) || is_ia32_SetccMem(node) || is_ia32_CMovcc(node)
|| is_ia32_Jcc(node) || is_ia32_Adc(node) || is_ia32_Sbb(node)
|| is_ia32_Sbb0(node) || is_ia32_Cmc(node);
}
/**
* Dumper interface for dumping ia32 nodes in vcg.
* @param n the node to dump
......@@ -196,8 +203,7 @@ static void ia32_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
fprintf(F, "AM scale = %u\n", get_ia32_am_scale(n));
/* dump pn code */
if (is_ia32_CMovcc(n) || is_ia32_Jcc(n) ||
is_ia32_Setcc(n) || is_ia32_SetccMem(n)) {
if (has_ia32_condcode_attr(n)) {
const ia32_attr_t *attr = get_ia32_attr_const(n);
const char *cc_name = condition_code_name(get_ia32_condcode(n));
if (cc_name) {
......@@ -299,6 +305,7 @@ const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node)
ia32_condcode_attr_t *get_ia32_condcode_attr(ir_node *node)
{
assert(has_ia32_condcode_attr(node));
ia32_attr_t *attr = get_ia32_attr(node);
ia32_condcode_attr_t *cc_attr = CAST_IA32_ATTR(ia32_condcode_attr_t, attr);
......@@ -307,6 +314,7 @@ ia32_condcode_attr_t *get_ia32_condcode_attr(ir_node *node)
const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node)
{
assert(has_ia32_condcode_attr(node));
const ia32_attr_t *attr = get_ia32_attr_const(node);
const ia32_condcode_attr_t *cc_attr = CONST_CAST_IA32_ATTR(ia32_condcode_attr_t, attr);
......
......@@ -243,6 +243,8 @@ Adc => {
out => [ "in_r4 in_r5", "flags", "none" ] },
ins => [ "base", "index", "mem", "left", "right", "eflags" ],
outs => [ "res", "flags", "M" ],
attr_type => "ia32_condcode_attr_t",
fixed => "x86_condition_code_t condition_code = x86_cc_carry;",
emit => "adc%M %B",
am => "source,binary",
latency => 1,
......@@ -440,6 +442,8 @@ Sbb => {
out => [ "in_r4", "flags", "none" ] },
ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
outs => [ "res", "flags", "M" ],
attr_type => "ia32_condcode_attr_t",
fixed => "x86_condition_code_t condition_code = x86_cc_carry;",
am => "source,binary",
emit => "sbb%M %B",
latency => 1,
......@@ -452,6 +456,8 @@ Sbb0 => {
# irn_flags => [ "rematerializable" ],
reg_req => { in => [ "flags" ], out => [ "gp", "flags" ] },
outs => [ "res", "flags" ],
attr_type => "ia32_condcode_attr_t",
fixed => "x86_condition_code_t condition_code = x86_cc_carry;",
emit => "sbb%M %D0, %D0",
latency => 1,
mode => $mode_gp,
......@@ -754,6 +760,8 @@ NotMem => {
Cmc => {
reg_req => { in => [ "flags" ], out => [ "flags" ] },
attr_type => "ia32_condcode_attr_t",
fixed => "x86_condition_code_t condition_code = x86_cc_carry;",
emit => "cmc",
latency => 1,
mode => $mode_flags,
......
......@@ -7,6 +7,7 @@ typedef enum x86_condition_code_t {
x86_cc_overflow = 0x00, /**< OF=1 */
x86_cc_below = 0x02, /**< CF=1 */
x86_cc_carry = x86_cc_below,
x86_cc_equal = 0x04, /**< ZF=1 */
x86_cc_below_equal = 0x06, /**< ZF=1 or CF=1 */
x86_cc_sign = 0x08, /**< SF=1 */
......
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