static void ia32_finish_irg_walker(ir_node *irn, void *env) {
ia32_code_gen_t *cg = env;
const ia32_register_req_t **reqs;
- const arch_register_t *out_reg, *in_reg;
+ const arch_register_t *out_reg, *in_reg, *in2_reg;
int n_res, i;
- ir_node *copy, *in_node, *block;
+ ir_node *copy, *in_node, *block, *in2_node;
ia32_op_type_t op_tp;
if (is_ia32_irn(irn)) {
for (i = 0; i < n_res; i++) {
if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
/* get in and out register */
- out_reg = get_ia32_out_reg(irn, i);
- in_node = get_irn_n(irn, reqs[i]->same_pos);
- in_reg = arch_get_irn_register(cg->arch_env, in_node);
+ out_reg = get_ia32_out_reg(irn, i);
+ in_node = get_irn_n(irn, reqs[i]->same_pos);
+ in_reg = arch_get_irn_register(cg->arch_env, in_node);
+ in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
+ in2_reg = arch_get_irn_register(cg->arch_env, in2_node);
/* don't copy ignore nodes */
if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
/* check if in and out register are equal */
if (! REGS_ARE_EQUAL(out_reg, in_reg)) {
/* in case of a commutative op: just exchange the in's */
- if (is_ia32_commutative(irn)) {
- ir_node *in2 = get_irn_n(irn, reqs[i]->same_pos ^ 1);
- if (REGS_ARE_EQUAL(out_reg, arch_get_irn_register(cg->arch_env, in2))) {
- set_irn_n(irn, reqs[i]->same_pos, in2);
- set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
- }
+ if (is_ia32_commutative(irn) && REGS_ARE_EQUAL(out_reg, in2_reg)) {
+ set_irn_n(irn, reqs[i]->same_pos, in2_node);
+ set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
}
else {
DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
reg = arch_get_irn_register(env->cg->arch_env, irn);
arch_set_irn_register(env->cg->arch_env, new_op, reg);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
exchange(irn, proj);
}
sched_remove(irn);
}
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
exchange(irn, proj);
}
/* set optimizations */
cg->opt.incdec = 0;
- cg->opt.doam = 0;
+ cg->opt.doam = 1;
cg->opt.placecnst = 1;
cg->opt.immops = 1;
cg->opt.extbb = 1;
#include "ia32_new_nodes.h"
#include "bearch_ia32_t.h"
#include "gen_ia32_regalloc_if.h" /* the generated interface (register type and class defenitions) */
+#include "ia32_transform.h"
#undef is_NoMem
#define is_NoMem(irn) (get_irn_op(irn) == op_NoMem)
int am_sc_sign = 0;
ident *am_sc = NULL;
ir_node *left, *right, *temp;
- ir_node *base, *index;
+ ir_node *base, *index, *orig_base, *orig_index;
ia32_am_flavour_t am_flav;
DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
/* a new LEA. */
/* If the LEA contains already a frame_entity then we also */
/* create a new one otherwise we would loose it. */
- if ((isadd && !be_is_NoReg(cg, index) && (am_flav & ia32_am_I)) || /* no new LEA if index already set */
+ if ((isadd && !be_is_NoReg(cg, index) && (am_flav & ia32_I)) || /* no new LEA if index already set */
get_ia32_frame_ent(left) || /* no new LEA if stack access */
(have_am_sc && get_ia32_am_sc(left))) /* no new LEA if AM symconst already present */
{
DBG((mod, LEVEL_1, "\tleave old LEA, creating new one\n"));
}
else {
+ ir_node *assim_lea_idx, *assim_lea_base;
+
DBG((mod, LEVEL_1, "\tgot LEA as left operand ... assimilating\n"));
offs = get_ia32_am_offs(left);
am_sc = have_am_sc ? am_sc : get_ia32_am_sc(left);
have_am_sc = am_sc ? 1 : 0;
am_sc_sign = is_ia32_am_sc_sign(left);
- base = get_irn_n(left, 0);
- index = get_irn_n(left, 1);
scale = get_ia32_am_scale(left);
+
+ assim_lea_base = get_irn_n(left, 0);
+ assim_lea_idx = get_irn_n(left, 1);
+
+ if (be_is_NoReg(cg, assim_lea_base) && ! be_is_NoReg(cg, assim_lea_idx)) {
+ /* assimilate index */
+ assert(be_is_NoReg(cg, index) && ! be_is_NoReg(cg, base) && "operand mismatch for LEA assimilation");
+ index = assim_lea_idx;
+ }
+ else if (! be_is_NoReg(cg, assim_lea_base) && be_is_NoReg(cg, assim_lea_idx)) {
+ /* assimilate base */
+ assert(! be_is_NoReg(cg, index) && (base == left) && "operand mismatch for LEA assimilation");
+ base = assim_lea_base;
+ }
+ else {
+ assert(0 && "operand mismatch for LEA assimilation");
+ }
}
}
set_ia32_op_type(res, ia32_AddrModeS);
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
+
DBG((mod, LEVEL_1, "\tLEA [%+F + %+F * %d + %s]\n", base, index, scale, get_ia32_am_offs(res)));
/* get the result Proj of the Add/Sub */
/**
* Prints the old node name on cg obst and returns a pointer to it.
*/
-const char *ia32_get_old_node_name(ia32_transform_env_t *env) {
- ia32_isa_t *isa = (ia32_isa_t *)env->cg->arch_env->isa;
+const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
+ ia32_isa_t *isa = (ia32_isa_t *)cg->arch_env->isa;
- lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", env->irn);
+ lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
obstack_1grow(isa->name_obst, 0);
isa->name_obst_size += obstack_object_size(isa->name_obst);
return obstack_finish(isa->name_obst);
}
}
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, mode);
/* set AM support */
set_ia32_am_support(new_op, ia32_am_Dest);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, mode);
set_ia32_emit_cl(new_op);
set_ia32_am_support(new_op, ia32_am_Dest);
}
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, mode);
}
}
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, mode);
else {
new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
set_ia32_am_support(new_op, ia32_am_None);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
}
return new_op;
else {
new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
set_ia32_am_support(new_op, ia32_am_None);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
}
return new_op;
}
}
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, mode);
be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(res, mode_Is);
set_ia32_am_support(new_op, ia32_am_Source);
}
set_ia32_res_mode(new_op, get_irn_mode(get_proj_for_pn(env->irn, pn_Quot_res)));
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
set_ia32_sc(new_op, name);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(new_op, env->mode);
set_ia32_immop_type(new_op, ia32_ImmSymConst);
else {
env->cg->used_x87 = 1;
new_op = new_rd_ia32_vfchs(env->dbg, env->irg, env->block, op, env->mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
}
}
else {
set_ia32_sc(res, name);
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(res, mode);
set_ia32_immop_type(res, ia32_ImmSymConst);
else {
env->cg->used_x87 = 1;
res = new_rd_ia32_vfabs(dbg, irg, block, op, mode);
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
}
}
else {
res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(res, mode);
p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
res = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem, mode_T);
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(res, mode);
res = new_rd_Proj(dbg, irg, block, res, mode, 0);
res = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem, mode_T);
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_res_mode(res, mode);
res = new_rd_Proj(dbg, irg, block, res, mode, 0);
set_ia32_am_flavour(new_op, am_flav);
set_ia32_ls_mode(new_op, mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
set_ia32_ls_mode(new_op, get_irn_mode(val));
set_ia32_immop_type(new_op, immop);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
copy_ia32_Immop_attr(res, and);
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
return res;
}
}
set_ia32_res_mode(res, get_irn_mode(sel));
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
return res;
}
set_ia32_immop_type(res, ia32_ImmConst);
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
return res;
}
ir_node *new_op = new_rd_ia32_CMov(env->dbg, env->irg, env->block, \
get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
// proj = new_rd_Proj(dbg, irg, block, new_op, src_mode, 0);
// set_ia32_Immop_tarval(new_op, new_tarval_from_long(n - m, mode_Is));
// set_ia32_am_support(new_op, ia32_am_Source);
-// SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+// SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
// /* ASHR Sn, n - m */
// new_op = new_rd_ia32_Shrs(dbg, irg, block, noreg, noreg, proj, noreg, nomem, mode_T);
// set_ia32_Immop_tarval(new_op, new_tarval_from_long(n - m, mode_Is));
new_op = new_rd_ia32_Conv_FP2I(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
/* if target mode is not int: add an additional downscale convert */
if (tgt_bits < 32) {
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_am_support(new_op, ia32_am_Source);
set_ia32_tgt_mode(new_op, tgt_mode);
set_ia32_src_mode(new_op, src_mode);
}
if (new_op) {
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
set_ia32_tgt_mode(new_op, tgt_mode);
set_ia32_src_mode(new_op, src_mode);
set_ia32_am_flavour(new_op, ia32_B);
set_ia32_ls_mode(new_op, mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, 0);
}
set_ia32_use_frame(new_op);
set_ia32_immop_type(new_op, ia32_ImmConst);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
}
set_ia32_am_flavour(new_op, ia32_B);
set_ia32_ls_mode(new_op, mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
set_ia32_am_flavour(new_op, ia32_B);
set_ia32_ls_mode(new_op, mode);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
return new_op;
}
set_ia32_am_support(res, ia32_am_Full);
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(&tenv));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(tenv.cg, irn));
/* copy register */
slots = get_ia32_slots(res);
slots[0] = in2_reg;
set_ia32_immop_type(res, ia32_ImmConst);
}
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(&tenv));
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
/* add Add to schedule */
sched_add_before(irn, res);