virtual bool operator()( Inst *inst ) { if ( inst->out_reg or not inst->need_a_register() ) return true; // make a new reg CppOutReg *out_reg = cc->new_out_reg( inst->type() ); // assign out_reg + constraint propagation () Vec<InstAndPort> assigned_ports; if ( not assign_port_rec( assigned_ports, inst, -1, out_reg ) ) { std::cerr << "base constraint cannot be fullfilled !\n"; return false; } // edges and optionnal constraints int num_edge = 0; // , num_optionnal_constraint = 0; while ( true ) { // there's an edge for propagation ? if ( num_edge < assigned_ports.size() ) { InstAndPort port = assigned_ports[ num_edge++ ]; if ( port.is_an_output() ) { // sort parents by apparition order struct SortBySchedNum { bool operator()( const Inst::Parent &a, const Inst::Parent &b ) const { return a.inst->sched_num < b.inst->sched_num; } }; port.inst->update_sched_num(); std::sort( port.inst->par.begin(), port.inst->par.end(), SortBySchedNum() ); // try to propagate the reg through each output edge CppOutReg *reg = port.inst->out_reg; for( Inst::Parent &p : port.inst->par ) { // std::cout << " " << *port.inst << " -> " << *p.inst << std::endl; for( Inst *inst = port.inst; ; inst = inst->next_sched ) { // target is reached ? if ( inst == p.inst ) { // assign input port, or insert a copy instruction if ( not assign_port_rec( assigned_ports, p.inst, p.ninp, reg ) ) insert_copy_inst_before( assigned_ports, inst, p ); break; } // if there a conflict if ( not inst->used_reg_ok_for( reg, port.inst ) ) { // add a copy inst insert_copy_inst_before( assigned_ports, inst, p ); break; } // -> say that here, reg should be the output of port.inst (and nothing else) inst->add_used_reg( reg, port.inst ); } } } else { CppOutReg *reg = port.inst->inp_reg[ port.ninp() ]; if ( Inst *dst = port.inst->inp[ port.ninp() ].inst ) { // std::cout << " " << *port.inst << " <- " << *dst << " " << reg << std::endl; for( Inst *inst = port.inst->prev_sched; ; inst = inst->prev_sched ) { if ( not inst ) { PRINT( *port.inst ); PRINT( *dst ); ERROR( "..." ); } // target is reached ? if ( inst == dst ) { Inst *beg_reg = dst; // assign output port, or insert a copy instruction if ( not assign_port_rec( assigned_ports, dst, -1, reg ) ) { insert_copy_inst_after( assigned_ports, dst, port ); beg_reg = dst->next_sched; // reg will be used starting from the copy inst } // -> register the use of reg as output of beg_reg for( Inst *d = beg_reg; d != port.inst; d = d->next_sched ) inst->add_used_reg( reg, beg_reg ); break; } // if there is a conflict if ( not inst->used_reg_ok_for( reg, dst ) ) { // add a copy inst insert_copy_inst_after( assigned_ports, inst, port ); // -> register the use of reg as output of beg_reg for( Inst *c = inst->next_sched, *d = c; d != port.inst; d = d->next_sched ) inst->add_used_reg( reg, c ); break; } } } } continue; } // constraint that would be good to fullfill // if ( num_optionnal_constraint < assigned_ports.size() ) { // InstAndPort port = assigned_ports[ num_optionnal_constraint++ ]; // for( std::pair<const Inst::PortConstraint,int> &c : port.inst->same_out ) // if ( c.second != Inst::COMPULSORY and c.first.src_ninp == port.ninp_constraint() ) // assign_port_rec( assigned_ports, c.first.dst_inst, c.first.dst_ninp, out_reg ); // continue; // } // nothing to propagate break; } return true; }