return res;
}
-static be_insn_t *chordal_scan_insn(be_chordal_alloc_env_t *env, ir_node *irn)
+static be_insn_t *chordal_scan_insn(be_chordal_env_t *env, ir_node *irn)
{
be_insn_env_t ie;
- ie.ignore_colors = env->chordal_env->ignore_colors;
- ie.aenv = env->chordal_env->birg->main_env->arch_env;
- ie.obst = &env->chordal_env->obst;
- ie.cls = env->chordal_env->cls;
+ ie.ignore_colors = env->ignore_colors;
+ ie.aenv = env->birg->main_env->arch_env;
+ ie.obst = &env->obst;
+ ie.cls = env->cls;
return be_scan_insn(&ie, irn);
}
+static ir_node *prepare_constr_insn(be_chordal_env_t *env, ir_node *irn)
+{
+ be_insn_t *insn = chordal_scan_insn(env, irn);
+ int n_uses = be_insn_n_uses(insn);
+ int n_defs = be_insn_n_defs(insn);
+ int i;
+
+ if(!insn->has_constraints)
+ goto end;
+
+ for(i = insn->use_start; i < insn->n_ops; ++i) {
+ be_operand_t *op = &insn->ops[i];
+ if(op->has_constraints && values_interfere(env->lv, insn->irn, op->carrier)) {
+ ir_node *bl = get_nodes_block(insn->irn);
+ ir_node *copy = be_new_Copy(env->cls, env->irg, bl, op->carrier);
+
+ sched_add_before(insn->irn, copy);
+ set_irn_n(insn->irn, op->pos, copy);
+ DBG((env->dbg, LEVEL_3, "inserting constr copy %+F for %+F pos %d\n", copy, insn->irn, op->pos));
+ be_liveness_update(env->lv, op->carrier);
+ }
+ }
+
+end:
+ obstack_free(&env->obst, insn);
+ return insn->next_insn;
+}
+
+static void pre_spill_prepare_constr_walker(ir_node *bl, void *data)
+{
+ be_chordal_env_t *env = data;
+ ir_node *irn;
+ for(irn = sched_first(bl); !sched_is_end(irn);) {
+ irn = prepare_constr_insn(env, irn);
+ }
+}
+
+void be_pre_spill_prepare_constr(be_chordal_env_t *cenv) {
+ irg_block_walk_graph(cenv->irg, pre_spill_prepare_constr_walker, NULL, (void *) cenv);
+}
+
static void pair_up_operands(const be_chordal_alloc_env_t *alloc_env, be_insn_t *insn)
{
const be_chordal_env_t *env = alloc_env->chordal_env;
Now, figure out which input operand must be copied since it has input
constraints which are also output constraints.
*/
+#if 0
for(i = insn->use_start; i < insn->n_ops; ++i) {
be_operand_t *op = &insn->ops[i];
if(op->has_constraints && (values_interfere(env->lv, op->carrier, insn->irn) || arch_irn_is(aenv, op->carrier, ignore))) {
}
}
}
+#endif
/*
Make the Perm, recompute liveness and re-scan the insn since the
*/
// be_liveness_recompute(env->lv);
obstack_free(&env->obst, insn);
- *the_insn = insn = chordal_scan_insn(alloc_env, insn->irn);
+ *the_insn = insn = chordal_scan_insn(env, insn->irn);
/*
Copy the input constraints of the insn to the Perm as output
{
be_chordal_env_t *env = alloc_env->chordal_env;
void *base = obstack_base(&env->obst);
- be_insn_t *insn = chordal_scan_insn(alloc_env, irn);
+ be_insn_t *insn = chordal_scan_insn(env, irn);
ir_node *res = insn->next_insn;
int be_silent = *silent;
#include "irgraph_t.h"
#include "irprintf_t.h"
#include "irgwalk.h"
+#include "ircons.h"
#include "irdump.h"
#include "irdom.h"
#include "ircons.h"
BE_TIMER_PUSH(ra_timer.t_live);
be_liveness_recompute(chordal_env.lv);
BE_TIMER_POP(ra_timer.t_live);
-
dump(BE_CH_DUMP_LIVE, irg, chordal_env.cls, "-live", dump_ir_block_graph_sched);
+ be_pre_spill_prepare_constr(&chordal_env);
+ dump(BE_CH_DUMP_CONSTR, irg, chordal_env.cls, "-constr-pre", dump_ir_block_graph_sched);
+
BE_TIMER_PUSH(ra_timer.t_spill);
/* spilling */
);
dump(BE_CH_DUMP_SPILL, irg, chordal_env.cls, "-spill", dump_ir_block_graph_sched);
- be_abi_fix_stack_nodes(bi->abi, chordal_env.lv);
be_compute_spill_offsets(&chordal_env);
check_for_memory_operands(&chordal_env);
+ be_abi_fix_stack_nodes(bi->abi, chordal_env.lv);
BE_TIMER_PUSH(ra_timer.t_verify);
co_build_ou_structure(co);
co_build_graph_structure(co);
if(be_copymin_stats) {
- ir_printf("%40F %20s\n", current_ir_graph, chordal_env.cls->name);
- printf("max copy costs: %d\n", co_get_max_copy_costs(co));
- printf("init copy costs: %d\n", co_get_copy_costs(co));
- printf("inevit copy costs: %d\n", co_get_inevit_copy_costs(co));
- printf("copy costs lower bound: %d\n", co_get_lower_bound(co));
+ ir_printf("%30F %10s %7d%7d%7d%7d", current_ir_graph, chordal_env.cls->name,
+ co_get_max_copy_costs(co), co_get_copy_costs(co), co_get_inevit_copy_costs(co), co_get_lower_bound(co));
}
/* Dump the interference graph in Appel's format. */
if (co) {
if(be_copymin_stats) {
- printf("final copy costs : %d\n", co_get_copy_costs(co));
+ int optimizable_costs = co_get_max_copy_costs(co) - co_get_lower_bound(co);
+ int remaining = co_get_copy_costs(co);
+ int evitable = remaining - co_get_lower_bound(co);
+
+ if(optimizable_costs > 0)
+ printf("%5d %5.2f\n", remaining, (evitable * 100.0) / optimizable_costs);
+ else
+ printf("%5d %5s\n", remaining, "-");
}
co_free_graph_structure(co);
co_free_ou_structure(co);
*/
FILE *be_chordal_open(const be_chordal_env_t *env, const char *prefix, const char *suffix);
+void be_pre_spill_prepare_constr(be_chordal_env_t *cenv);
+
#endif /* _BECHORDAL_T_H */
int *inv_node_map;
java_coal_t *coal;
- ir_node *irn;
ir_node *n, *m;
int max_idx = 0;
}
}
+ if(dump_flags & DUMP_BEFORE) {
+ char fn[512];
+ ir_snprintf(fn, sizeof(fn), "%F-%s-before.dot", co->cenv->irg, co->cenv->cls->name);
+ java_coal_dump(coal, fn);
+ }
+
java_coal_coalesce(coal);
be_ifg_foreach_node(ifg, nodes_it, n) {
}
}
+ if(dump_flags & DUMP_AFTER) {
+ char fn[512];
+ ir_snprintf(fn, sizeof(fn), "%F-%s-after.dot", co->cenv->irg, co->cenv->cls->name);
+ java_coal_dump(coal, fn);
+ }
+
java_coal_destroy(coal);
bitset_free(nodes);
}
#include "phiclass.h"
#include "irbitset.h"
#include "irphase_t.h"
+#include "irprintf_t.h"
+
#include "bearch.h"
#include "benode_t.h"
obstack_free(&env.obst, NULL);
}
+/*
+___ _____ ____ ____ ___ _____ ____ _
+|_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
+| || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
+| || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
+|___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
+|_| |___/
+*/
+
+static const char *get_dot_color_name(int col)
+{
+ static const char *names[] = {
+ "blue",
+ "red",
+ "green",
+ "yellow",
+ "cyan",
+ "magenta",
+ "orange",
+ "chocolate",
+ "beige",
+ "navy",
+ "darkgreen",
+ "darkred",
+ "lightPink",
+ "chartreuse",
+ "lightskyblue",
+ "linen",
+ "pink",
+ "lightslateblue",
+ "mintcream",
+ "red",
+ "darkolivegreen",
+ "mediumblue",
+ "mistyrose",
+ "salmon",
+ "darkseagreen",
+ "mediumslateblue"
+ "moccasin",
+ "tomato",
+ "forestgreen",
+ "darkturquoise",
+ "palevioletred"
+ };
+
+ return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
+}
+
+typedef struct _co_ifg_dump_t {
+ const copy_opt_t *co;
+ unsigned flags;
+} co_ifg_dump_t;
+
+static const char *get_dot_shape_name(co_ifg_dump_t *cod, ir_node *irn)
+{
+ arch_register_req_t req;
+
+ arch_get_register_req(cod->co->aenv, &req, irn, BE_OUT_POS(0));
+ if(arch_register_req_is(&req, limited))
+ return "diamond";
+
+ return "ellipse";
+}
+
+static void ifg_dump_graph_attr(FILE *f, void *self)
+{
+ fprintf(f, "overlay=false");
+}
+
+static int ifg_is_dump_node(void *self, ir_node *irn)
+{
+ co_ifg_dump_t *cod = self;
+ return !arch_irn_is(cod->co->aenv, irn, ignore);
+}
+
+static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
+{
+ co_ifg_dump_t *env = self;
+ const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
+
+ ir_fprintf(f, "label=\"%+F\" style=filled color=%s shape=%s", irn, get_dot_color_name(reg->index), get_dot_shape_name(env, irn));
+}
+
+static void ifg_dump_at_end(FILE *file, void *self)
+{
+ co_ifg_dump_t *env = self;
+ affinity_node_t *a;
+
+ co_gs_foreach_aff_node(env->co, a) {
+ const arch_register_t *ar = arch_get_irn_register(env->co->aenv, a->irn);
+ unsigned aidx = get_irn_idx(a->irn);
+ neighb_t *n;
+
+ co_gs_foreach_neighb(a, n) {
+ const arch_register_t *nr = arch_get_irn_register(env->co->aenv, n->irn);
+ int nidx = get_irn_idx(n->irn);
+
+ if(aidx < nidx) {
+ const char *color = nr == ar ? "blue" : "red";
+ fprintf(file, "\tn%d -- n%d [label=\"%d\" style=dashed color=%s];\n", aidx, nidx, n->costs, color);
+ }
+ }
+ }
+}
+
+
+static be_ifg_dump_dot_cb_t ifg_dot_cb = {
+ ifg_is_dump_node,
+ ifg_dump_graph_attr,
+ ifg_dump_node_attr,
+ NULL,
+ NULL,
+ ifg_dump_at_end
+};
+
+
+
+void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags)
+{
+ co_ifg_dump_t cod;
+
+ cod.co = co;
+ cod.flags = flags;
+ be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &cod);
+}
+
void co_solve_park_moon(copy_opt_t *opt)
{
*/
void co_dump_appel_graph_cliques(const copy_opt_t *co, FILE *f);
+enum {
+ CO_IFG_DUMP_COLORS = 1,
+ CO_IFG_DUMP_LABELS = 2
+};
+
+/**
+ * Dump the interference graph with the affinity edges and the coloring.
+ */
+void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags);
+
/**
* Constructs another internal representation of the affinity edges
*/
#endif
+#include <signal.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
static int jvm_inited = 0;
static jni_env_t env;
+void (*old_int_handler)(int);
+void (*old_abrt_handler)(int);
-static void jvm_destroy_at_exit(void)
+static void sig_jvm_destroy_at_exit(int signal)
{
if(jvm_inited)
stop_vm(&env);
+
+ switch(signal) {
+ case SIGABRT:
+ old_abrt_handler(signal);
+ break;
+ case SIGINT:
+ old_int_handler(signal);
+ break;
+ default:;
+ }
+}
+
+static void jvm_destroy_at_exit(void)
+{
+ sig_jvm_destroy_at_exit(0);
}
static jni_env_t *get_jvm(void)
args[0] = cp_param;
start_vm(&env, sizeof(args) / sizeof(args[0]), args);
jvm_inited = 1;
+ old_int_handler = signal(SIGINT, sig_jvm_destroy_at_exit);
+ old_abrt_handler = signal(SIGABRT, sig_jvm_destroy_at_exit);
atexit(jvm_destroy_at_exit);
}
*/
void be_liveness_introduce(be_lv_t *lv, ir_node *irn);
+/**
+ * Add all nodes which are missing in the current liveness data.
+ * The liveness data of the already existing nodes (in the liveness data) is not touched.
+ * @param The liveness info.
+ */
+void be_liveness_add_missing(be_lv_t *lv);
+
/**
* Dump the liveness information for a graph.
* @param f The output.