Exemplo n.º 1
0
Var Interpreter::make_Callable( Vec<Var> lst, Var self ) {
    // remove doubles
    for( int i = 0; i < lst.size(); ++i )
        for( int j = i + 1; j < lst.size(); ++j )
            if ( lst[ i ].expr() == lst[ j ].expr() )
                lst.remove_unordered( j-- );

    //
    Expr surdef_list_data = cst( SI32( lst.size() ) );
    for( int i = 0; i < lst.size(); ++i )
        surdef_list_data = concat( surdef_list_data, pointer_on( lst[ i ].expr() ) );
    Var surdef_list( &type_SurdefList, surdef_list_data );

    //
    Var self_type = type_of( self ); // returns void if self is not defined

    // -> Callable[ surdef_list, self_type, parm_type ]
    Var *parms[ 3 ];
    parms[ 0 ] = &surdef_list;
    parms[ 1 ] = &self_type;
    parms[ 2 ] = &void_var;

    Var *callable_type = type_for( class_info( class_Callable ), parms );
    return Var( callable_type, self ? pointer_on( self.expr() ) : cst() ).add_ref( 0, self );
}
Exemplo n.º 2
0
static Vec<Expr> extract_inst_that_must_be_done_if( std::map<Inst *,OutCondFront> &outputs, std::map<Expr,int> &inputs, std::set<Expr> &deps, Vec<Expr> &front, const BoolOpSeq &best_item, bool ok ) {
    // inst in the front that must be done
    Vec<Expr> cond_front, res;
    for( int i = 0; i < front.size(); ++i ) {
        if ( front[ i ]->when->can_be_factorized_by( best_item ) ) {
            Expr expr = front[ i ];
            res << expr;
            // mv inst from front to cond_front
            cond_front << expr;
            front.remove_unordered( i-- );
        }
    }


    // expand the front
    Inst *inst;
    while ( cond_front.size() ) {
        // pick a random ready inst
        inst = cond_front.pop_back().inst;

        // say that it's done
        inst->op_id = Inst::cur_op_id;

        // update the front
        for( Inst::Parent &p : inst->par ) {
            // an instruction that cannot be executed under the condition best_item ?
            if ( not p.inst->when->can_be_factorized_by( best_item ) ) {
                // -> it will be computed under an IfInp, parents will use Nout(If,...)
                Inst *to_be_replaced = inst->par.size() == 1 ? p.inst : inst;
                if ( not outputs.count( to_be_replaced ) )
                    outputs[ to_be_replaced ].num_in_outputs = outputs.size() - 1;
                outputs[ to_be_replaced ].inp[ ok ] = inst;
            // else, add to front if possible
            } else if ( ready_to_be_scheduled( p.inst ) ) {
                p.inst->op_id = Inst::cur_op_id - 1; // -> in the front
                cond_front << p.inst;
                res << p.inst;
            }
        }
    }

    // needed inputs (inp of produced inst that does not belong to the if block)
    for( Expr expr : res ) {
        for( Expr inp : expr->inp )
            if ( inp.inst and not inp->when->can_be_factorized_by( best_item ) )
                if ( not inputs.count( inp ) )
                    inputs[ inp ] = inputs.size() - 1;
        for( Expr dep : expr->dep )
            if ( dep and not dep->when->can_be_factorized_by( best_item ) )
                deps.insert( dep );
    }

    return res;
}
Exemplo n.º 3
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;
}