-/**
- * Transforms a Sub or xSub into Neg--Add iff OUT_REG == SRC2_REG.
- * THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
- */
-void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
- ia32_transform_env_t tenv;
- ir_node *in1, *in2, *noreg, *nomem, *res;
- const arch_register_t *in1_reg, *in2_reg, *out_reg, **slots;
-
- /* Return if AM node or not a Sub or xSub */
- if (get_ia32_op_type(irn) != ia32_Normal || !(is_ia32_Sub(irn) || is_ia32_xSub(irn)))
- return;
-
- noreg = ia32_new_NoReg_gp(cg);
- nomem = new_rd_NoMem(cg->irg);
- in1 = get_irn_n(irn, 2);
- in2 = get_irn_n(irn, 3);
- in1_reg = arch_get_irn_register(cg->arch_env, in1);
- in2_reg = arch_get_irn_register(cg->arch_env, in2);
- out_reg = get_ia32_out_reg(irn, 0);
-
- tenv.block = get_nodes_block(irn);
- tenv.dbg = get_irn_dbg_info(irn);
- tenv.irg = cg->irg;
- tenv.irn = irn;
- tenv.mode = get_ia32_res_mode(irn);
- tenv.cg = cg;
- DEBUG_ONLY(tenv.mod = cg->mod;)
-
- /* in case of sub and OUT == SRC2 we can transform the sequence into neg src2 -- add */
- if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
- /* generate the neg src2 */
- res = gen_Minus_ex(&tenv, in2);
- arch_set_irn_register(cg->arch_env, res, in2_reg);
-
- /* add to schedule */
- sched_add_before(irn, res);
-
- /* generate the add */
- if (mode_is_float(tenv.mode)) {
- res = new_rd_ia32_xAdd(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem);
- set_ia32_am_support(res, ia32_am_Source);
- }
- else {
- res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem);
- set_ia32_am_support(res, ia32_am_Full);
- set_ia32_commutative(res);
- }
- set_ia32_res_mode(res, tenv.mode);
-
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(tenv.cg, irn));
- /* copy register */
- slots = get_ia32_slots(res);
- slots[0] = in2_reg;
-
- /* add to schedule */
- sched_add_before(irn, res);
-
- /* remove the old sub */
- sched_remove(irn);
-
- DBG_OPT_SUB2NEGADD(irn, res);
-
- /* exchange the add and the sub */
- exchange(irn, res);
- }
-}
-
-/**
- * Transforms a LEA into an Add if possible
- * THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
- */
-void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) {
- ia32_am_flavour_t am_flav;
- int imm = 0;
- ir_node *res = NULL;
- ir_node *nomem, *noreg, *base, *index, *op1, *op2;
- char *offs;
- ia32_transform_env_t tenv;
- const arch_register_t *out_reg, *base_reg, *index_reg;
-
- /* must be a LEA */
- if (! is_ia32_Lea(irn))
- return;
-
- am_flav = get_ia32_am_flavour(irn);
-
- if (get_ia32_am_sc(irn))
- return;
-
- /* only some LEAs can be transformed to an Add */
- if (am_flav != ia32_am_B && am_flav != ia32_am_OB && am_flav != ia32_am_OI && am_flav != ia32_am_BI)
- return;
-
- noreg = ia32_new_NoReg_gp(cg);
- nomem = new_rd_NoMem(cg->irg);
- op1 = noreg;
- op2 = noreg;
- base = get_irn_n(irn, 0);
- index = get_irn_n(irn,1);
-
- offs = get_ia32_am_offs(irn);
-
- /* offset has a explicit sign -> we need to skip + */
- if (offs && offs[0] == '+')
- offs++;
-
- out_reg = arch_get_irn_register(cg->arch_env, irn);
- base_reg = arch_get_irn_register(cg->arch_env, base);
- index_reg = arch_get_irn_register(cg->arch_env, index);
-
- tenv.block = get_nodes_block(irn);
- tenv.dbg = get_irn_dbg_info(irn);
- tenv.irg = cg->irg;
- tenv.irn = irn;
- DEBUG_ONLY(tenv.mod = cg->mod;)
- tenv.mode = get_irn_mode(irn);
- tenv.cg = cg;
-
- switch(get_ia32_am_flavour(irn)) {
- case ia32_am_B:
- /* out register must be same as base register */
- if (! REGS_ARE_EQUAL(out_reg, base_reg))
- return;
-
- op1 = base;
- break;
- case ia32_am_OB:
- /* out register must be same as base register */
- if (! REGS_ARE_EQUAL(out_reg, base_reg))
- return;
-
- op1 = base;
- imm = 1;
- break;
- case ia32_am_OI:
- /* out register must be same as index register */
- if (! REGS_ARE_EQUAL(out_reg, index_reg))
- return;
-
- op1 = index;
- imm = 1;
- break;
- case ia32_am_BI:
- /* out register must be same as one in register */
- if (REGS_ARE_EQUAL(out_reg, base_reg)) {
- op1 = base;
- op2 = index;
- }
- else if (REGS_ARE_EQUAL(out_reg, index_reg)) {
- op1 = index;
- op2 = base;
- }
- else {
- /* in registers a different from out -> no Add possible */
- return;
- }
- default:
- break;
- }
-
- res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, op1, op2, nomem);
- arch_set_irn_register(cg->arch_env, res, out_reg);
- set_ia32_op_type(res, ia32_Normal);
- set_ia32_commutative(res);
- set_ia32_res_mode(res, tenv.mode);
-
- if (imm) {
- set_ia32_cnst(res, offs);
- set_ia32_immop_type(res, ia32_ImmConst);
- }
-
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
-
- /* add Add to schedule */
- sched_add_before(irn, res);
-
- DBG_OPT_LEA2ADD(irn, res);
-
- res = new_rd_Proj(tenv.dbg, tenv.irg, tenv.block, res, tenv.mode, pn_ia32_Add_res);
-
- /* add result Proj to schedule */
- sched_add_before(irn, res);
-
- /* remove the old LEA */
- sched_remove(irn);
-
- /* exchange the Add and the LEA */
- exchange(irn, res);
-}
-