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