+ DBG((mod, LEVEL_1, "perm move %+F irg %+F\n", perm, irg));
+
+ /* get some proj and find out the register class of the proj. */
+ foreach_out_edge (perm, edge) {
+ last_proj = get_edge_src_irn(edge);
+ cls = arch_get_irn_reg_class(aenv, last_proj, -1);
+ assert(is_Proj(last_proj));
+ break;
+ }
+
+ /* find the point in the schedule after which the
+ * potentially movable nodes must be defined.
+ * A perm will only be pushed up to first instruction
+ * which lets an operand of itself die. */
+
+ sched_foreach_reverse_from (sched_prev(perm), irn) {
+ for(i = get_irn_arity(irn) - 1; i >= 0; --i) {
+ ir_node *op = get_irn_n(irn, i);
+ if(arch_irn_consider_in_reg_alloc(aenv, cls, op)
+ && !values_interfere(env->birg, op, last_proj)) {
+ frontier = sched_next(irn);
+ goto found_front;
+ }
+ }
+ }
+found_front:
+
+ DBG((mod, LEVEL_2, "\tfrontier: %+F\n", frontier));
+
+ node = sched_prev(perm);
+ n_moved = 0;
+ while(!sched_is_begin(node)) {
+ const arch_register_req_t *req;
+ int input = -1;
+ ir_node *proj;
+
+ foreach_out_edge(perm, edge) {
+ ir_node *out = get_edge_src_irn(edge);
+ int pn = get_Proj_proj(out);
+ ir_node *in = get_irn_n(perm, pn);
+ if(node == in) {
+ proj = out;
+ input = pn;
+ break;
+ }
+ }
+ /* it wasn't an input to the perm, we can't do anything more */
+ if(input < 0)
+ break;
+ if(!sched_comes_after(frontier, node))
+ break;
+ if(arch_irn_is(aenv, node, modify_flags))
+ break;
+ if(is_Proj(node)) {
+ req = arch_get_register_req(aenv, get_Proj_pred(node),
+ -1 - get_Proj_proj(node));
+ } else {
+ req = arch_get_register_req(aenv, node, -1);