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 ); }
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; }
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; }