}
else
cnst = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode);
+
set_ia32_Const_attr(cnst, env->irn);
+
return cnst;
}
int same_args = 1;
for (i = 0; i < n; i++) {
- if (get_irn_n(cand, i) == get_irn_n(irn, i)) {
+ if (get_irn_n(cand, i) != get_irn_n(irn, i)) {
same_args = 0;
break;
}
DBG((cg->mod, LEVEL_1, "replacing %+F by ", irn));
DBG_OPT_CJMP(irn);
- set_irn_op(irn, op_ia32_CJmp);
+ set_irn_op(irn, op_ia32_CJmpAM);
DB((cg->mod, LEVEL_1, "%+F\n", irn));
}
proj_res = new_r_Proj(current_ir_graph, bl, push, get_irn_mode(sp), pn_ia32_Push_stack);
proj_M = new_r_Proj(current_ir_graph, bl, push, mode_M, pn_ia32_Push_M);
+ /* copy a possible constant from the store */
+ set_ia32_id_cnst(push, get_ia32_id_cnst(irn));
+ set_ia32_immop_type(push, get_ia32_immop_type(irn));
+
/* the push must have SP out register */
arch_set_irn_register(cg->arch_env, push, arch_get_irn_register(cg->arch_env, sp));
sched_add_before(proj_res,pop);
}
-/**
-
/**
* Tries to optimize two following IncSP.
*/
ia32_optimize_CondJmp(irn, cg);
else if (be_is_IncSP(irn))
ia32_optimize_IncSP(irn, cg);
+ else if (is_ia32_Store(irn))
+ ia32_create_Push(irn, cg);
}
}
+/**
+ * Sets new_right index of irn to right and new_left index to left.
+ * Also exchange left and right
+ */
+static void exchange_left_right(ir_node *irn, ir_node **left, ir_node **right, int new_left, int new_right) {
+ ir_node *temp;
+
+ set_irn_n(irn, new_right, *right);
+ set_irn_n(irn, new_left, *left);
+
+ temp = *left;
+ *left = *right;
+ *right = temp;
+
+ /* this is only needed for Compares, but currently ALL nodes
+ * have this attribute :-) */
+ set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
+}
+
/**
* Optimizes a pattern around irn to address mode if possible.
*/
ir_node *left, *right, *temp;
ir_node *store, *load, *mem_proj;
ir_node *succ, *addr_b, *addr_i;
- int check_am_src = 0;
+ int check_am_src = 0;
+ int need_exchange_on_fail = 0;
DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
if (! is_ia32_irn(irn))
/* operand is a load, so we only need to check right operand. */
if (pred_is_specific_nodeblock(block, left, is_ia32_Ld))
{
- set_irn_n(irn, 2, right);
- set_irn_n(irn, 3, left);
-
- temp = left;
- left = right;
- right = temp;
+ exchange_left_right(irn, &left, &right, 3, 2);
+ need_exchange_on_fail = 1;
}
}
temp = left;
left = right;
right = temp;
+
+ /* this is only needed for Compares, but currently ALL nodes
+ * have this attribute :-) */
+ set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
}
}
check_am_src = 1;
}
+ /* was exchanged but optimize failed: exchange back */
+ if (check_am_src && need_exchange_on_fail)
+ exchange_left_right(irn, &left, &right, 3, 2);
+
+ need_exchange_on_fail = 0;
+
/* normalize commutative ops */
- if (node_is_ia32_comm(irn)) {
+ if (check_am_src && node_is_ia32_comm(irn)) {
/* Assure that left operand is always a Load if there is one */
/* because non-commutative ops can only use Source AM if the */
/* left operand is a Load, so we only need to check the left */
/* operand afterwards. */
if (pred_is_specific_nodeblock(block, right, is_ia32_Ld)) {
- set_irn_n(irn, 2, right);
- set_irn_n(irn, 3, left);
-
- temp = left;
- left = right;
- right = temp;
+ exchange_left_right(irn, &left, &right, 3, 2);
+ need_exchange_on_fail = 1;
}
}
if (get_irn_arity(irn) == 5) {
/* binary AMop */
set_irn_n(irn, 4, get_irn_n(left, 2));
+
+ /* this is only needed for Compares, but currently ALL nodes
+ * have this attribute :-) */
+ set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
+
+ /* disconnect from Load */
+ /* (make second op -> first, set second in to noreg) */
+ set_irn_n(irn, 2, get_irn_n(irn, 3));
+ set_irn_n(irn, 3, noreg_gp);
}
else {
/* unary AMop */
set_irn_n(irn, 3, get_irn_n(left, 2));
- }
- /* disconnect from Load */
- set_irn_n(irn, 2, noreg_gp);
+ /* disconnect from Load */
+ set_irn_n(irn, 2, noreg_gp);
+ }
DBG_OPT_AM_S(left, irn);
DB((mod, LEVEL_1, "merged with %+F into source AM\n", left));
}
+ else {
+ /* was exchanged but optimize failed: exchange back */
+ if (need_exchange_on_fail)
+ exchange_left_right(irn, &left, &right, 3, 2);
+ }
}
}
}