Commit 53ad01ab authored by Christoph Mallon's avatar Christoph Mallon
Browse files

Defer decision whether to create Test(x, x) instead of Cmp(x, 0) until...

Defer decision whether to create Test(x, x) instead of Cmp(x, 0) until peephole optimisation. This improves the code when Cmp(AM, 0) is undone by the flags repair phase.

[r21134]
parent 52e9462f
......@@ -160,6 +160,62 @@ static ir_node *turn_into_mode_t(ir_node *node)
return new_node;
}
/**
* Replace Cmp(x, 0) by a Test(x, x)
*/
static void peephole_ia32_Cmp(ir_node *const node)
{
ir_node *right;
ia32_immediate_attr_t const *imm;
dbg_info *dbgi;
ir_graph *irg;
ir_node *block;
ir_node *noreg;
ir_node *nomem;
ir_node *op;
ia32_attr_t const *attr;
int ins_permuted;
int cmp_unsigned;
ir_node *test;
arch_register_t const *reg;
if (get_ia32_op_type(node) != ia32_Normal)
return;
right = get_irn_n(node, n_ia32_Cmp_right);
if (!is_ia32_Immediate(right))
return;
imm = get_ia32_immediate_attr_const(right);
if (imm->symconst != NULL || imm->offset != 0)
return;
dbgi = get_irn_dbg_info(node);
irg = current_ir_graph;
block = get_nodes_block(node);
noreg = ia32_new_NoReg_gp(cg);
nomem = get_irg_no_mem(irg);
op = get_irn_n(node, n_ia32_Cmp_left);
attr = get_irn_generic_attr(node);
ins_permuted = attr->data.ins_permuted;
cmp_unsigned = attr->data.cmp_unsigned;
if (is_ia32_Cmp(node)) {
test = new_rd_ia32_Test(dbgi, irg, block, noreg, noreg, nomem,
op, op, ins_permuted, cmp_unsigned);
} else {
test = new_rd_ia32_Test8Bit(dbgi, irg, block, noreg, noreg, nomem,
op, op, ins_permuted, cmp_unsigned);
}
set_ia32_ls_mode(test, get_ia32_ls_mode(node));
reg = arch_get_irn_register(arch_env, node);
arch_set_irn_register(arch_env, test, reg);
sched_add_before(node, test);
be_peephole_exchange(node, test);
}
/**
* Peephole optimization for Test instructions.
* We can remove the Test, if a zero flags was produced which is still
......@@ -1046,12 +1102,14 @@ void ia32_peephole_optimization(ia32_code_gen_t *new_cg)
/* register peephole optimisations */
clear_irp_opcodes_generic_func();
register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const);
register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea);
register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test);
register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const);
register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea);
register_peephole_optimisation(op_ia32_Cmp, peephole_ia32_Cmp);
register_peephole_optimisation(op_ia32_Cmp8Bit, peephole_ia32_Cmp);
register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test);
register_peephole_optimisation(op_ia32_Test8Bit, peephole_ia32_Test);
register_peephole_optimisation(op_be_Return, peephole_ia32_Return);
register_peephole_optimisation(op_be_Return, peephole_ia32_Return);
if (! ia32_cg_config.use_imul_mem_imm32)
register_peephole_optimisation(op_ia32_IMul, peephole_ia32_Imul_split);
if (ia32_cg_config.use_pxor)
......
......@@ -2723,64 +2723,31 @@ static ir_node *gen_Cmp(ir_node *node)
assert(ia32_mode_needs_gp_reg(cmp_mode));
/* we prefer the Test instruction where possible except cases where
* we can use SourceAM */
/* Prefer the Test instruction, when encountering (x & y) ==/!= 0 */
cmp_unsigned = !mode_is_signed(cmp_mode);
if (is_Const_0(right)) {
if (is_And(left) &&
get_irn_n_edges(left) == 1 &&
can_fold_test_and(node)) {
/* Test(and_left, and_right) */
ir_node *and_left = get_And_left(left);
ir_node *and_right = get_And_right(left);
ir_mode *mode = get_irn_mode(and_left);
match_arguments(&am, block, and_left, and_right, NULL,
match_commutative |
match_am | match_8bit_am | match_16bit_am |
match_am_and_immediates | match_immediate |
match_8bit | match_16bit);
if (get_mode_size_bits(mode) == 8) {
new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op1,
am.new_op2, am.ins_permuted,
cmp_unsigned);
} else {
new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op1,
am.new_op2, am.ins_permuted, cmp_unsigned);
}
if (is_Const_0(right) &&
is_And(left) &&
get_irn_n_edges(left) == 1 &&
can_fold_test_and(node)) {
/* Test(and_left, and_right) */
ir_node *and_left = get_And_left(left);
ir_node *and_right = get_And_right(left);
ir_mode *mode = get_irn_mode(and_left);
match_arguments(&am, block, and_left, and_right, NULL,
match_commutative |
match_am | match_8bit_am | match_16bit_am |
match_am_and_immediates | match_immediate |
match_8bit | match_16bit);
if (get_mode_size_bits(mode) == 8) {
new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op1,
am.new_op2, am.ins_permuted,
cmp_unsigned);
} else {
match_arguments(&am, block, NULL, left, NULL,
match_am | match_8bit_am | match_16bit_am |
match_8bit | match_16bit);
if (am.op_type == ia32_AddrModeS) {
/* Cmp(AM, 0) */
ir_node *imm_zero = try_create_Immediate(right, 0);
if (get_mode_size_bits(cmp_mode) == 8) {
new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
imm_zero, am.ins_permuted,
cmp_unsigned);
} else {
new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
imm_zero, am.ins_permuted, cmp_unsigned);
}
} else {
/* Test(left, left) */
if (get_mode_size_bits(cmp_mode) == 8) {
new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
am.new_op2, am.ins_permuted,
cmp_unsigned);
} else {
new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
am.new_op2, am.ins_permuted,
cmp_unsigned);
}
}
new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op1,
am.new_op2, am.ins_permuted, cmp_unsigned);
}
} else {
/* Cmp(left, right) */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment