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

psi transform and emit logical rewritten from scratch

[r14513]
parent 11107302
......@@ -867,17 +867,10 @@ ia32_irn_ops_t ia32_irn_ops = {
static void ia32_prepare_graph(void *self) {
ia32_code_gen_t *cg = self;
/* transform psi condition trees */
ia32_pre_transform_phase(cg);
/* transform all remaining nodes */
/* transform nodes into assembler instructions */
ia32_transform_graph(cg);
//add_fpu_edges(cg->birg);
// Matze: disabled for now. Because after transformation start block has no
// self-loop anymore so it might be merged with its successor block. This
// will bring several nodes to the startblock which sometimes get scheduled
// before the initial IncSP/Barrier
/* do local optimisations (mainly CSE) */
local_optimize_graph(cg->irg);
if (cg->dump)
......
......@@ -930,25 +930,58 @@ void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
finish_CondJmp(env, node, mode_E, pnc);
}
static
void emit_register_or_immediate(ia32_emit_env_t *env, const ir_node *node,
int pos)
{
ir_node *op = get_irn_n(node, pos);
if(is_ia32_Immediate(op)) {
emit_ia32_Immediate(env, op);
} else {
ia32_emit_source_register(env, node, pos);
}
}
static
int is_ia32_Immediate_0(const ir_node *node)
{
const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
tarval *tv = attr->offset;
if(tv == NULL || attr->symconst != NULL)
return 0;
return classify_tarval(tv) == CNST_NULL;
}
static
void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
long pnc = get_ia32_pncode(node);
int is_PsiCondCMov = is_ia32_PsiCondCMov(node);
int idx_left = 2 - is_PsiCondCMov;
int idx_right = 3 - is_PsiCondCMov;
const arch_register_t *in1, *in2, *out;
out = arch_get_irn_register(env->arch_env, node);
in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_left));
in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_right));
in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 2));
in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 3));
/* we have to emit the cmp first, because the destination register */
/* could be one of the compare registers */
if (is_ia32_CmpCMov(node)) {
be_emit_cstring(env, "\tcmp ");
ia32_emit_source_register(env, node, 1);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
long pncr = pnc & ~ia32_pn_Cmp_Unsigned;
ir_node *cmp_right = get_irn_n(node, 1);
if( (pncr == pn_Cmp_Eq || pncr == pn_Cmp_Lg)
&& is_ia32_Immediate(cmp_right)
&& is_ia32_Immediate_0(cmp_right)) {
be_emit_cstring(env, "\ttest ");
ia32_emit_source_register(env, node, 0);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else {
be_emit_cstring(env, "\tcmp ");
emit_register_or_immediate(env, node, 1);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
}
} else if (is_ia32_xCmpCMov(node)) {
be_emit_cstring(env, "\tucomis");
ia32_emit_mode_suffix_mode(env, get_irn_mode(node));
......@@ -956,12 +989,6 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
ia32_emit_source_register(env, node, 1);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else if (is_PsiCondCMov) {
/* omit compare because flags are already set by And/Or */
be_emit_cstring(env, "\ttest ");
ia32_emit_source_register(env, node, 0);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else {
assert(0 && "unsupported CMov");
}
......@@ -972,42 +999,26 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
} else if (REGS_ARE_EQUAL(out, in1)) {
ir_node *n = (ir_node*) node;
/* true in == out -> need complement compare and exchange true and default in */
ir_node *t = get_irn_n(n, idx_left);
set_irn_n(n, idx_left, get_irn_n(n, idx_right));
set_irn_n(n, idx_right, t);
ir_node *t = get_irn_n(n, 2);
set_irn_n(n, 2, get_irn_n(n, 3));
set_irn_n(n, 3, t);
pnc = get_negated_pnc(pnc, get_irn_mode(node));
} else {
/* out is different from in: need copy default -> out */
if (is_PsiCondCMov) {
be_emit_cstring(env, "\tmovl ");
ia32_emit_dest_register(env, node, 2);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
be_emit_cstring(env, "\tmovl ");
ia32_emit_source_register(env, node, 3);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
be_emit_finish_line_gas(env, node);
}
if (is_PsiCondCMov) {
be_emit_cstring(env, "\tcmov");
ia32_emit_cmp_suffix(env, pnc);
be_emit_cstring(env, "l ");
ia32_emit_source_register(env, node, 1);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
be_emit_cstring(env, "\tcmov");
ia32_emit_cmp_suffix(env, pnc);
be_emit_cstring(env, "l ");
ia32_emit_source_register(env, node, 2);
be_emit_cstring(env, "\tmovl ");
ia32_emit_source_register(env, node, 3);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
be_emit_finish_line_gas(env, node);
}
be_emit_cstring(env, "\tcmov");
ia32_emit_cmp_suffix(env, pnc);
be_emit_cstring(env, "l ");
ia32_emit_source_register(env, node, 2);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
be_emit_finish_line_gas(env, node);
}
......@@ -1016,11 +1027,6 @@ void emit_ia32_CmpCMov(ia32_emit_env_t *env, const ir_node *node) {
CMov_emitter(env, node);
}
static
void emit_ia32_PsiCondCMov(ia32_emit_env_t *env, const ir_node *node) {
CMov_emitter(env, node);
}
static
void emit_ia32_xCmpCMov(ia32_emit_env_t *env, const ir_node *node) {
CMov_emitter(env, node);
......@@ -1028,7 +1034,7 @@ void emit_ia32_xCmpCMov(ia32_emit_env_t *env, const ir_node *node) {
static
void Set_emitter(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode) {
int pnc = get_ia32_pncode(node);
long pnc = get_ia32_pncode(node);
const char *reg8bit;
const arch_register_t *out;
......@@ -1036,16 +1042,25 @@ void Set_emitter(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode) {
reg8bit = ia32_get_mapped_reg_name(env->isa->regs_8bit, out);
if (is_ia32_CmpSet(node)) {
be_emit_cstring(env, "\tcmp ");
ia32_emit_binop(env, node);
long pncr = pnc & ~ia32_pn_Cmp_Unsigned;
ir_node *cmp_right = get_irn_n(node, n_ia32_CmpSet_cmp_right);
if( (pncr == pn_Cmp_Eq || pncr == pn_Cmp_Lg)
&& is_ia32_Immediate(cmp_right)
&& is_ia32_Immediate_0(cmp_right)) {
be_emit_cstring(env, "\ttest ");
ia32_emit_source_register(env, node, n_ia32_CmpSet_cmp_left);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, n_ia32_CmpSet_cmp_left);
} else {
be_emit_cstring(env, "\tcmp ");
ia32_emit_binop(env, node);
}
} else if (is_ia32_xCmpSet(node)) {
be_emit_cstring(env, "\tucomis");
ia32_emit_mode_suffix_mode(env, get_irn_mode(get_irn_n(node, 2)));
be_emit_char(env, ' ');
ia32_emit_binop(env, node);
} else if (is_ia32_PsiCondSet(node)) {
be_emit_cstring(env, "\tcmp $0, ");
ia32_emit_source_register(env, node, 0);
} else {
assert(0 && "unsupported Set");
}
......@@ -1068,11 +1083,6 @@ void emit_ia32_CmpSet(ia32_emit_env_t *env, const ir_node *node) {
Set_emitter(env, node, get_irn_mode(get_irn_n(node, 2)));
}
static
void emit_ia32_PsiCondSet(ia32_emit_env_t *env, const ir_node *node) {
Set_emitter(env, node, get_irn_mode(get_irn_n(node, 0)));
}
static
void emit_ia32_xCmpSet(ia32_emit_env_t *env, const ir_node *node) {
Set_emitter(env, node, get_irn_mode(get_irn_n(node, 2)));
......@@ -1336,22 +1346,22 @@ void emit_Jmp(ia32_emit_env_t *env, const ir_node *node) {
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
assert(attr->am_sc != NULL || attr->cnst_val.tv != NULL);
if(attr->am_sc != NULL) {
ident *id = get_entity_ld_ident(attr->am_sc);
assert(attr->symconst != NULL || attr->offset != NULL);
if(attr->symconst != NULL) {
ident *id = get_entity_ld_ident(attr->symconst);
if(attr->data.am_sc_sign)
if(attr->attr.data.am_sc_sign)
be_emit_char(env, '-');
be_emit_ident(env, id);
}
if(attr->cnst_val.tv != NULL) {
if(attr->am_sc != NULL)
if(attr->offset != NULL) {
if(attr->symconst != NULL)
be_emit_char(env, '+');
else
be_emit_char(env, '$');
be_emit_tarval(env, attr->cnst_val.tv);
be_emit_tarval(env, attr->offset);
}
}
......@@ -1956,9 +1966,7 @@ void ia32_register_emitters(void) {
IA32_EMIT(CJmp);
IA32_EMIT(CJmpAM);
IA32_EMIT(CmpCMov);
IA32_EMIT(PsiCondCMov);
IA32_EMIT(CmpSet);
IA32_EMIT(PsiCondSet);
IA32_EMIT(SwitchJmp);
IA32_EMIT(CopyB);
IA32_EMIT(CopyB_i);
......
......@@ -272,7 +272,6 @@ static INLINE int need_constraint_copy(ir_node *irn) {
! is_ia32_Conv_I2I(irn) &&
! is_ia32_Conv_I2I8Bit(irn) &&
! is_ia32_CmpCMov(irn) &&
! is_ia32_PsiCondCMov(irn) &&
! is_ia32_CmpSet(irn);
}
......
......@@ -430,6 +430,15 @@ const ia32_asm_attr_t *get_ia32_asm_attr_const(const ir_node *node) {
return asm_attr;
}
const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
const ia32_immediate_attr_t *immediate_attr
= CONST_CAST_IA32_ATTR(ia32_immediate_attr_t, attr);
return immediate_attr;
}
/**
* Gets the type of an ia32 node.
*/
......@@ -1195,6 +1204,20 @@ init_ia32_asm_attributes(ir_node *res)
#endif
}
void
init_ia32_immediate_attributes(ir_node *res, ir_entity *symconst,
int symconst_sign, tarval *offset)
{
ia32_immediate_attr_t *attr = get_irn_generic_attr(res);
#ifndef DEBUG
attr->attr.attr_type |= IA32_ATTR_ia32_immediate_attr_t;
#endif
attr->symconst = symconst;
attr->attr.data.am_sc_sign = symconst_sign;
attr->offset = offset;
}
ir_node *get_ia32_result_proj(const ir_node *node)
{
const ir_edge_t *edge;
......@@ -1291,6 +1314,20 @@ int ia32_compare_asm_attr(ir_node *a, ir_node *b)
return 0;
}
static
int ia32_compare_immediate_attr(ir_node *a, ir_node *b)
{
const ia32_immediate_attr_t *attr_a = get_ia32_immediate_attr_const(a);
const ia32_immediate_attr_t *attr_b = get_ia32_immediate_attr_const(b);
if(attr_a->symconst != attr_b->symconst ||
attr_a->attr.data.am_sc_sign != attr_b->attr.data.am_sc_sign ||
attr_a->offset != attr_b->offset)
return 1;
return 0;
}
/* copies the ia32 attributes */
static void ia32_copy_attr(const ir_node *old_node, ir_node *new_node)
{
......
......@@ -57,6 +57,8 @@ const ia32_attr_t *get_ia32_attr_const(const ir_node *node);
ia32_x87_attr_t *get_ia32_x87_attr(ir_node *node);
const ia32_x87_attr_t *get_ia32_x87_attr_const(const ir_node *node);
const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node);
/**
* Gets the type of an ia32 node.
*/
......@@ -492,6 +494,8 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
void init_ia32_x87_attributes(ir_node *node);
void init_ia32_asm_attributes(ir_node *node);
void init_ia32_immediate_attributes(ir_node *node, ir_entity *symconst,
int symconst_sign, tarval *offset);
/**
* Registers the ia32_copy_attr function for all ia32 opcodes.
......
......@@ -31,6 +31,7 @@
#include "firm_types.h"
#include "../bearch_t.h"
#include "../bemachine.h"
#include "irnode_t.h"
typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod } ia32_op_flavour_t;
typedef enum { pn_EAX, pn_EDX } pn_ia32_Register;
......@@ -87,15 +88,17 @@ enum {
#ifndef NDEBUG
typedef enum {
IA32_ATTR_INVALID = 0,
IA32_ATTR_ia32_attr_t = 1 << 0,
IA32_ATTR_ia32_x87_attr_t = 1 << 1,
IA32_ATTR_ia32_asm_attr_t = 1 << 2,
IA32_ATTR_INVALID = 0,
IA32_ATTR_ia32_attr_t = 1 << 0,
IA32_ATTR_ia32_x87_attr_t = 1 << 1,
IA32_ATTR_ia32_asm_attr_t = 1 << 2,
IA32_ATTR_ia32_immediate_attr_t = 1 << 3,
} ia32_attr_type_t;
#endif
typedef struct ia32_attr_t ia32_attr_t;
struct ia32_attr_t {
except_attr exc; /**< the exception attribute. MUST be the first one. */
struct {
unsigned tp:3; /**< ia32 node type. */
unsigned imm_tp:2; /**< ia32 immop type. */
......@@ -152,6 +155,13 @@ struct ia32_attr_t {
const arch_register_t **slots; /**< register slots for assigned registers */
};
typedef struct ia32_immediate_attr_t ia32_immediate_attr_t;
struct ia32_immediate_attr_t {
ia32_attr_t attr;
ir_entity *symconst;
tarval *offset;
};
typedef struct ia32_x87_attr_t ia32_x87_attr_t;
struct ia32_x87_attr_t {
ia32_attr_t attr;
......@@ -167,9 +177,10 @@ struct ia32_asm_attr_t {
/* the following union is necessary to indicate to the compiler that we might want to cast
* the structs (we use them to simulate OO-inheritance) */
union allow_casts_attr_t_ {
ia32_attr_t attr;
ia32_x87_attr_t x87_attr;
ia32_asm_attr_t asm_attr;
ia32_attr_t attr;
ia32_x87_attr_t x87_attr;
ia32_asm_attr_t asm_attr;
ia32_immediate_attr_t immediate_attr;
};
#ifndef NDEBUG
......
......@@ -71,15 +71,6 @@ static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
return irn == cg->noreg_gp || irn == cg->noreg_xmm || irn == cg->noreg_vfp;
}
void ia32_pre_transform_phase(ia32_code_gen_t *cg) {
/*
We need to transform the consts twice:
- the psi condition tree transformer needs existing constants to be ia32 constants
- the psi condition tree transformer inserts new firm constants which need to be transformed
*/
irg_walk_graph(cg->irg, NULL, ia32_transform_psi_cond_tree, cg);
}
/********************************************************************************************************
* _____ _ _ ____ _ _ _ _ _
* | __ \ | | | | / __ \ | | (_) (_) | | (_)
......
......@@ -303,13 +303,17 @@ $default_attr_type = "ia32_attr_t";
ia32_asm_attr_t =>
"\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
"\tinit_ia32_x87_attributes(res);".
"\tinit_ia32_asm_attributes(res);"
"\tinit_ia32_asm_attributes(res);",
ia32_immediate_attr_t =>
"\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
"\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);"
);
%compare_attr = (
ia32_attr_t => "ia32_compare_nodes_attr",
ia32_x87_attr_t => "ia32_compare_x87_attr",
ia32_asm_attr_t => "ia32_compare_asm_attr",
ia32_attr_t => "ia32_compare_nodes_attr",
ia32_x87_attr_t => "ia32_compare_x87_attr",
ia32_asm_attr_t => "ia32_compare_asm_attr",
ia32_immediate_attr_t => "ia32_compare_immediate_attr",
);
%operands = (
......@@ -329,6 +333,8 @@ Immediate => {
op_flags => "c",
irn_flags => "I",
reg_req => { out => [ "gp_NOREG" ] },
attr => "ir_entity *symconst, int symconst_sign, tarval *offset",
attr_type => "ia32_immediate_attr_t",
mode => $mode_gp,
},
......@@ -752,6 +758,7 @@ Dec => {
Not => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
ins => [ "base", "index", "val", "mem" ],
emit => '. not%M %unop2',
units => [ "GP" ],
mode => $mode_gp,
......@@ -1321,14 +1328,9 @@ Conv_FP2FP => {
CmpCMov => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] },
latency => 2,
units => [ "GP" ],
mode => $mode_gp,
},
PsiCondCMov => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] },
ins => [ "cmp_left", "cmp_right", "val_true", "val_false" ],
attr => "pn_Cmp pn_code",
init_attr => "attr->pn_code = pn_code;",
latency => 2,
units => [ "GP" ],
mode => $mode_gp,
......@@ -1354,14 +1356,9 @@ vfCmpCMov => {
CmpSet => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
latency => 2,
units => [ "GP" ],
mode => $mode_gp,
},
PsiCondSet => {
irn_flags => "R",
reg_req => { in => [ "gp" ], out => [ "eax ebx ecx edx" ] },
ins => [ "base", "index", "cmp_left", "cmp_right", "mem" ],
attr => "pn_Cmp pn_code",
init_attr => "attr->pn_code = pn_code;",
latency => 2,
units => [ "GP" ],
mode => $mode_gp,
......
......@@ -238,6 +238,20 @@ static ir_entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst)
return res;
}
static int is_Const_0(ir_node *node) {
if(!is_Const(node))
return 0;
return classify_Const(node) == CNST_NULL;
}
static int is_Const_1(ir_node *node) {
if(!is_Const(node))
return 0;
return classify_Const(node) == CNST_ONE;
}
/**
* Transforms a Const.
*/
......@@ -352,6 +366,7 @@ static ir_node *gen_SymConst(ir_node *node) {
return cnst;
}
#if 0
/**
* SSE convert of an integer node into a floating point node.
*/
......@@ -392,6 +407,7 @@ static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbgi,
return conv;
}
#endif
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
......@@ -1004,9 +1020,8 @@ static ir_node *gen_Max(ir_node *node) {
if (! mode_is_signed(op_mode)) {
pnc |= ia32_pn_Cmp_Unsigned;
}
new_op = new_rd_ia32_CmpCMov(dbgi, irg, block, new_op1, new_op2, new_op1, new_op2);
set_ia32_pncode(new_op, pnc);
set_ia32_am_support(new_op, ia32_am_None);
new_op = new_rd_ia32_CmpCMov(dbgi, irg, block, new_op1, new_op2,
new_op1, new_op2, pnc);
}
SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
......@@ -1044,9 +1059,8 @@ static ir_node *gen_Min(ir_node *node) {
if (! mode_is_signed(op_mode)) {
pnc |= ia32_pn_Cmp_Unsigned;
}
new_op = new_rd_ia32_CmpCMov(dbgi, irg, block, new_op1, new_op2, new_op1, new_op2);
set_ia32_pncode(new_op, pnc);
set_ia32_am_support(new_op, ia32_am_None);
new_op = new_rd_ia32_CmpCMov(dbgi, irg, block, new_op1, new_op2,
new_op1, new_op2, pnc);
}
SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
......@@ -1657,6 +1671,7 @@ static ir_node *gen_Load(ir_node *node) {
}
}
set_irn_pinned(new_op, get_irn_pinned(node));
set_ia32_am_support(new_op, ia32_am_Source);
set_ia32_op_type(new_op, ia32_AddrModeS);
set_ia32_am_flavour(new_op, am_flav);
......@@ -1744,6 +1759,7 @@ static ir_node *gen_Store(ir_node *node) {
}
}
set_irn_pinned(new_op, get_irn_pinned(node));
set_ia32_am_support(new_op, ia32_am_Dest);
set_ia32_op_type(new_op, ia32_AddrModeD);
set_ia32_am_flavour(new_op, am_flav);
......@@ -1997,36 +2013,83 @@ typedef ir_node *cmov_func_t(dbg_info *db, ir_graph *irg, ir_node *block,
static ir_node *gen_Psi(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *psi_true = get_Psi_val(node, 0);
ir_node *new_psi_true = be_transform_node(psi_true);
ir_node *psi_default = get_Psi_default(node);
ir_node *new_psi_default = be_transform_node(psi_default);
ia32_code_gen_t *cg = env_cg;
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
ir_node *cmp_proj = get_Mux_sel(node);
ir_node *noreg = ia32_new_NoReg_gp(cg);
ir_node *nomem = new_rd_NoMem(irg);
ir_node *cmp, *cmp_a, *cmp_b, *and1, *and2, *new_op = NULL;
ir_node *cond = get_Psi_cond(node, 0);
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
ir_node *nomem = new_NoMem();
ir_node *new_op;
ir_node *cmp, *cmp_a, *cmp_b;
ir_node *new_cmp_a, *new_cmp_b;
ir_mode *cmp_mode;
int pnc;
assert(get_irn_mode(cmp_proj) == mode_b && "Condition for Psi must have mode_b");
int pnc;
assert(get_Psi_n_conds(node) == 1);
assert(get_irn_mode(cond) == mode_b);
if(is_And(cond) || is_Or(cond)) {
ir_node *new_cond = be_transform_node(cond);
tarval *tv_zero = new_tarval_from_long(0, mode_Iu);
ir_node *zero = new_rd_ia32_Immediate(NULL, irg, block, NULL, 0,
tv_zero);
arch_set_irn_register(env_cg->arch_env, zero,
&ia32_gp_regs[REG_GP_NOREG]);
/* we have to compare the result against zero */
new_cmp_a = new_cond;
new_cmp_b = zero;
pnc = pn_Cmp_Lg;
} else {
cmp = get_Proj_pred(cond);