00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <list>
00047 #include <map>
00048 #include <set>
00049 #include <utility>
00050 #include <vector>
00051 #include <unistd.h>
00052
00053 #include "region.h"
00054 #include "region_bb_util.h"
00055 #include "speculation.h"
00056 #include "recovery.h"
00057 #include "label_util.h"
00058 #include "gra_live.h"
00059 #include "op.h"
00060 #include "vt_region.h"
00061 #include "defs.h"
00062 #include "cg_flags.h"
00063 #include "tracing.h"
00064 #include "ipfec_defs.h"
00065 #include "scheduler.h"
00066 #include "cgtarget.h"
00067 #include "ipfec_options.h"
00068 #include "whirl2ops.h"
00069
00070 typedef mempool_allocator<TN*> TN_ALLOC;
00071 typedef mempool_allocator<OP*> OP_ALLOC;
00072 std::vector<OP*, OP_ALLOC> chk_vector;
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 inline BOOL
00087 Match_Chk_Ld(OP *chk_op, OP *load_op)
00088 {
00089 Is_True(OP_chk(chk_op),("Input a non-chk OP!"));
00090 Is_True(CGTARG_Is_OP_Speculative(load_op), ("Input a non-speculative load!"));
00091 Is_True((OP_float_chk(chk_op) ? OP_Is_Float_Mem(load_op) : !OP_Is_Float_Mem(load_op)),("Doesn't match, no matter float/integer!"));
00092
00093 if(!TNs_Are_Equivalent(Get_chk_reg(chk_op), OP_result(load_op,0)))
00094 return FALSE;
00095
00096 if( OP_chk_s(chk_op) && CGTARG_Is_OP_Speculative(load_op) && !CGTARG_Is_OP_Advanced_Load(load_op) )
00097 return TRUE;
00098
00099 if( OP_chk_a(chk_op) && CGTARG_Is_OP_Advanced_Load(load_op) )
00100 return TRUE;
00101
00102 return FALSE;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 inline BB*
00115 Get_Recovery_BB(OP* chk)
00116 {
00117 Is_True(OP_chk(chk),("Input a non-chk OP!"));
00118
00119 TN *target_tn;
00120 target_tn = Get_chk_tgt(chk);
00121
00122 Is_True(TN_is_label(target_tn),("Not a label!"));
00123
00124 LABEL_IDX lab;
00125 lab = TN_label(target_tn);
00126
00127 return Get_Label_BB(lab);
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 inline void
00147 Collect_Results(std::set<TN*, compare_tn, TN_ALLOC>& result_set, OP* op)
00148 {
00149 for(INT i = 0; i < OP_results(op); i++){
00150 TN* result = OP_result(op, i);
00151 Is_True(TN_is_GFP(result), ("Result TN is not a GFP register!"));
00152 if(!TN_is_const_reg(result))
00153 result_set.insert(result);
00154 }
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 BB* Divide_BB(BB *bb, OP *point)
00182 {
00183 Is_True(OP_bb(point) == bb,("op is not in bb!"));
00184
00185 if(point == BB_last_op(bb))
00186 return NULL;
00187
00188 BB* bottom_bb = Gen_And_Insert_BB_After(bb);
00189 if (BB_exit(bb)) {
00190 BB_Transfer_Exitinfo(bb, bottom_bb);
00191 Exit_BB_Head = BB_LIST_Delete(bb, Exit_BB_Head);
00192 Exit_BB_Head = BB_LIST_Push(bottom_bb, Exit_BB_Head, &MEM_pu_pool);
00193 }
00194 if (BB_call(bb)) {
00195 BB_Transfer_Callinfo(bb, bottom_bb);
00196 }
00197 if (BB_asm(bb)) {
00198 BB_Transfer_Asminfo (bb, bottom_bb);
00199 }
00200
00201 BBLIST* next;
00202 BBLIST* succ;
00203 for(succ = BB_succs(bb); succ; succ = next) {
00204 BB* bb_succ = BBLIST_item(succ);
00205 next = BBLIST_next(succ);
00206 Link_Pred_Succ_with_Prob(bottom_bb, bb_succ, BBLIST_prob(succ));
00207 Unlink_Pred_Succ(bb, bb_succ);
00208 }
00209 for(OP *op = OP_next(point); op; ) {
00210 OP *tmp = op;
00211 op = OP_next(op);
00212 BB_Move_Op_To_End(bottom_bb, bb, tmp);
00213 }
00214 return bottom_bb;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 static BOOL
00233 Find_Path_in_Region(REGIONAL_CFG_NODE* from,
00234 REGIONAL_CFG_NODE* to,
00235 std::vector<REGIONAL_CFG_NODE *>& path,
00236 std::vector<REGIONAL_CFG_NODE *>& visited)
00237 {
00238 Is_True(to != NULL,("to node is NULL."));
00239
00240 if(from == NULL)
00241 return FALSE;
00242 for(std::vector<REGIONAL_CFG_NODE *>::iterator iter = visited.begin(); iter != visited.end(); iter++){
00243 if(from == *iter)
00244 return FALSE;
00245 }
00246 visited.push_back(from);
00247 if (from == to){
00248 path.push_back(from);
00249 return TRUE;
00250 }
00251 for (CFG_SUCC_NODE_ITER succ_iter(from); succ_iter != 0; ++succ_iter) {
00252 REGIONAL_CFG_NODE* cfg_node = *succ_iter;
00253 if (Find_Path_in_Region(cfg_node, to, path, visited)){
00254 path.push_back(from);
00255 return TRUE;
00256 }
00257 }
00258 return FALSE;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 static std::list<OP *>
00278 Find_Execution_Path(OP *from, OP *to)
00279 {
00280 Is_True(CGTARG_Is_OP_Speculative(from), ("op is not a speculative ld!"));
00281 Is_True(OP_chk(to), ("op is not a chk!"));
00282 Is_True(Home_Region(OP_bb(from)) == Home_Region(OP_bb(to)),("not in the same region!"));
00283
00284 REGIONAL_CFG_NODE* from_node = Regional_Cfg_Node(OP_bb(from));
00285 REGIONAL_CFG_NODE* to_node = Regional_Cfg_Node(OP_bb(to));
00286 std::vector<REGIONAL_CFG_NODE *> regional_cfg_path;
00287 std::vector<REGIONAL_CFG_NODE *> visited_node;
00288
00289 if( from_node == to_node ){
00290 regional_cfg_path.push_back(from_node);
00291 }else{
00292 if(!Find_Path_in_Region(from_node, to_node, regional_cfg_path, visited_node))
00293 FmtAssert(FALSE,("Can not find a regional cfg path!"));
00294 }
00295
00296 std::list<OP *> OP_path;
00297 for(std::vector<REGIONAL_CFG_NODE *>::reverse_iterator iter = regional_cfg_path.rbegin(); iter != regional_cfg_path.rend(); iter++){
00298 if ((*iter)->Is_Region()) continue;
00299 BB* bb = (*iter)->BB_Node();
00300 if(BB_length(bb) == 0) continue;
00301 OP *start_op = bb == OP_bb(from) ? from : BB_first_op(bb);
00302 OP *end_op = bb == OP_bb(to) ? to : BB_last_op(bb);
00303
00304 Is_True(start_op != NULL,("start_op can not be NULL!"));
00305 Is_True(end_op != NULL,("end_op can not be NULL!"));
00306
00307 for(OP *op = start_op; op != OP_next(end_op); op = OP_next(op)){
00308 OP_path.push_back(op);
00309 }
00310 }
00311 return OP_path;
00312 }
00313
00314
00315 static inline BOOL
00316 In_OP_Vector(std::vector<OP*, OP_ALLOC>& opv, OP* op)
00317 {
00318 for(std::vector<OP*, OP_ALLOC>::iterator iter = opv.begin(); iter != opv.end(); iter++){
00319 if(op == *iter){
00320 return TRUE;
00321 }
00322 }
00323 return FALSE;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 static BB *
00343 Do_Build_Recovery_Block(std::list<OP*>& Exec_Path)
00344 {
00345
00346 OP* spec_ld = Exec_Path.front();
00347 OP* chk = Exec_Path.back();
00348
00349 TN* spec_ld_ptn = OP_opnd(spec_ld,0);
00350 TN* chk_ptn = OP_opnd(chk,0);
00351
00352 Is_True(CGTARG_Is_OP_Speculative(spec_ld),("op is not a speculative load!"));
00353 Is_True(OP_chk(chk),("op is not a chk op!"));
00354 Is_True(Match_Chk_Ld(chk,spec_ld),("chk and spec_ld do not match!"));
00355
00356 Exec_Path.pop_front();
00357 Exec_Path.pop_back();
00358
00359 std::vector<OP*, OP_ALLOC> candidate_ops;
00360 std::vector<OP*, OP_ALLOC> cascaded_ops;
00361 std::vector<OP*, OP_ALLOC> cascaded_loads;
00362
00363 std::set<TN*, compare_tn, TN_ALLOC> speculative_chain_def;
00364 std::set<TN*, compare_tn, TN_ALLOC> cascaded_chain_def;
00365
00366 Collect_Results(speculative_chain_def, spec_ld);
00367
00368
00369
00370 for(std::list<OP*, OP_ALLOC>::iterator iter = Exec_Path.begin(); iter != Exec_Path.end(); iter++){
00371 OP* op = *iter;
00372 BOOL on_cascaded_chain = FALSE;
00373 BOOL on_speculative_chain = FALSE;
00374 BOOL depend_by_predicate = FALSE;
00375 for(INT i = 0; i < OP_opnds(op); i++){
00376 TN* opnd = OP_opnd(op,i);
00377 if(!TN_is_register(opnd) || TN_is_const_reg(opnd)){
00378 continue;
00379 }
00380 if(cascaded_chain_def.find(opnd) != cascaded_chain_def.end()){
00381 on_cascaded_chain = TRUE;
00382 }
00383 if(speculative_chain_def.find(opnd) != speculative_chain_def.end()){
00384 on_speculative_chain = TRUE;
00385 if(i == 0 && OP_has_predicate(op)){
00386 depend_by_predicate = TRUE;
00387 }
00388 }
00389 }
00390 if(on_cascaded_chain){
00391
00392 if( CGTARG_Is_OP_Speculative_Load(op) ) {
00393 cascaded_loads.push_back(op);
00394 }
00395
00396 cascaded_ops.push_back(op);
00397 Collect_Results(cascaded_chain_def,op);
00398 continue;
00399 }
00400 if(on_speculative_chain){
00401 TN* cur_ptn = OP_opnd(op,0);
00402 if(OP_baneful(op)){
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 Is_True( cur_ptn != spec_ld_ptn
00422 && cur_ptn != chk_ptn
00423 && cur_ptn != True_TN,("find a baneful op on speculative chain!"));
00424 }else if(depend_by_predicate){
00425 candidate_ops.push_back(op);
00426 Collect_Results(speculative_chain_def,op);
00427 }else{
00428 if( cur_ptn == spec_ld_ptn
00429 || cur_ptn == chk_ptn
00430 || cur_ptn == True_TN){
00431 if(OP_load(op) && IPFEC_Enable_Cascade){
00432 Is_True(CGTARG_Is_OP_Speculative_Load(op),("cascaded load is not a speculative load!"));
00433 cascaded_loads.push_back(op);
00434 cascaded_ops.push_back(op);
00435 Collect_Results(cascaded_chain_def,op);
00436 }else{
00437 candidate_ops.push_back(op);
00438 Collect_Results(speculative_chain_def,op);
00439 }
00440 }
00441 }
00442 }
00443 }
00444
00445 if(CGTARG_Is_OP_Speculative_Load(spec_ld)){
00446 for(std::set<TN*>::iterator iter = speculative_chain_def.begin(); iter != speculative_chain_def.end(); iter++){
00447 TN* tn = *iter;
00448 Set_TN_is_take_nat(tn);
00449 }
00450 }
00451
00452
00453
00454 for(std::list<OP*, OP_ALLOC>::iterator iter = Exec_Path.begin(); iter != Exec_Path.end(); iter++){
00455 OP* op = *iter;
00456 BOOL is_candidate = FALSE;
00457 if(In_OP_Vector(candidate_ops,op)){
00458 continue;
00459 }
00460 if(In_OP_Vector(cascaded_ops,op)){
00461 continue;
00462 }
00463 for(INT i = 0; i < OP_results(op); i++) {
00464 TN *rslt = OP_result(op, i);
00465 if(speculative_chain_def.find(rslt) != speculative_chain_def.end()){
00466 Is_True(!OP_baneful(op),("Find a baneful op in identify output dependence stage!"));
00467 candidate_ops.push_back(op);
00468 Collect_Results(speculative_chain_def, op);
00469 break;
00470 }
00471 }
00472 }
00473
00474
00475
00476 if( candidate_ops.empty() && cascaded_ops.empty() && CGTARG_Is_OP_Advanced_Load(spec_ld) ){
00477 OP* check_ld = Dup_OP(spec_ld);
00478 TN* pr_tn = OP_opnd(chk, 0);
00479 TN* ldtype_tn = OP_Is_Float_Mem(spec_ld) ? Gen_Enum_TN(ECV_fldtype_c_nc) : Gen_Enum_TN(ECV_ldtype_c_nc);
00480 Set_OP_opnd(check_ld, 0, pr_tn);
00481 Set_OP_opnd(check_ld, enum_ldtype_pos, ldtype_tn);
00482 Set_OP_cond_def_kind(check_ld, OP_ALWAYS_COND_DEF);
00483 BB_Insert_Op_Before(OP_bb(chk), chk, check_ld);
00484 BB_Remove_Op(OP_bb(chk), chk);
00485 Copy_WN_For_Memory_OP(check_ld,spec_ld);
00486 Reset_BB_scheduled(OP_bb(check_ld));
00487 return NULL;
00488 }
00489
00490 BB* last_bb = OP_bb(chk);
00491 while(BB_next(last_bb) != NULL)
00492 last_bb = BB_next(last_bb);
00493 BB* recovery_bb = Gen_And_Insert_BB_After(last_bb);
00494
00495 OP* recovery_op = Dup_OP ( spec_ld );
00496 TN* ldtype_tn = OP_Is_Float_Mem(recovery_op) ? Gen_Enum_TN(ECV_fldtype) : Gen_Enum_TN(ECV_ldtype);
00497 Set_OP_opnd ( recovery_op, enum_ldtype_pos, ldtype_tn );
00498 Reset_OP_speculative (recovery_op);
00499 BB_Append_Op (recovery_bb, recovery_op);
00500
00501 for(std::list<OP*>::iterator exec_path_iter = Exec_Path.begin(); exec_path_iter != Exec_Path.end(); exec_path_iter++){
00502 OP* op = *exec_path_iter;
00503 for(std::vector<OP*, OP_ALLOC>::iterator cand_iter = candidate_ops.begin(); cand_iter != candidate_ops.end(); cand_iter++){
00504 if(op == *cand_iter){
00505 for(INT i=0; i < OP_results(op); i++){
00506 TN *result_tn = OP_result(op,i);
00507 if(TN_Is_Allocatable(result_tn))
00508 GTN_UNIVERSE_Add_TN(result_tn);
00509 }
00510 for(INT i=0; i < OP_opnds(op); i++){
00511 TN *opnd_tn = OP_opnd(op,i);
00512 if(TN_Is_Allocatable(opnd_tn))
00513 GTN_UNIVERSE_Add_TN(opnd_tn);
00514 }
00515 recovery_op = Dup_OP(op);
00516 BB_Append_Op(recovery_bb, recovery_op);
00517 }
00518 }
00519
00520
00521 for(std::vector<OP*, OP_ALLOC>::iterator casc_iter = cascaded_ops.begin(); casc_iter != cascaded_ops.end(); casc_iter++){
00522 if(op == *casc_iter){
00523 for(INT i=0; i < OP_results(op); i++){
00524 TN *result_tn = OP_result(op,i);
00525 if(TN_Is_Allocatable(result_tn))
00526 GTN_UNIVERSE_Add_TN(result_tn);
00527 }
00528 for(INT i=0; i < OP_opnds(op); i++){
00529 TN *opnd_tn = OP_opnd(op,i);
00530 if(TN_Is_Allocatable(opnd_tn))
00531 GTN_UNIVERSE_Add_TN(opnd_tn);
00532 }
00533 }
00534 }
00535 }
00536
00537 if(!IPFEC_Enable_Cascade)
00538 return recovery_bb;
00539
00540 if( CGTARG_Is_OP_Speculative(spec_ld) && !CGTARG_Is_OP_Advanced_Load(spec_ld))
00541 return recovery_bb;
00542
00543
00544 for(std::vector<OP *, OP_ALLOC>::iterator iter = cascaded_loads.begin(); iter != cascaded_loads.end(); iter++){
00545 OP *op = *iter;
00546 if( CGTARG_Is_OP_Speculative_Load(op) && CGTARG_Is_OP_Advanced_Load(op) ){
00547 TN *reg_tn = OP_result(op, 0);
00548 TOP op_code = TN_is_float(reg_tn) ? TOP_invala_f_e : TOP_invala_e;
00549 OP *invala = Mk_OP(op_code, True_TN, reg_tn);
00550 BB_Append_Op(recovery_bb, invala);
00551 continue;
00552 }
00553 if( CGTARG_Is_OP_Speculative(op) && !CGTARG_Is_OP_Advanced_Load(op) ){
00554
00555 TN *reg_tn = OP_result(op, 0);
00556 TOP op_code = TN_is_float(reg_tn) ? TOP_ldf8 : TOP_ld8;
00557 TN *ldtype_tn = TN_is_float(reg_tn) ? Gen_Enum_TN(ECV_fldtype_s) : Gen_Enum_TN(ECV_ldtype_s);
00558 OP *load_from_gr_zero = Mk_OP(op_code, reg_tn, True_TN, ldtype_tn, Gen_Enum_TN(ECV_ldhint), Zero_TN);
00559 BB_Append_Op(recovery_bb, load_from_gr_zero);
00560 continue;
00561 }
00562 Is_True(FALSE,("Can not get to here!"));
00563 }
00564 return recovery_bb;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 static void
00579 Build_Recovery_Block()
00580 {
00581
00582 std::vector< std::pair<OP*,OP*> >::iterator iter;
00583 for(iter = load_chk_pairs.begin(); iter != load_chk_pairs.end(); ++iter){
00584
00585 OP* load_op = iter->first;
00586 OP* chk_op = iter->second;
00587 Is_True(Match_Chk_Ld(chk_op,load_op),("chk and spec_ld do not match!"));
00588
00589 std::list<OP *> OP_exec_path = Find_Execution_Path(load_op, chk_op);
00590 BB *recovery_bb = Do_Build_Recovery_Block(OP_exec_path);
00591 if( recovery_bb ){
00592 Set_BB_recovery(recovery_bb);
00593 TN *label_tn = Gen_Label_TN(Gen_Label_For_BB(recovery_bb), 0);
00594 Set_chk_tgt(chk_op, label_tn);
00595 chk_vector.push_back(chk_op);
00596 }
00597 }
00598 return;
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 static INT16
00611 Update_CFG()
00612 {
00613 INT16 count = 0;
00614
00615 std::vector<OP*, OP_ALLOC>::iterator iter;
00616 for(iter = chk_vector.begin(); iter != chk_vector.end(); iter++){
00617
00618 OP *chk_op = *iter;
00619 Is_True(OP_chk(chk_op),("chk_op is not a chk!"));
00620
00621
00622
00623 BB *recovery_bb = Get_Recovery_BB(chk_op);
00624 Is_True(recovery_bb,("can not find corresponding recovery block!"));
00625
00626 BB* home_bb = OP_bb(chk_op);
00627 BOOL home_intact = BB_scheduled(home_bb);
00628 BOOL home_chk_split = BB_chk_split(home_bb);
00629 BOOL home_split_head = BB_chk_split_head(home_bb);
00630 BOOL home_split_tail = BB_chk_split_tail(home_bb);
00631
00632
00633
00634 BOOL cut = TRUE;
00635 BB* bottom_bb = NULL;
00636 bottom_bb = RGN_Divide_BB(home_bb, chk_op, TRUE);
00637 FmtAssert(bottom_bb != NULL,
00638 ("RGN_Divide_BB() returned NULL bottom_bb"));
00639
00640
00641
00642 RGN_Unlink_Pred_Succ(home_bb, bottom_bb);
00643 RGN_Link_Pred_Succ_With_Prob(home_bb, bottom_bb, btm_prob);
00644
00645 RGN_Gen_And_Insert_Node(recovery_bb,home_bb,bottom_bb);
00646 RGN_Link_Pred_Succ_With_Prob(home_bb, recovery_bb, rec_prob);
00647
00648 Add_Goto_Op(recovery_bb, bottom_bb);
00649 RGN_Link_Pred_Succ_With_Prob(recovery_bb, bottom_bb, 1.0F);
00650
00651 BB_freq(recovery_bb) = BB_freq(home_bb) * rec_prob;
00652 BB_freq(bottom_bb) = BB_freq(home_bb);
00653
00654
00655
00656 if(cut) {
00657 if(IPFEC_Chk_Compact) {
00658
00659 if(!home_chk_split){
00660 Set_BB_chk_split_head(home_bb);
00661 Set_BB_chk_split_tail(bottom_bb);
00662 }
00663 if(home_split_head)
00664 Set_BB_chk_split_head(home_bb);
00665 else if(home_split_tail){
00666 Reset_BB_chk_split_tail(home_bb);
00667 Set_BB_chk_split_tail(bottom_bb);
00668 }
00669
00670 Set_BB_chk_split(home_bb);
00671 Set_BB_chk_split(bottom_bb);
00672 if(home_intact){
00673 Set_BB_scheduled(home_bb);
00674 Set_BB_scheduled(bottom_bb);
00675 }else{
00676 Reset_BB_scheduled(home_bb);
00677 Reset_BB_scheduled(bottom_bb);
00678 }
00679 }else{
00680 Reset_BB_scheduled(home_bb);
00681 Reset_BB_scheduled(bottom_bb);
00682 }
00683 }
00684 count++;
00685 }
00686 return count;
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 INT16
00700 Generate_Recovery_Code()
00701 {
00702 INT16 count;
00703 Set_Error_Phase("recovery block generation");
00704 chk_vector.clear();
00705 Build_Recovery_Block();
00706 count = Update_CFG();
00707 load_chk_pairs.clear();
00708 return count;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 void
00725 Adjust_Recovery_Block()
00726 {
00727
00728 BB* home_bb = NULL;
00729 BB* recovery_bb = NULL;
00730 BB* bottom_bb = NULL;
00731
00732 for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00733 if (BB_recovery(bb))
00734 continue;
00735 for (OP* op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
00736 if (!OP_chk(op))
00737 continue;
00738 OP* chk_op = op;
00739 home_bb = bb;
00740 recovery_bb = Get_Recovery_BB(chk_op);
00741 Is_True(BB_recovery(recovery_bb),("not a recovery block!"));
00742
00743 Is_True(BB_succs_len(recovery_bb) == 1,("recovery block's successor num > 1 !"));
00744
00745 bottom_bb = BB_Unique_Successor(recovery_bb);
00746 while(BB_length(bottom_bb) == 0)
00747 bottom_bb = BB_next(bottom_bb);
00748
00749 OP* first_op = BB_first_op(bottom_bb);
00750 if(OP_dummy(first_op))
00751 first_op = OP_next(first_op);
00752 Is_True(first_op != NULL,("too many dummy OP!"));
00753 Is_True(!OP_dummy(first_op),("too many dummy OP!"));
00754
00755 if(OP_start_bundle(first_op))
00756 continue;
00757
00758 Is_True(bottom_bb == BB_next(home_bb),("bottom_bb must be a fall through bb of home_bb!"));
00759 Is_True(BB_in_succs(home_bb,bottom_bb),("bottom_bb,must be a fall through bb of home_bb!"));
00760 Is_True(chk_op == BB_last_op(home_bb), ("chk_op should be the last op of home bb!"));
00761
00762 BB_Remove_Op(recovery_bb, BB_last_op(recovery_bb));
00763 Unlink_Pred_Succ(recovery_bb, bottom_bb);
00764
00765 BOOL need_jump_back = TRUE;
00766 BB* jump_back_bb = NULL;
00767 OP* prev_op = chk_op;
00768 OP* copy_op = first_op;
00769 while(!OP_start_bundle(copy_op)){
00770 OP* dup_op = Dup_OP(copy_op);
00771 BB_Append_Op(recovery_bb, dup_op);
00772 prev_op = copy_op;
00773 if(OP_next(prev_op) != NULL){
00774 copy_op = OP_next(prev_op);
00775 }else{
00776 BB* prev_bb = OP_bb(prev_op);
00777 BB* next_bb = BB_next(prev_bb);
00778 if(!BB_in_succs(prev_bb,next_bb)){
00779 need_jump_back = FALSE;
00780 break;
00781 }else{
00782 while(BB_length(next_bb) == 0)
00783 next_bb = BB_next(next_bb);
00784 jump_back_bb = next_bb;
00785 copy_op = BB_first_op(next_bb);
00786 }
00787 }
00788 }
00789
00790 if(need_jump_back){
00791 if(OP_next(prev_op) != NULL){
00792 jump_back_bb = Divide_BB(OP_bb(prev_op), prev_op);
00793 Is_True(jump_back_bb,("jump_back can not be NULL!"));
00794 Is_True(OP_start_bundle(BB_first_op(jump_back_bb)),("jump_back's first op must start a bundle!"));
00795 BB_freq(jump_back_bb) = BB_freq(OP_bb(prev_op));
00796 Set_BB_chk_split(jump_back_bb);
00797 Set_BB_scheduled(jump_back_bb);
00798 Link_Pred_Succ_with_Prob(OP_bb(prev_op), jump_back_bb, btm_prob);
00799 }
00800 Add_Goto(recovery_bb, jump_back_bb);
00801 }
00802 Reset_BB_scheduled(recovery_bb);
00803 SCHEDULER local_scheduler(recovery_bb, FALSE);
00804 local_scheduler.Schedule_BB();
00805 Set_BB_scheduled(recovery_bb);
00806 }
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 BOOL BB_Check_Bundle_Integrity(BB* bb)
00822 {
00823
00824
00825 if(BB_length(bb) == 0){
00826 return TRUE;
00827 }
00828
00829 for (OP* op = BB_first_op(bb);;) {
00830 UINT64 slot_mask;
00831 UINT stop_mask;
00832 INT slot;
00833 INT ibundle;
00834
00835
00836
00837 stop_mask = 0;
00838 slot_mask = 0;
00839 for (slot = 0; op && slot < ISA_MAX_SLOTS; op = OP_next(op)) {
00840 INT words;
00841 INT w;
00842
00843 if(!OP_dummy(op)){
00844 if (OP_simulated(op))
00845 return FALSE;
00846 if(slot == 0){
00847 Set_OP_start_bundle(op);
00848 }else{
00849 Reset_OP_start_bundle(op);
00850 }
00851 words = ISA_PACK_Inst_Words(OP_code(op));
00852 for (w = 0; w < words; ++w) {
00853 if (slot >= ISA_MAX_SLOTS)
00854 return FALSE;
00855 slot++;
00856 slot_mask = slot_mask << ISA_TAG_SHIFT;
00857 if ( EXEC_PROPERTY_is_M_Unit(OP_code(op)) &&
00858 EXEC_PROPERTY_is_I_Unit(OP_code(op)) ){
00859 slot_mask |= OP_m_unit(op) ? ISA_EXEC_PROPERTY_M_Unit : ISA_EXEC_PROPERTY_I_Unit;
00860 } else {
00861 slot_mask |= ISA_EXEC_Unit_Prop(OP_code(op));
00862 }
00863 stop_mask = stop_mask << 1;
00864 }
00865 PORT_SET b0b2;
00866 b0b2 = b0b2 + ip_B0;
00867 b0b2 = b0b2 + ip_B2;
00868 if (TSI_Issue_Ports(OP_code(op))== b0b2){
00869 slot_mask = slot_mask | ISA_EXEC_PROPERTY_B_Unit;
00870 }
00871 stop_mask |= (OP_end_group(op) != 0);
00872 }
00873 }
00874
00875 if (slot == 0)
00876 return TRUE;
00877
00878 if (slot != ISA_MAX_SLOTS)
00879 return FALSE;
00880
00881 for (ibundle = 0; ibundle < ISA_MAX_BUNDLES; ++ibundle) {
00882 UINT64 this_slot_mask = ISA_EXEC_Slot_Mask(ibundle);
00883 UINT32 this_stop_mask = ISA_EXEC_Stop_Mask(ibundle);
00884 if ((slot_mask & this_slot_mask) == this_slot_mask && (stop_mask & ~1) == this_stop_mask)
00885 break;
00886 }
00887 if (ibundle == ISA_MAX_BUNDLES)
00888 return FALSE;
00889 }
00890 Is_True(FALSE,("Can not get to here!"));
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 void BB_Disconnect_All_Preds(BB* bb)
00905 {
00906 BBLIST* next;
00907 BBLIST* pred;
00908 for(pred = BB_preds(bb); pred; pred = next){
00909 BB* pred_bb = BBLIST_item(pred);
00910 next = BBLIST_next(pred);
00911 Unlink_Pred_Succ(pred_bb,bb);
00912 }
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 void BB_Disconnect_All_Succs(BB* bb)
00927 {
00928 BBLIST* next;
00929 BBLIST* succ;
00930 for(succ = BB_succs(bb); succ; succ = next){
00931 BB* succ_bb = BBLIST_item(succ);
00932 next = BBLIST_next(succ);
00933 Unlink_Pred_Succ(bb, succ_bb);
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 void BB_Take_Over_All_Preds(BB* to_bb, BB* from_bb)
00949 {
00950 BBLIST* next;
00951 BBLIST* pred;
00952 for(pred = BB_preds(from_bb); pred; pred = next){
00953 BB* pred_bb = BBLIST_item(pred);
00954 next = BBLIST_next(pred);
00955 Link_Pred_Succ_with_Prob(pred_bb, to_bb, BBLIST_prob(pred));
00956 Unlink_Pred_Succ(pred_bb,from_bb);
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 void BB_Take_Over_All_Succs(BB* to_bb, BB* from_bb)
00971 {
00972 BBLIST* next;
00973 BBLIST* succ;
00974 for(succ = BB_succs(from_bb); succ; succ = next){
00975 BB* succ_bb = BBLIST_item(succ);
00976 next = BBLIST_next(succ);
00977 Link_Pred_Succ_with_Prob(to_bb, succ_bb, BBLIST_prob(succ));
00978 Unlink_Pred_Succ(from_bb, succ_bb);
00979 }
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 void BB_Copy_All_Preds(BB* to_bb, BB* from_bb)
00993 {
00994 BBLIST* next;
00995 BBLIST* pred;
00996 for(pred = BB_preds(from_bb); pred; pred = next){
00997 BB* pred_bb = BBLIST_item(pred);
00998 next = BBLIST_next(pred);
00999 Link_Pred_Succ_with_Prob(pred_bb, to_bb, BBLIST_prob(pred));
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 void BB_Copy_All_Succs(BB* to_bb, BB* from_bb)
01015 {
01016 BBLIST* next;
01017 BBLIST* succ;
01018 for(succ = BB_succs(from_bb); succ; succ = next){
01019 BB* succ_bb = BBLIST_item(succ);
01020 next = BBLIST_next(succ);
01021 Link_Pred_Succ_with_Prob(to_bb, succ_bb, BBLIST_prob(succ));
01022 }
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 BB*
01040 Handle_Chk_Split_Bunch(BB* head_bb)
01041 {
01042
01043
01044
01045
01046 BB* tail_bb = head_bb;
01047 for(BB* bb = BB_next(head_bb); bb; bb = BB_next(bb)){
01048 if(BB_chk_split(bb) && !BB_chk_split_head(bb)){
01049 tail_bb = bb;
01050 continue;
01051 }
01052 if(BB_length(bb) == 0){
01053 continue;
01054 }
01055 break;
01056 }
01057
01058
01059
01060 for(BB* bb = head_bb; bb != BB_next(tail_bb); bb = BB_next(bb)){
01061 for(OP* op = BB_first_op(bb); op; op = OP_next(op)){
01062 if(OP_chk(op)){
01063 Is_True(op == BB_last_op(bb),("chk is not the last op of an chk split BB!"));
01064 BB* rec_bb = Get_Recovery_BB(op);
01065 Is_True(BB_recovery(rec_bb),("not a recovery block!"));
01066 BB_Disconnect_All_Preds(rec_bb);
01067 BB_Disconnect_All_Succs(rec_bb);
01068 Is_True(OP_xfer(BB_last_op(rec_bb)),("rec_bb's last op should be an branch!"));
01069 BB_Remove_Op(rec_bb, BB_last_op(rec_bb));
01070 }
01071 }
01072 if(bb != tail_bb)
01073 BB_Disconnect_All_Succs(bb);
01074 if(bb != head_bb){
01075 BB_Disconnect_All_Preds(bb);
01076 BB_Append_All(head_bb,bb);
01077 if (BB_exit(bb)) {
01078 BB_Transfer_Exitinfo(bb, head_bb);
01079 Exit_BB_Head = BB_LIST_Delete(bb, Exit_BB_Head);
01080 Exit_BB_Head = BB_LIST_Push(head_bb, Exit_BB_Head, &MEM_pu_pool);
01081 }
01082 if (BB_call(bb)) {
01083 BB_Transfer_Callinfo(bb, head_bb);
01084 }
01085 if (BB_asm(bb)) {
01086 BB_Transfer_Asminfo (bb, head_bb);
01087 }
01088 if(bb == tail_bb)
01089 BB_Take_Over_All_Succs(head_bb,bb);
01090 BB_next(BB_prev(bb)) = BB_next(bb);
01091 BB_prev(BB_next(bb)) = BB_prev(bb);
01092 }
01093 bb = head_bb;
01094 }
01095
01096
01097 SCHEDULER local_scheduler(head_bb, FALSE);
01098 local_scheduler.Schedule_BB();
01099
01100 Set_BB_scheduled(head_bb);
01101 Set_BB_chk_split(head_bb);
01102 BB* end_bb = head_bb;
01103
01104
01105
01106 OP* last_op = BB_last_op(head_bb);
01107 for(OP* cur_op = BB_first_op(head_bb);;){
01108 if(OP_chk(cur_op)){
01109 OP* chk = cur_op;
01110 BB* home_bb = OP_bb(chk);
01111 BB* rec_bb = Get_Recovery_BB(chk);
01112 BB* back_bb = NULL;
01113 BB* btm_bb = NULL;
01114 BOOL has_chk = FALSE;
01115 BOOL has_br = FALSE;
01116 OP* bar = chk;
01117 OP* tmp = chk;
01118 float fall_thru_prob = 0;
01119
01120
01121
01122 while (tmp && !OP_end_group(tmp)) tmp = OP_next(tmp);
01123 if(tmp && (!OP_next(tmp) ||OP_start_bundle(OP_next(tmp)))) {
01124 OP* op = chk;
01125 while(op != NULL && !OP_end_group(op)) {
01126 op = OP_next(op);
01127 bar = op;
01128 OP* dup_op = Dup_OP(op);
01129 BB_Append_Op(rec_bb,dup_op);
01130 if(OP_chk(op)) has_chk = TRUE;
01131 if(TOP_is_xfer(OP_code(op)) || OP_call(op)) has_br = TRUE;
01132 }
01133 } else {
01134 for(OP* op = OP_next(chk); (op != NULL && !OP_start_bundle(op)); op = OP_next(op)) {
01135 bar = op;
01136 OP* dup_op = Dup_OP(op);
01137 BB_Append_Op(rec_bb,dup_op);
01138 if(OP_chk(op)) has_chk = TRUE;
01139 if(TOP_is_xfer(OP_code(op)) || OP_call(op)) has_br = TRUE;
01140 }
01141 }
01142
01143 back_bb = Divide_BB(home_bb,bar);
01144 if(back_bb == NULL){
01145 back_bb = BB_Fall_Thru_Successor(home_bb);
01146 if(back_bb != NULL){
01147 BBLIST *succ = BB_Find_Succ(home_bb,back_bb);
01148 fall_thru_prob = BBLIST_prob(succ);
01149 }
01150 }else{
01151 Is_True(has_br == FALSE,("Branch op should be in the last bundle of its' home BB!"));
01152 Link_Pred_Succ_with_Prob(home_bb,back_bb,btm_prob);
01153 BB_freq(back_bb) = BB_freq(home_bb);
01154 Set_BB_chk_split(back_bb);
01155 Set_BB_scheduled(back_bb);
01156 }
01157 if(back_bb != NULL){
01158 Add_Goto(rec_bb,back_bb);
01159 }
01160 if(has_chk || has_br){
01161 btm_bb = Divide_BB(home_bb,chk);
01162 Link_Pred_Succ_with_Prob(home_bb,btm_bb,btm_prob);
01163 BB_freq(btm_bb) = BB_freq(home_bb);
01164 Set_BB_chk_split(btm_bb);
01165 Set_BB_scheduled(btm_bb);
01166 }
01167 Link_Pred_Succ_with_Prob(home_bb,rec_bb,rec_prob);
01168 if(has_br && back_bb != NULL){
01169 BB* frag_bb = Divide_BB(rec_bb,OP_prev(BB_last_op(rec_bb)));
01170 BB_Copy_All_Succs(rec_bb,btm_bb);
01171 Change_Succ(rec_bb,back_bb,frag_bb);
01172 BB_freq(frag_bb) = BB_freq(rec_bb) * fall_thru_prob;
01173 Reset_BB_scheduled(rec_bb);
01174 Reset_BB_scheduled(frag_bb);
01175 Set_BB_recovery(frag_bb);
01176 }
01177 }
01178 if(cur_op == last_op){
01179 break;
01180 }else if(OP_next(cur_op)){
01181 cur_op = OP_next(cur_op);
01182 }else{
01183 Is_True(BB_next(OP_bb(cur_op)),("cur_op's next bb should not be NULL!"));
01184 Is_True(BB_chk_split(BB_next(OP_bb(cur_op))),("cur_op's next bb should be chk_split bb!"));
01185 cur_op = BB_first_op(BB_next(OP_bb(cur_op)));
01186 end_bb = OP_bb(cur_op);
01187 }
01188 }
01189
01190 Is_True(end_bb,("end_bb should not be NULL!"));
01191 return end_bb;
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 void
01204 Force_Chk_Fail()
01205 {
01206
01207 for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
01208 for (OP* op = BB_first_op(bb); op != NULL; op = OP_next(op)){
01209 if(CGTARG_Is_OP_Check_Load(op)){
01210 TN* ldtype_tn = OP_Is_Float_Mem(op) ? Gen_Enum_TN(ECV_fldtype) : Gen_Enum_TN(ECV_ldtype);
01211 Set_OP_opnd(op, 1, ldtype_tn);
01212 continue;
01213 }
01214 if(OP_chk_s(op)){
01215 OP* chk_a;
01216 TN* pr_tn = OP_opnd(op,0);
01217 TN *aclr_tn = Gen_Enum_TN(ECV_aclr_clr);
01218 TN *target_tn = OP_opnd(op,2);
01219 if(OP_float_chk(op)){
01220 chk_a = Mk_OP(TOP_chk_f_a, pr_tn, aclr_tn, FZero_TN, target_tn);
01221 }else{
01222 chk_a = Mk_OP(TOP_chk_a, pr_tn, aclr_tn, Zero_TN, target_tn);
01223 }
01224 OP_flags(chk_a) = OP_flags(op);
01225 BB_Insert_Op_After(bb, op, chk_a);
01226 BB_Remove_Op(bb,op);
01227 continue;
01228 }
01229 if(OP_chk_a(op)){
01230 TN* reg_tn = OP_float_chk(op) ? FZero_TN : Zero_TN;
01231 Set_OP_opnd(op, 2, reg_tn);
01232 continue;
01233 }
01234 }
01235 }
01236 }
01237
01238