+void be_copy_opt_init(void) {
+}
+
+copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, int (*get_costs)(ir_node*, ir_node*, int)) {
+ const char *s1, *s2, *s3;
+ int len;
+ copy_opt_t *co;
+
+ dbg = firm_dbg_register("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);
+}
+
+int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) {
+ arch_register_req_t req;
+
+ if (arch_irn_is_ignore(co->aenv, irn))
+ return 0;
+
+ if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(co->aenv, irn, &req))
+ return 1;
+
+ return 0;
+}
+
+int co_is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
+ const ir_edge_t *edge;
+
+ if (arch_irn_is_ignore(co->aenv, irn))
+ return 0;
+
+ foreach_out_edge(irn, edge) {
+ ir_node *n = edge->src;
+
+ if (!nodes_interfere(co->cenv, irn, n) || irn == n) {
+ arch_register_req_t req;
+ arch_get_register_req(co->aenv, &req, n, -1);
+
+ if(is_Reg_Phi(n) ||
+ is_Perm(co->aenv, n) ||
+ (arch_register_req_is(&req, should_be_same) && req.other_same == irn)
+ )
+ return 1;
+ }
+ }
+
+ return 0;
+}