summaryrefslogtreecommitdiffhomepage
path: root/ir/be/amd64
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2018-03-16 10:43:37 +0100
committerChristoph Mallon <christoph.mallon@gmx.de>2018-03-20 08:39:47 +0100
commit4f5faa5db18da79edaee7ed2c6eca498a4510d8c (patch)
tree923784a3e6587e9425257dfb1cda944a2bb3ba51 /ir/be/amd64
parente8b75f418c9479f978b1bb2ed3e7466ece576ee2 (diff)
amd64: Add peephole optimization `cmp $0, %r` -> `test %r, %r`.
Diffstat (limited to 'ir/be/amd64')
-rw-r--r--ir/be/amd64/amd64_optimize.c25
-rw-r--r--ir/be/amd64/amd64_spec.pl24
2 files changed, 39 insertions, 10 deletions
diff --git a/ir/be/amd64/amd64_optimize.c b/ir/be/amd64/amd64_optimize.c
index b5b2441..77ef1f6 100644
--- a/ir/be/amd64/amd64_optimize.c
+++ b/ir/be/amd64/amd64_optimize.c
@@ -17,6 +17,30 @@
#include "gen_amd64_regalloc_if.h"
#include "util.h"
+static void peephole_amd64_cmp(ir_node *const node)
+{
+ /* cmp $0, %reg -> test %reg, %reg */
+ amd64_binop_addr_attr_t const *const attr = get_amd64_binop_addr_attr_const(node);
+ if (attr->base.base.op_mode == AMD64_OP_REG_IMM) {
+ x86_imm32_t const *const imm = &attr->u.immediate;
+ if (imm->kind == X86_IMM_VALUE && imm->offset == 0) {
+ amd64_binop_addr_attr_t test_attr = *attr;
+ test_attr.base.base.op_mode = AMD64_OP_REG_REG;
+
+ dbg_info *const dbgi = get_irn_dbg_info(node);
+ ir_node *const block = get_nodes_block(node);
+ ir_node *const base = get_irn_n(node, attr->base.addr.base_input);
+ ir_node *const in[] = { base, base };
+ ir_node *const test = new_bd_amd64_test(dbgi, block, ARRAY_SIZE(in), in, amd64_reg_reg_reqs, &test_attr);
+
+ arch_register_t const *const oreg = arch_get_irn_register_out(node, pn_amd64_cmp_flags);
+ arch_set_irn_register_out(test, pn_amd64_test_flags, oreg);
+
+ be_peephole_replace(node, test);
+ }
+ }
+}
+
static void make_add(ir_node *const node, size_t const n_in, ir_node *const *const in, arch_register_req_t const **const reqs, amd64_binop_addr_attr_t const *const attr, arch_register_t const *const oreg)
{
dbg_info *const dbgi = get_irn_dbg_info(node);
@@ -117,6 +141,7 @@ static void peephole_be_IncSP(ir_node *const node)
void amd64_peephole_optimization(ir_graph *const irg)
{
ir_clear_opcodes_generic_func();
+ register_peephole_optimization(op_amd64_cmp, peephole_amd64_cmp);
register_peephole_optimization(op_amd64_lea, peephole_amd64_lea);
register_peephole_optimization(op_amd64_mov_imm, peephole_amd64_mov_imm);
register_peephole_optimization(op_be_IncSP, peephole_be_IncSP);
diff --git a/ir/be/amd64/amd64_spec.pl b/ir/be/amd64/amd64_spec.pl
index d70e2af..be20d85 100644
--- a/ir/be/amd64/amd64_spec.pl
+++ b/ir/be/amd64/amd64_spec.pl
@@ -130,6 +130,17 @@ my $binop_commutative = {
emit => "{name}%M %AM",
};
+my $cmpop = {
+ irn_flags => [ "modify_flags", "rematerializable" ],
+ state => "exc_pinned",
+ in_reqs => "...",
+ out_reqs => [ "none", "flags", "mem" ],
+ outs => [ "dummy", "flags", "M" ],
+ attr_type => "amd64_binop_addr_attr_t",
+ attr => "const amd64_binop_addr_attr_t *attr_init",
+ emit => "{name}%M %AM",
+};
+
my $sextop = {
in_reqs => [ "rax" ],
out_reqs => [ "rdx" ],
@@ -457,16 +468,9 @@ jmp => {
."x86_insn_size_t size = X86_SIZE_64;\n",
},
-cmp => {
- irn_flags => [ "modify_flags", "rematerializable" ],
- state => "exc_pinned",
- in_reqs => "...",
- out_reqs => [ "none", "flags", "mem" ],
- outs => [ "dummy", "flags", "M" ],
- attr_type => "amd64_binop_addr_attr_t",
- attr => "const amd64_binop_addr_attr_t *attr_init",
- emit => "cmp%M %AM",
-},
+cmp => { template => $cmpop },
+
+test => { template => $cmpop },
cmpxchg => {
irn_flags => [ "modify_flags" ],