예제 #1
0
Inst *Codegen_C::scheduling( Vec<Expr> out ) {
    // update inst->when
    for( Expr inst : out )
        inst->update_when( BoolOpSeq( True() ) );

    // get the front
    ++Inst::cur_op_id;
    Vec<Expr> front;
    for( Expr inst : out )
        get_front( front, inst );
    ++Inst::cur_op_id;
    for( Expr inst : front )
        inst->op_id = Inst::cur_op_id;

    // go to the roots
    Inst *beg = 0, *end;
    ++Inst::cur_op_id;
    while ( front.size() ) {
        // try to find an instruction with the same condition set or an inst that is not going to write anything
        Inst *inst = 0;
        for( int i = 0; i < front.size(); ++i ) {
            if ( front[ i ]->when->always( false ) ) {
                front.remove_unordered( i-- );
                continue;
            }
            if ( front[ i ]->when->always( true ) ) {
                inst = front[ i ].inst;
                front.remove_unordered( i );
                break;
            }
        }

        // if not possible to do more without a condition
        if ( not inst ) {
            if ( not front.size() )
                break;

            // try to find the best condition to move forward
            std::map<BoolOpSeq,int> possible_conditions;
            for( int i = 0; i < front.size(); ++i ) {
                Vec<BoolOpSeq> pc = front[ i ]->when->common_terms();
                PRINT( *front[ i ]->when );
                PRINT( pc.size() );
                for( int c = 0; c < pc.size(); ++c )
                    std::cout << "    " << pc[ c ];
                std::cout << "\n";
                for( BoolOpSeq &item : pc )
                    ++possible_conditions[ item ];
            }
            int best_score = -1;
            BoolOpSeq best_item;
            for( const std::pair<BoolOpSeq,int> &p : possible_conditions ) {
                if ( best_score < p.second ) {
                    best_score = p.second;
                    best_item = p.first;
                }
            }

            // start the input list with the conditions
            std::map<Inst *,OutCondFront> outputs; // inst to replace -> replacement values + IfOut pos
            std::map<Expr,int> inputs;
            std::set<Expr> deps;
            inputs[ best_item.expr() ] = 0;

            // get a front of instructions that must be done under the condition `cond`
            Vec<Expr> ok_we_inp = extract_inst_that_must_be_done_if( outputs, inputs, deps, front, best_item    , 1 );
            Vec<Expr> ko_we_inp = extract_inst_that_must_be_done_if( outputs, inputs, deps, front, not best_item, 0 );

            //            for( std::pair<Expr,int> i : inputs )
            //                std::cout << "  inp=" << *i.first << " num=" << i.second << std::endl;
            //            for( std::pair<Inst *,OutCondFront> o : outputs )
            //                std::cout << "  to_be_repl=" << *o.first << "\n    ok=" << o.second.inp[ 1 ] << "\n    ko=" << o.second.inp[ 0 ] << "\n    num=" << o.second.num_in_outputs << std::endl;

            Expr if_inp_ok = make_if_inp( inputs, deps, ok_we_inp );
            Expr if_inp_ko = make_if_inp( inputs, deps, ko_we_inp );

            Expr if_out_ok = make_if_out( outputs, 1 );
            Expr if_out_ko = make_if_out( outputs, 0 );

            // complete the If instruction
            Vec<Expr> inp( Size(), inputs.size() );
            for( std::pair<Expr,int> i : inputs )
                inp[ i.second ] = i.first;
            Expr if_expr = if_inst( inp, if_inp_ok, if_inp_ko, if_out_ok, if_out_ko );
            *if_expr->when = BoolOpSeq( True() );

            // use the outputs of the if instruction
            Vec<Expr> if_out_sel( Size(), outputs.size() );
            for( int i = 0; i < if_out_sel.size(); ++i ) {
                if_out_sel[ i ] = get_nout( if_expr, i );
                *if_out_sel[ i ]->when = BoolOpSeq( True() );
            }

            for( std::pair<Inst *,OutCondFront> o : outputs )
                for( Inst::Parent &p : o.first->par )
                    if ( p.ninp >= 0 )
                        p.inst->mod_inp( if_out_sel[ o.second.num_in_outputs ], p.ninp );
                    else
                        p.inst->mod_dep( if_out_sel[ o.second.num_in_outputs ], o.first );

            // add dep to the if instruction
            for( Expr d : deps )
                if_expr->add_dep( d );

            // push if_expr in the front
            // if_expr->op_id = Inst::cur_op_id - 1;
            // front << if_expr;

            inst = if_expr.inst;
        }

        // register
        inst->op_id = Inst::cur_op_id; // say that it's done
        if ( not beg ) {
            beg = inst;
            end = inst;
        } else {
            end->next_sched = inst;
            inst->prev_sched = end;
            end = inst;
        }

        // update the front
        for( Inst::Parent &p : inst->par ) {
            if ( ready_to_be_scheduled( p.inst ) ) {
                p.inst->op_id = Inst::cur_op_id - 1; // -> in the front
                front << p.inst;
            }
        }
    }

    // delayed operation (ext blocks)
    for( Inst *inst = beg; inst; inst = inst->next_sched ) {
        // schedule sub block (ext instructions)
        for( int ind = 0; ind < inst->ext_disp_size(); ++ind ) {
            Inst *ext_beg = scheduling( inst->ext[ ind ] );
            ext_beg->par_ext_sched = inst;
            inst->ext_sched << ext_beg;
        }

        // add internal break or continue if necessary
        //        CC_SeqItemBlock *b[ s ];
        //        for( int i = 0; i < s; ++i )
        //            b[ i ] = ne->ext[ i ].ptr();
        //        ne->expr->add_break_and_continue_internal( b );
    }

    return beg;
}