summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJohannes Bucher <johannes.bucher2@student.kit.edu>2020-02-20 15:56:27 +0100
committerJohannes Bucher <johannes.bucher2@student.kit.edu>2020-02-21 14:08:04 +0100
commit8ec9cdb5700d3fac4ffe6331cb26364b9dc3d756 (patch)
tree42015aa028fda8cffe86947d0e4a6e8dac30729b
parent8fa5acb79803197f6bf2d6db38b920453688f463 (diff)
amd64: peephole: remove consecutive zero extensions
-rw-r--r--ir/be/amd64/amd64_optimize.c35
-rw-r--r--ir/be/bepeephole.c11
-rw-r--r--ir/be/bepeephole.h7
3 files changed, 53 insertions, 0 deletions
diff --git a/ir/be/amd64/amd64_optimize.c b/ir/be/amd64/amd64_optimize.c
index 77ef1f6..2c94f7a 100644
--- a/ir/be/amd64/amd64_optimize.c
+++ b/ir/be/amd64/amd64_optimize.c
@@ -15,6 +15,7 @@
#include "bepeephole.h"
#include "besched.h"
#include "gen_amd64_regalloc_if.h"
+#include "iredges_t.h"
#include "util.h"
static void peephole_amd64_cmp(ir_node *const node)
@@ -133,6 +134,39 @@ static void peephole_amd64_mov_imm(ir_node *const node)
}
}
+static void peephole_amd64_mov_gp(ir_node *const node)
+{
+ /*
+ * amd64_mov_gp instructions always perform a mov with zero extension (or the mov instruction overwrites the whole
+ * quadword anyway).
+ * This optimization removes unnecessary zero extensions, for example after a load:
+ * movzwl (%r1), %r2
+ * movzwl %r2, %r2 <-- remove this instruction
+ */
+ ir_node *const pred = get_irn_n(node, 0);
+ if (!is_Proj(pred)) {
+ return;
+ }
+ amd64_addr_attr_t const *const attr = get_amd64_addr_attr_const(node);
+ x86_addr_t const *const addr = &attr->addr;
+ if (addr->variant != X86_ADDR_REG) {
+ return;
+ }
+ ir_node *const operand = get_Proj_pred(pred);
+ if (is_amd64_mov_gp(operand)) {
+ if (get_amd64_attr_const(node)->size < get_amd64_attr_const(operand)->size) {
+ return;
+ }
+ arch_register_t const *const operand_out = arch_get_irn_register_out(operand, pn_amd64_mov_gp_res);
+ arch_register_t const *const node_out = arch_get_irn_register_out(node, pn_amd64_mov_gp_res);
+ arch_register_t const *const node_in = arch_get_irn_register_in(node, 0);
+ if (operand_out == node_out && node_in == node_out) {
+ ir_node *const node_proj = be_get_or_make_Proj_for_pn(node, pn_amd64_mov_gp_res);
+ be_peephole_exchange_using_proj(node_proj, pred);
+ }
+ }
+}
+
static void peephole_be_IncSP(ir_node *const node)
{
be_peephole_IncSP_IncSP(node);
@@ -144,6 +178,7 @@ void amd64_peephole_optimization(ir_graph *const irg)
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_amd64_mov_gp, peephole_amd64_mov_gp);
register_peephole_optimization(op_be_IncSP, peephole_be_IncSP);
be_peephole_opt(irg);
}
diff --git a/ir/be/bepeephole.c b/ir/be/bepeephole.c
index d291d3e..89d2bf8 100644
--- a/ir/be/bepeephole.c
+++ b/ir/be/bepeephole.c
@@ -130,6 +130,17 @@ static void be_peephole_before_exchange(const ir_node *old_node,
be_liveness_remove(lv, old_node);
}
+void be_peephole_exchange_using_proj(ir_node *old_proj, ir_node *nw)
+{
+ assert(is_Proj(old_proj));
+ ir_node *old = skip_Proj(old_proj);
+ assert(be_has_only_one_user(old));
+ be_peephole_before_exchange(old, nw);
+ sched_remove(old);
+ exchange(old_proj, nw);
+ be_liveness_introduce(lv, nw);
+}
+
void be_peephole_exchange(ir_node *old, ir_node *nw)
{
be_peephole_before_exchange(old, nw);
diff --git a/ir/be/bepeephole.h b/ir/be/bepeephole.h
index a043f57..836eed0 100644
--- a/ir/be/bepeephole.h
+++ b/ir/be/bepeephole.h
@@ -39,6 +39,13 @@ typedef void (*peephole_opt_func) (ir_node *node);
void be_peephole_exchange(ir_node *old, ir_node *nw);
/**
+ * Same as be_peephole_exchange(), but this function should be used for exchanging a Proj node with a new node, as it
+ * updates the internal state correctly for this case.
+ * This function removes the proj operand of old_proj from the schedule.
+ */
+void be_peephole_exchange_using_proj(ir_node *old_proj, ir_node *nw);
+
+/**
* Same as be_peephole_exchange(), but also replace @p old in the schedule
* by @p nw.
*/