FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
- /* 1st: transform psi condition trees */
- irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_psi_cond_tree, cg);
+ /* 1st: transform constants and psi condition trees */
+ irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_psi_cond_tree, cg);
/* 2nd: transform all remaining nodes */
ia32_register_transformers();
- irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
+ irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
/* 3rd: optimize address mode */
! is_ia32_Lea(irn) && \
! is_ia32_Conv_I2I(irn) && \
! is_ia32_Conv_I2I8Bit(irn) && \
- ! is_ia32_CMov(irn) && \
- ! is_ia32_Set(irn);
+ ! is_ia32_CmpCMov(irn) && \
+ ! is_ia32_CmpSet(irn);
}
/**
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "%s %s", instr, reg);
lc_esnprintf(ia32_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F */", irn);
IA32_DO_EMIT(irn);
-// lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fnstsw %3D", irn);
lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fnstsw %%ax", irn);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* Store x87 FPU Control Word */");
IA32_DO_EMIT(irn);
/* we have to emit the cmp first, because the destination register */
/* could be one of the compare registers */
- if (is_ia32_CMov(irn)) {
+ if (is_ia32_CmpCMov(irn)) {
lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %2S", irn, irn);
}
else if (is_ia32_xCmpCMov(irn)) {
IA32_DO_EMIT(irn);
}
-static void emit_ia32_CMov(ir_node *irn, ia32_emit_env_t *env) {
+static void emit_ia32_CmpCMov(ir_node *irn, ia32_emit_env_t *env) {
CMov_emitter(irn, env);
}
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* clear target as set modifies only lower 8 bit */");
IA32_DO_EMIT(irn);
- if (is_ia32_Set(irn)) {
- lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %2S", irn, irn);
+ if (is_ia32_CmpSet(irn)) {
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %s", ia32_emit_binop(irn, env));
}
else if (is_ia32_xCmpSet(irn)) {
- lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ucomis%M %1S, %2S", get_irn_n(irn, 0), irn, irn);
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ucomis%M %s", get_irn_n(irn, 0), ia32_emit_binop(irn, env));
}
else {
assert(0 && "unsupported Set");
IA32_DO_EMIT(irn);
}
-static void emit_ia32_Set(ir_node *irn, ia32_emit_env_t *env) {
+static void emit_ia32_CmpSet(ir_node *irn, ia32_emit_env_t *env) {
Set_emitter(irn, env);
}
IA32_EMIT(TestJmp);
IA32_EMIT(CJmp);
IA32_EMIT(CJmpAM);
- IA32_EMIT(CMov);
- IA32_EMIT(Set);
+ IA32_EMIT(CmpCMov);
+ IA32_EMIT(CmpSet);
IA32_EMIT(SwitchJmp);
IA32_EMIT(CopyB);
IA32_EMIT(CopyB_i);
"outs" => [ "res", "M" ],
},
-"CMov" => {
+"CmpCMov" => {
"irn_flags" => "R",
"comment" => "construct Conditional Move: CMov(sel, a, b) == sel ? a : b",
"reg_req" => { "in" => [ "gp", "gp", "gp", "gp" ], "out" => [ "in_r4" ] }
"reg_req" => { "in" => [ "vfp", "vfp", "gp", "gp" ], "out" => [ "in_r4" ] }
},
-"Set" => {
+"CmpSet" => {
"irn_flags" => "R",
"comment" => "construct Set: Set(sel) == sel ? 1 : 0",
- "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "eax ebx ecx edx" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
+ "outs" => [ "res", "M" ],
},
"xCmpSet" => {
"irn_flags" => "R",
"comment" => "construct Set: SSE Compare + int Set",
- "reg_req" => { "in" => [ "xmm", "xmm" ], "out" => [ "eax ebx ecx edx" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
+ "outs" => [ "res", "M" ],
},
"vfCmpSet" => {
"irn_flags" => "R",
"comment" => "construct Set: x87 Compare + int Set",
- "reg_req" => { "in" => [ "vfp", "vfp" ], "out" => [ "eax ebx ecx edx" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
+ "outs" => [ "res", "M" ],
},
"vfCMov" => {
return NULL;
}
-typedef ir_node *set_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *cmp_a, ir_node *cmp_b, ir_mode *mode);
typedef ir_node *cmov_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *cmp_a, ir_node *cmp_b, \
ir_node *psi_true, ir_node *psi_default, ir_mode *mode);
}
else {
/* integer psi */
- set_func_t *set_func = NULL;
- cmov_func_t *cmov_func = NULL;
+ construct_binop_func *set_func = NULL;
+ cmov_func_t *cmov_func = NULL;
if (mode_is_float(get_irn_mode(cmp_a))) {
/* 1st case: compare operands are floats */
set_func = new_rd_ia32_vfCmpSet;
cmov_func = new_rd_ia32_vfCmpCMov;
}
+
+ pnc -= pn_Cmp_Uo; /* fp compare -> int compare */
}
else {
/* 2nd case: compare operand are integer too */
- set_func = new_rd_ia32_Set;
- cmov_func = new_rd_ia32_CMov;
+ set_func = new_rd_ia32_CmpSet;
+ cmov_func = new_rd_ia32_CmpCMov;
}
/* create the nodes */
-
+ env->irn = cmp;
if (is_ia32_Const_1(psi_true) && is_ia32_Const_0(psi_default)) {
/* first case for SETcc: default is 0, set to 1 iff condition is true */
- new_op = set_func(dbg, irg, block, cmp_a, cmp_b, mode);
- set_ia32_pncode(new_op, pnc);
+ new_op = gen_binop(env, cmp_a, cmp_b, set_func);
+ set_ia32_pncode(get_Proj_pred(new_op), pnc);
}
else if (is_ia32_Const_0(psi_true) && is_ia32_Const_1(psi_default)) {
/* second case for SETcc: default is 1, set to 0 iff condition is true: */
/* we invert condition and set default to 0 */
- new_op = set_func(dbg, irg, block, cmp_a, cmp_b, mode);
- set_ia32_pncode(new_op, get_negated_pnc(pnc, get_irn_mode(cmp_a)));
+ new_op = gen_binop(env, cmp_a, cmp_b, set_func);
+ set_ia32_pncode(get_Proj_pred(new_op), get_negated_pnc(pnc, mode));
}
else {
/* otherwise: use CMOVcc */
new_op = cmov_func(dbg, irg, block, cmp_a, cmp_b, psi_true, psi_default, mode);
set_ia32_pncode(new_op, pnc);
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
}
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
}
return new_op;
}
else {
/* integer Psi */
- new_op = new_rd_ia32_Set(dbg, irg, block, cmp_a, cmp_b, mode);
- set_ia32_pncode(new_op, pnc);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, cmp));
+ ia32_transform_env_t tenv;
+
+ tenv.block = block;
+ tenv.cg = cg;
+ tenv.dbg = dbg;
+ tenv.irg = irg;
+ tenv.irn = cmp;
+ tenv.mode = mode;
+ tenv.mod = cg->mod;
+
+ new_op = gen_binop(&tenv, cmp_a, cmp_b, new_rd_ia32_CmpSet);
+ set_ia32_pncode(get_Proj_pred(new_op), pnc);
}
/* exchange with old compare */
/* BEWARE: new_r_Const_long works for floating point as well */
new_cmp = new_r_Cmp(irg, block, psi_sel, new_r_Const_long(irg, block, mode, 0));
+ /* transform the const */
+ ia32_place_consts_set_modes(new_cmp, cg);
new_cmp = new_r_Proj(irg, block, new_cmp, mode_b, pn_Cmp_Ne + (mode_is_float(mode) ? pn_Cmp_Uo : 0));
set_Psi_cond(node, 0, new_cmp);