set_ia32_is_remat(new);
}
+typedef enum produces_flag_t {
+ produces_no_flag,
+ produces_flag_zero,
+ produces_flag_carry
+} produces_flag_t;
+
/**
- * Returns non-zero if the given node produces
- * a zero flag.
+ * Return which usable flag the given node produces
*
* @param node the node to check
- * @param pn if >= 0, the projection number of the used result
+ * @param pn the projection number of the used result
*/
-static int produces_zero_flag(ir_node *node, int pn)
+static produces_flag_t produces_test_flag(ir_node *node, int pn)
{
ir_node *count;
const ia32_immediate_attr_t *imm_attr;
if (!is_ia32_irn(node))
- return 0;
-
- if (pn >= 0) {
- if (pn != pn_ia32_res)
- return 0;
- }
+ return produces_no_flag;
switch (get_ia32_irn_opcode(node)) {
- case iro_ia32_Add:
- case iro_ia32_Adc:
- case iro_ia32_And:
- case iro_ia32_Or:
- case iro_ia32_Xor:
- case iro_ia32_Sub:
- case iro_ia32_Sbb:
- case iro_ia32_Neg:
- case iro_ia32_Inc:
- case iro_ia32_Dec:
- return 1;
-
- case iro_ia32_ShlD:
- case iro_ia32_ShrD:
- assert(n_ia32_ShlD_count == n_ia32_ShrD_count);
- count = get_irn_n(node, n_ia32_ShlD_count);
- goto check_shift_amount;
-
- case iro_ia32_Shl:
- case iro_ia32_Shr:
- case iro_ia32_Sar:
- assert(n_ia32_Shl_count == n_ia32_Shr_count
- && n_ia32_Shl_count == n_ia32_Sar_count);
- count = get_irn_n(node, n_ia32_Shl_count);
+ case iro_ia32_Add:
+ case iro_ia32_Adc:
+ case iro_ia32_And:
+ case iro_ia32_Or:
+ case iro_ia32_Xor:
+ case iro_ia32_Sub:
+ case iro_ia32_Sbb:
+ case iro_ia32_Neg:
+ case iro_ia32_Inc:
+ case iro_ia32_Dec:
+ break;
+
+ case iro_ia32_ShlD:
+ case iro_ia32_ShrD:
+ assert(n_ia32_ShlD_count == n_ia32_ShrD_count);
+ count = get_irn_n(node, n_ia32_ShlD_count);
+ goto check_shift_amount;
+
+ case iro_ia32_Shl:
+ case iro_ia32_Shr:
+ case iro_ia32_Sar:
+ assert(n_ia32_Shl_count == n_ia32_Shr_count
+ && n_ia32_Shl_count == n_ia32_Sar_count);
+ count = get_irn_n(node, n_ia32_Shl_count);
check_shift_amount:
- /* when shift count is zero the flags are not affected, so we can only
- * do this for constants != 0 */
- if (!is_ia32_Immediate(count))
- return 0;
-
- imm_attr = get_ia32_immediate_attr_const(count);
- if (imm_attr->symconst != NULL)
- return 0;
- if ((imm_attr->offset & 0x1f) == 0)
- return 0;
- return 1;
-
- default:
- break;
+ /* when shift count is zero the flags are not affected, so we can only
+ * do this for constants != 0 */
+ if (!is_ia32_Immediate(count))
+ return produces_no_flag;
+
+ imm_attr = get_ia32_immediate_attr_const(count);
+ if (imm_attr->symconst != NULL)
+ return produces_no_flag;
+ if ((imm_attr->offset & 0x1f) == 0)
+ return produces_no_flag;
+ break;
+
+ case iro_ia32_Mul:
+ return pn == pn_ia32_Mul_res_high ?
+ produces_flag_carry : produces_no_flag;
+
+ default:
+ return produces_no_flag;
}
- return 0;
+
+ return pn == pn_ia32_res ?
+ produces_flag_zero : produces_no_flag;
}
/**
res_proj = new_r_Proj(current_ir_graph, block, new_node, mode_Iu,
pn_ia32_res);
- reg = arch_get_irn_register(arch_env, node);
+ reg = arch_get_irn_register(node);
arch_set_irn_register(arch_env, res_proj, reg);
sched_add_before(node, new_node);
}
set_ia32_ls_mode(test, get_ia32_ls_mode(node));
- reg = arch_get_irn_register(arch_env, node);
+ reg = arch_get_irn_register(node);
arch_set_irn_register(arch_env, test, reg);
foreach_out_edge_safe(node, edge, tmp) {
ir_node *flags_proj;
ir_node *block;
ir_mode *flags_mode;
- int pn = -1;
+ int pn = pn_ia32_res;
ir_node *schedpoint;
const ir_edge_t *edge;
}
}
- if(!produces_zero_flag(left, pn))
- return;
+ switch (produces_test_flag(left, pn)) {
+ case produces_flag_zero:
+ break;
+
+ case produces_flag_carry:
+ foreach_out_edge(node, edge) {
+ ir_node *user = get_edge_src_irn(edge);
+ int pnc = get_ia32_condcode(user);
+
+ switch (pnc) {
+ case pn_Cmp_Eq: pnc = pn_Cmp_Ge | ia32_pn_Cmp_unsigned; break;
+ case pn_Cmp_Lg: pnc = pn_Cmp_Lt | ia32_pn_Cmp_unsigned; break;
+ default: panic("unexpected pn");
+ }
+ set_ia32_condcode(user, pnc);
+ }
+ break;
+
+ default:
+ return;
+ }
left = turn_into_mode_t(left);
val = get_irn_n(store, n_ia32_unary_op);
mem = get_irn_n(store, n_ia32_mem);
- spreg = arch_get_irn_register(cg->arch_env, curr_sp);
+ spreg = arch_get_irn_register(curr_sp);
push = new_rd_ia32_Push(get_irn_dbg_info(store), irg, block, noreg, noreg, mem, val, curr_sp);
copy_mark(store, push);
/* not a GP copy, ignore */
continue;
}
- dreg = arch_get_irn_register(arch_env, node);
- sreg = arch_get_irn_register(arch_env, be_get_Copy_op(node));
+ dreg = arch_get_irn_register(node);
+ sreg = arch_get_irn_register(be_get_Copy_op(node));
if (regmask & copymask & (1 << sreg->index)) {
break;
}
if (loads[loadslot] != NULL)
break;
- dreg = arch_get_irn_register(arch_env, node);
+ dreg = arch_get_irn_register(node);
if (regmask & (1 << dreg->index)) {
/* this register is already used */
break;
const arch_register_t *reg;
mem = get_irn_n(load, n_ia32_mem);
- reg = arch_get_irn_register(arch_env, load);
+ reg = arch_get_irn_register(load);
pop = new_rd_ia32_Pop(get_irn_dbg_info(load), irg, block, mem, pred_sp);
arch_set_irn_register(arch_env, pop, reg);
/* transform Load->IncSP combinations to Pop where possible */
peephole_Load_IncSP_to_pop(node);
- if (arch_get_irn_register(arch_env, node) != esp)
+ if (arch_get_irn_register(node) != esp)
return;
/* replace IncSP -4 by Pop freereg when possible */
if (be_peephole_get_value(CLASS_ia32_flags, REG_EFLAGS) != NULL)
return;
- reg = arch_get_irn_register(arch_env, node);
+ reg = arch_get_irn_register(node);
assert(be_peephole_get_reg_value(reg) == NULL);
/* create xor(produceval, produceval) */
base = NULL;
base_reg = NULL;
} else {
- base_reg = arch_get_irn_register(arch_env, base);
+ base_reg = arch_get_irn_register(base);
}
if(is_noreg(cg, index)) {
index = NULL;
index_reg = NULL;
} else {
- index_reg = arch_get_irn_register(arch_env, index);
+ index_reg = arch_get_irn_register(index);
}
if(base == NULL && index == NULL) {
return;
}
- out_reg = arch_get_irn_register(arch_env, node);
+ out_reg = arch_get_irn_register(node);
scale = get_ia32_am_scale(node);
assert(!is_ia32_need_stackent(node) || get_ia32_frame_ent(node) != NULL);
/* check if we have immediates values (frame entities should already be