+#include "belive_t.h"
+#include "beinsn_t.h"
+#include "besched_t.h"
+#include "benodesets.h"
+#include "bejavacoal.h"
+#include "bestatevent.h"
+#include "beirg_t.h"
+#include "error.h"
+
+#include <libcore/lc_timing.h>
+#include <libcore/lc_opts.h>
+#include <libcore/lc_opts_enum.h>
+
+#define DUMP_BEFORE 1
+#define DUMP_AFTER 2
+#define DUMP_APPEL 4
+#define DUMP_ALL 2 * DUMP_APPEL - 1
+
+#define COST_FUNC_FREQ 1
+#define COST_FUNC_LOOP 2
+#define COST_FUNC_ALL_ONE 3
+
+static unsigned dump_flags = 0;
+static unsigned style_flags = 0;
+static unsigned do_stats = 0;
+static cost_fct_t cost_func = co_get_costs_exec_freq;
+static unsigned algo = CO_ALGO_HEUR4;
+static int improve = 1;
+
+static const lc_opt_enum_mask_items_t dump_items[] = {
+ { "before", DUMP_BEFORE },
+ { "after", DUMP_AFTER },
+ { "appel", DUMP_APPEL },
+ { "all", DUMP_ALL },
+ { NULL, 0 }
+};
+
+static const lc_opt_enum_mask_items_t style_items[] = {
+ { "color", CO_IFG_DUMP_COLORS },
+ { "labels", CO_IFG_DUMP_LABELS },
+ { "constr", CO_IFG_DUMP_CONSTR },
+ { "shape", CO_IFG_DUMP_SHAPE },
+ { "full", 2 * CO_IFG_DUMP_SHAPE - 1 },
+ { NULL, 0 }
+};
+
+static const lc_opt_enum_mask_items_t algo_items[] = {
+ { "none", CO_ALGO_NONE },
+ { "heur", CO_ALGO_HEUR },
+ { "heur2", CO_ALGO_HEUR2 },
+#ifdef WITH_JVM
+ { "heur3", CO_ALGO_HEUR3 },
+#endif /* WITH_JVM */
+ { "heur4", CO_ALGO_HEUR4 },
+#ifdef WITH_ILP
+ { "ilp", CO_ALGO_ILP },
+#endif /* WITH_ILP */
+ { NULL, 0 }
+};
+
+typedef int (*opt_funcptr)(void);
+
+static const lc_opt_enum_func_ptr_items_t cost_func_items[] = {
+ { "freq", (opt_funcptr) co_get_costs_exec_freq },
+ { "loop", (opt_funcptr) co_get_costs_loop_depth },
+ { "one", (opt_funcptr) co_get_costs_all_one },
+ { NULL, NULL }
+};
+
+static lc_opt_enum_mask_var_t dump_var = {
+ &dump_flags, dump_items
+};
+
+static lc_opt_enum_mask_var_t style_var = {
+ &style_flags, style_items
+};
+
+static lc_opt_enum_mask_var_t algo_var = {
+ &algo, algo_items
+};
+
+static lc_opt_enum_func_ptr_var_t cost_func_var = {
+ (opt_funcptr*) &cost_func, cost_func_items
+};
+
+static const lc_opt_table_entry_t options[] = {
+ LC_OPT_ENT_ENUM_INT ("algo", "select copy optimization algo", &algo_var),
+ LC_OPT_ENT_ENUM_FUNC_PTR ("cost", "select a cost function", &cost_func_var),
+ LC_OPT_ENT_ENUM_MASK ("dump", "dump ifg before or after copy optimization", &dump_var),
+ LC_OPT_ENT_ENUM_MASK ("style", "dump style for ifg dumping", &style_var),
+ LC_OPT_ENT_BOOL ("stats", "dump statistics after each optimization", &do_stats),
+ LC_OPT_ENT_BOOL ("improve", "run heur3 before if algo can exploit start solutions", &improve),
+ { NULL }
+};
+
+/* Insert additional options registration functions here. */
+extern void be_co_ilp_register_options(lc_opt_entry_t *grp);
+extern void be_co2_register_options(lc_opt_entry_t *grp);
+extern void be_co3_register_options(lc_opt_entry_t *grp);
+
+void be_init_copycoal(void)
+{
+ lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
+ lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
+ lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
+ lc_opt_entry_t *co_grp = lc_opt_get_grp(chordal_grp, "co");
+
+ lc_opt_add_table(co_grp, options);
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copycoal);
+
+#undef QUICK_AND_DIRTY_HACK
+
+static int nodes_interfere(const be_chordal_env_t *env, const ir_node *a, const ir_node *b)
+{
+ if (env->ifg)
+ return be_ifg_connected(env->ifg, a, b);
+ else
+ return values_interfere(env->birg, a, b);
+}
+
+
+/******************************************************************************
+ _____ _
+ / ____| | |
+ | | __ ___ _ __ ___ _ __ __ _| |
+ | | |_ |/ _ \ '_ \ / _ \ '__/ _` | |
+ | |__| | __/ | | | __/ | | (_| | |
+ \_____|\___|_| |_|\___|_| \__,_|_|
+
+ ******************************************************************************/
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+
+copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, cost_fct_t get_costs)
+{
+ const char *s1, *s2, *s3;
+ int len;
+ copy_opt_t *co;
+
+ FIRM_DBG_REGISTER(dbg, "ir.be.copyopt");
+
+ co = xcalloc(1, sizeof(*co));
+ co->cenv = chordal_env;
+ co->aenv = chordal_env->birg->main_env->arch_env;
+ co->irg = chordal_env->irg;
+ co->cls = chordal_env->cls;
+ co->get_costs = get_costs;
+
+ s1 = get_irp_prog_name();
+ s2 = get_entity_name(get_irg_entity(co->irg));
+ s3 = chordal_env->cls->name;
+ len = strlen(s1) + strlen(s2) + strlen(s3) + 5;
+ co->name = xmalloc(len);
+ snprintf(co->name, len, "%s__%s__%s", s1, s2, s3);
+
+ return co;
+}
+
+void free_copy_opt(copy_opt_t *co) {
+ xfree(co->name);
+ free(co);
+}
+
+int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) {
+ const arch_register_req_t *req;
+ const arch_register_t *reg;
+
+ if (arch_irn_is(co->aenv, irn, ignore))
+ return 0;
+
+ reg = arch_get_irn_register(co->aenv, irn);
+ if (arch_register_type_is(reg, ignore))
+ return 0;
+
+ req = arch_get_register_req(co->aenv, irn, -1);
+ if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(req))
+ return 1;
+
+ return 0;
+}
+
+int co_get_costs_loop_depth(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos) {
+ int cost = 0;
+ ir_loop *loop;
+ ir_node *root_block = get_nodes_block(root);
+
+ if (is_Phi(root)) {
+ /* for phis the copies are placed in the corresponding pred-block */
+ loop = get_irn_loop(get_Block_cfgpred_block(root_block, pos));
+ } else {
+ /* a perm places the copy in the same block as it resides */
+ loop = get_irn_loop(root_block);
+ }
+ if (loop) {
+ int d = get_loop_depth(loop);
+ cost = d*d;
+ }
+ return 1+cost;
+}