Example #1
0
        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;
        }