summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJonas Haag <jonas@lophus.org>2016-01-31 23:20:47 +0100
committerPhilipp Serrer <philipp@serrer.de>2018-01-18 18:10:14 +0100
commit6440d4c85e0782efc11385269b514d6ef50e59ff (patch)
tree5958cbfd46f315a938bf58a41ba8b9529c36b796
parent7db3eb44d75e6a9a00df9102225b4c8ca2ecaeb8 (diff)
Factor ia32 spill marks into generic backend code
-rw-r--r--ir/be/be_t.h1
-rw-r--r--ir/be/be_types.h4
-rw-r--r--ir/be/begnuas.c29
-rw-r--r--ir/be/bemain.c7
-rw-r--r--ir/be/bespillutil.c6
-rw-r--r--ir/be/ia32/ia32_bearch.c20
-rw-r--r--ir/be/ia32/ia32_emitter.c17
-rw-r--r--ir/be/ia32/ia32_new_nodes.c37
-rw-r--r--ir/be/ia32/ia32_optimize.c28
9 files changed, 57 insertions, 92 deletions
diff --git a/ir/be/be_t.h b/ir/be/be_t.h
index d3c87c8..e8dc5d8 100644
--- a/ir/be/be_t.h
+++ b/ir/be/be_t.h
@@ -42,6 +42,7 @@ struct be_options_t {
bool do_verify; /**< backend verify option */
char ilp_solver[128]; /**< the ilp solver name */
bool verbose_asm; /**< dump verbose assembler */
+ bool mark_spill_reload; /**< mark spills and reloads */
};
extern be_options_t be_options;
diff --git a/ir/be/be_types.h b/ir/be/be_types.h
index ec4440b..494c771 100644
--- a/ir/be/be_types.h
+++ b/ir/be/be_types.h
@@ -41,7 +41,9 @@ typedef enum arch_irn_flags_t {
arch_irn_flag_spill = 1U << 6,
/** node performs a reload like operation */
arch_irn_flag_reload = 1U << 7,
- arch_irn_flag_backend = 1U << 8, /**< begin of custom backend
+ /** node is rematerialized */
+ arch_irn_flag_rematerialized = 1U << 8,
+ arch_irn_flag_backend = 1U << 9, /**< begin of custom backend
flags */
} arch_irn_flags_t;
ENUM_BITSET(arch_irn_flags_t)
diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c
index 4c671d2..ef66af7 100644
--- a/ir/be/begnuas.c
+++ b/ir/be/begnuas.c
@@ -1649,18 +1649,37 @@ void be_gas_end_compilation_unit(const be_main_env_t *env)
be_dwarf_close();
}
+static const char* get_spillmark(const ir_node* const node)
+{
+ const char *spillmark = "";
+ if (be_options.mark_spill_reload) {
+ spillmark = " ";
+ if (!is_Proj(node)) {
+ if (arch_irn_is(node, spill)) {
+ spillmark = " (spill) ";
+ } else if (arch_irn_is(node, reload)) {
+ spillmark = " (reload)";
+ } else if (arch_irn_is(node, rematerialized)) {
+ spillmark = " (remat) ";
+ }
+ }
+ }
+ return spillmark;
+}
+
void be_emit_finish_line_gas(const ir_node *node)
{
if (node && be_options.verbose_asm) {
be_emit_pad_comment();
dbg_info *const dbg = get_irn_dbg_info(node);
src_loc_t const loc = ir_retrieve_dbg_info(dbg);
+ const char* const spillmark = get_spillmark(node);
char const *const fmt =
- !loc.file ? "/* %+F */\n" :
- loc.line == 0 ? "/* %+F %s */\n" :
- loc.column == 0 ? "/* %+F %s:%u */\n" :
- /* */ "/* %+F %s:%u:%u */\n";
- be_emit_irprintf(fmt, node, loc.file, loc.line, loc.column);
+ !loc.file ? "/*%s %+F */\n" :
+ loc.line == 0 ? "/*%s %+F %s */\n" :
+ loc.column == 0 ? "/*%s %+F %s:%u */\n" :
+ /* */ "/*%s %+F %s:%u:%u */\n";
+ be_emit_irprintf(fmt, spillmark, node, loc.file, loc.line, loc.column);
} else {
be_emit_char('\n');
}
diff --git a/ir/be/bemain.c b/ir/be/bemain.c
index 81aa566..3e05f99 100644
--- a/ir/be/bemain.c
+++ b/ir/be/bemain.c
@@ -89,9 +89,10 @@ static const lc_opt_table_entry_t be_main_options[] = {
LC_OPT_ENT_BOOL ("exceptions", "enable exception handling", &be_options.exceptions),
LC_OPT_ENT_BOOL ("verify", "verify the backend irg", &be_options.do_verify),
LC_OPT_ENT_BOOL ("time", "get backend timing statistics", &be_options.timing),
- LC_OPT_ENT_BOOL ("profilegenerate", "instrument the code for execution count profiling", &be_options.opt_profile_generate),
- LC_OPT_ENT_BOOL ("profileuse", "use existing profile data", &be_options.opt_profile_use),
- LC_OPT_ENT_BOOL ("verboseasm", "enable verbose assembler output", &be_options.verbose_asm),
+ LC_OPT_ENT_BOOL ("profilegenerate", "instrument the code for execution count profiling", &be_options.opt_profile_generate),
+ LC_OPT_ENT_BOOL ("profileuse", "use existing profile data", &be_options.opt_profile_use),
+ LC_OPT_ENT_BOOL ("verboseasm", "enable verbose assembler output", &be_options.verbose_asm),
+ LC_OPT_ENT_BOOL ("mark_spill_reload", "mark spills and reloads", &be_options.mark_spill_reload),
LC_OPT_ENT_STR("ilp.solver", "the ilp solver name", &be_options.ilp_solver),
LC_OPT_LAST
diff --git a/ir/be/bespillutil.c b/ir/be/bespillutil.c
index 832a666..5a1a221 100644
--- a/ir/be/bespillutil.c
+++ b/ir/be/bespillutil.c
@@ -423,14 +423,14 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
/* create a copy of the node */
ir_node *const bl = get_nodes_block(reloader);
ir_node *const res = new_similar_node(spilled, bl, ins);
- if (env->regif.mark_remat)
- env->regif.mark_remat(res);
DBG((dbg, LEVEL_1, "Insert remat %+F of %+F before reloader %+F\n", res,
spilled, reloader));
- if (!is_Proj(res))
+ if (!is_Proj(res)) {
+ arch_add_irn_flags(res, arch_irn_flag_rematerialized);
sched_add_before(reloader, res);
+ }
return res;
}
diff --git a/ir/be/ia32/ia32_bearch.c b/ir/be/ia32/ia32_bearch.c
index da91a6e..012e05b 100644
--- a/ir/be/ia32/ia32_bearch.c
+++ b/ir/be/ia32/ia32_bearch.c
@@ -358,7 +358,6 @@ static void ia32_perform_memory_operand(ir_node *irn, unsigned int i)
set_irn_n(irn, n_ia32_mem, spill);
set_irn_n(irn, i, ia32_get_admissible_noreg(irn, i));
attr->addr.variant = X86_ADDR_BASE;
- set_ia32_is_reload(irn);
/* kill the reload */
assert(get_irn_n_edges(op) == 0);
@@ -397,8 +396,6 @@ static ir_node *ia32_turn_back_dest_am(ir_node *node)
ir_node *const mem = get_irn_n(node, n_ia32_mem);
ir_node *const load = new_bd_ia32_Load(dbgi, block, base, idx, mem, size, false);
ia32_copy_am_attrs(load, node);
- if (is_ia32_is_reload(node))
- set_ia32_is_reload(load);
sched_add_before(node, load);
ir_node *const load_res = be_new_Proj(load, pn_ia32_Load_res);
ir_node *const load_mem = be_new_Proj(load, pn_ia32_Load_M);
@@ -442,8 +439,6 @@ ir_node *ia32_turn_back_am(ir_node *node)
ir_node *load_res = be_new_Proj(load, pn_ia32_Load_res);
ia32_copy_am_attrs(load, node);
- if (is_ia32_is_reload(node))
- set_ia32_is_reload(load);
set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
switch (get_ia32_am_support(node)) {
@@ -674,7 +669,7 @@ static ir_node *ia32_new_spill(ir_node *value, ir_node *after)
attr->addr.variant = X86_ADDR_BASE;
set_ia32_op_type(store, ia32_AddrModeD);
set_ia32_frame_use(store, IA32_FRAME_USE_AUTO);
- set_ia32_is_spill(store);
+ arch_add_irn_flags(store, arch_irn_flag_spill);
sched_add_after(after, store);
return res;
@@ -713,7 +708,6 @@ static ir_node *ia32_new_reload(ir_node *value, ir_node *spill, ir_node *before)
attr->addr.variant = X86_ADDR_BASE;
set_ia32_op_type(load, ia32_AddrModeS);
set_ia32_frame_use(load, IA32_FRAME_USE_AUTO);
- set_ia32_is_reload(load);
arch_add_irn_flags(load, arch_irn_flag_reload);
sched_add_before(before, load);
@@ -742,7 +736,7 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
};
set_ia32_frame_use(push, IA32_FRAME_USE_AUTO);
set_ia32_op_type(push, ia32_AddrModeS);
- set_ia32_is_spill(push);
+ arch_add_irn_flags(push, arch_irn_flag_spill);
sched_add_before(schedpoint, push);
return push;
@@ -768,7 +762,7 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp,
};
set_ia32_frame_use(pop, IA32_FRAME_USE_AUTO);
set_ia32_op_type(pop, ia32_AddrModeD);
- set_ia32_is_reload(pop);
+ arch_add_irn_flags(pop, arch_irn_flag_reload);
sched_add_before(schedpoint, pop);
return pop;
}
@@ -1017,6 +1011,7 @@ static void introduce_prologue(ir_graph *const irg, bool omit_fp)
ir_node *const noreg = ia32_new_NoReg_gp(irg);
ir_node *const initial_bp = be_get_Start_proj(irg, bp);
ir_node *const push = new_bd_ia32_Push(NULL, block, noreg, noreg, mem, initial_bp, initial_sp, X86_SIZE_32);
+ arch_add_irn_flags(push, arch_irn_flag_spill);
sched_add_after(start, push);
ir_node *const curr_mem = be_new_Proj(push, pn_ia32_Push_M);
edges_reroute_except(mem, curr_mem, push);
@@ -1388,16 +1383,9 @@ static void ia32_finish(void)
obstack_free(&opcodes_obst, NULL);
}
-static void ia32_mark_remat(ir_node *node)
-{
- if (is_ia32_irn(node))
- set_ia32_is_remat(node);
-}
-
static const regalloc_if_t ia32_regalloc_if = {
.spill_cost = 7,
.reload_cost = 5,
- .mark_remat = ia32_mark_remat,
.new_spill = ia32_new_spill,
.new_reload = ia32_new_reload,
.perform_memory_operand = ia32_perform_memory_operand,
diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c
index a7052c2..52d7ba5 100644
--- a/ir/be/ia32/ia32_emitter.c
+++ b/ir/be/ia32/ia32_emitter.c
@@ -59,7 +59,6 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static char pic_base_label[128];
static ir_label_t exc_label_id;
-static bool mark_spill_reload;
static bool omit_fp;
static int frame_type_size;
@@ -1248,18 +1247,9 @@ static void ia32_emit_node(ir_node *node)
{
DBG((dbg, LEVEL_1, "emitting code for %+F\n", node));
- if (is_ia32_irn(node)) {
- /* emit the exception label of this instruction */
- if (get_ia32_exc_label(node))
- ia32_assign_exc_label(node);
- if (mark_spill_reload) {
- if (is_ia32_is_spill(node))
- ia32_emitf(NULL, "xchg %ebx, %ebx /* spill mark */");
- if (is_ia32_is_reload(node))
- ia32_emitf(NULL, "xchg %edx, %edx /* reload mark */");
- if (is_ia32_is_remat(node))
- ia32_emitf(NULL, "xchg %ecx, %ecx /* remat mark */");
- }
+ /* emit the exception label of this instruction */
+ if (is_ia32_irn(node) && get_ia32_exc_label(node)) {
+ ia32_assign_exc_label(node);
}
be_emit_node(node);
@@ -1486,7 +1476,6 @@ static lc_opt_enum_int_var_t get_ip_style_var = {
};
static const lc_opt_table_entry_t ia32_emitter_options[] = {
- LC_OPT_ENT_BOOL ("mark_spill_reload", "mark spills and reloads with ud opcodes", &mark_spill_reload),
LC_OPT_ENT_ENUM_INT("get_ip", "method to get IP for the pic base", &get_ip_style_var),
LC_OPT_LAST
};
diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c
index 559d251..c8de886 100644
--- a/ir/be/ia32/ia32_new_nodes.c
+++ b/ir/be/ia32/ia32_new_nodes.c
@@ -232,7 +232,6 @@ void ia32_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
fprintf(F, "sign_extend = %s\n", be_dump_yesno(attr->sign_extend));
fprintf(F, "use_8bit_high = %s\n",
be_dump_yesno(attr->use_8bit_high));
- fprintf(F, "is reload = %s\n", be_dump_yesno(is_ia32_is_reload(n)));
fprintf(F, "latency = %u\n", get_ia32_latency(n));
/* dump modes */
@@ -410,42 +409,6 @@ int is_ia32_commutative(const ir_node *node)
return attr->is_commutative;
}
-void set_ia32_is_reload(ir_node *node)
-{
- ia32_attr_t *attr = get_ia32_attr(node);
- attr->is_reload = 1;
-}
-
-int is_ia32_is_reload(const ir_node *node)
-{
- const ia32_attr_t *attr = get_ia32_attr_const(node);
- return attr->is_reload;
-}
-
-void set_ia32_is_spill(ir_node *node)
-{
- ia32_attr_t *attr = get_ia32_attr(node);
- attr->is_spill = 1;
-}
-
-int is_ia32_is_spill(const ir_node *node)
-{
- const ia32_attr_t *attr = get_ia32_attr_const(node);
- return attr->is_spill;
-}
-
-void set_ia32_is_remat(ir_node *node)
-{
- ia32_attr_t *attr = get_ia32_attr(node);
- attr->is_remat = 1;
-}
-
-int is_ia32_is_remat(const ir_node *node)
-{
- const ia32_attr_t *attr = get_ia32_attr_const(node);
- return attr->is_remat;
-}
-
unsigned get_ia32_latency(const ir_node *node)
{
assert(is_ia32_irn(node));
diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c
index 5e913e0..e83a27d 100644
--- a/ir/be/ia32/ia32_optimize.c
+++ b/ir/be/ia32/ia32_optimize.c
@@ -36,6 +36,10 @@
#include "tv.h"
#include "util.h"
+static const arch_irn_flags_t spill_flags = arch_irn_flag_spill
+ | arch_irn_flag_reload
+ | arch_irn_flag_rematerialized;
+
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static bool is_hl_register(arch_register_t const *const reg)
@@ -47,19 +51,16 @@ static bool is_hl_register(arch_register_t const *const reg)
reg == &ia32_registers[REG_EDX];
}
-static void copy_mark(const ir_node *old, ir_node *newn)
+static void copy_spillflags(const ir_node *old, ir_node *const newn)
{
- if (is_ia32_is_reload(old))
- set_ia32_is_reload(newn);
- if (is_ia32_is_spill(old))
- set_ia32_is_spill(newn);
- if (is_ia32_is_remat(old))
- set_ia32_is_remat(newn);
+ /* Copy old spill flags */
+ const arch_irn_flags_t old_flags = arch_get_irn_flags(old) & spill_flags;
+ arch_add_irn_flags(newn, old_flags);
}
static void replace(ir_node *const old, ir_node *const newn)
{
- copy_mark(old, newn);
+ copy_spillflags(old, newn);
be_peephole_replace(old, newn);
}
@@ -614,7 +615,8 @@ static void peephole_IncSP_Store_to_push(ir_node *irn)
ir_node *const mem = get_irn_n(store, n_ia32_mem);
ir_node *const val = get_irn_n(store, n_ia32_unary_op);
ir_node *const push = new_bd_ia32_Push(dbgi, block, noreg, noreg, mem, val, curr_sp, X86_SIZE_32);
- copy_mark(store, push);
+
+ copy_spillflags(store, push);
if (first_push == NULL)
first_push = push;
@@ -761,11 +763,11 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn)
ir_node *pop = new_bd_ia32_Pop(get_irn_dbg_info(load), block, mem, pred_sp, size);
arch_set_irn_register_out(pop, pn_ia32_Load_res, reg);
- copy_mark(load, pop);
-
/* create stackpointer Proj */
pred_sp = be_new_Proj_reg(pop, pn_ia32_Pop_stack, &ia32_registers[REG_ESP]);
+ copy_spillflags(load, pop);
+
sched_add_before(irn, pop);
be_peephole_exchange(load, pop);
}
@@ -1057,7 +1059,7 @@ static void peephole_ia32_Conv_I2I(ir_node *node)
ir_node *block = get_nodes_block(node);
ir_node *cwtl = new_bd_ia32_Cwtl(dbgi, block, val);
arch_set_irn_register(cwtl, eax);
- be_peephole_replace(node, cwtl);
+ replace(node, cwtl);
}
/* Replace rolw $8, %[abcd]x by shorter xchgb %[abcd]l, %[abcd]h */
@@ -1073,7 +1075,7 @@ static void peephole_ia32_Rol(ir_node *node)
ir_node *const val = get_irn_n(node, n_ia32_Rol_val);
ir_node *const xchg = new_bd_ia32_Bswap16(dbgi, block, val);
arch_set_irn_register_out(xchg, pn_ia32_Bswap16_res, reg);
- be_peephole_replace(node, xchg);
+ replace(node, xchg);
}
}
}