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 #include <alloca.h>
00042 #include "defs.h"
00043 #include "config.h"
00044 #include "mempool.h"
00045 #include "tracing.h"
00046 #include "timing.h"
00047 #include "cgir.h"
00048 #include "pu_info.h"
00049 #include "cg.h"
00050 #include "cg_flags.h"
00051 #include "ttype.h"
00052 #include "targ_sim.h"
00053 #include "bb_set.h"
00054 #include "freq.h"
00055 #include "cgtarget.h"
00056 #include "whirl2ops.h"
00057 #include "dominate.h"
00058 #include "findloops.h"
00059 #include "cg_vector.h"
00060 #include "gtn_universe.h"
00061 #include "gtn_set.h"
00062 #include "data_layout.h"
00063 #include "op.h"
00064 #include "cflow.h"
00065 #include "reg_live.h"
00066
00067 #define X87_STACK_SIZE ( X87_Preg_Max_Offset - X87_Preg_Min_Offset + 1 )
00068 #define FIRST_STACK_REG REGISTER_MIN
00069 #define STACK_IS_EMPTY -1 // this stack is empty
00070 #define STACK_IS_WILD -2 // this stack has not been initialized yet
00071
00072 typedef struct _Stack {
00073 int top;
00074 REGISTER_SET live_in;
00075 REGISTER_SET live_out;
00076 REGISTER reg[X87_STACK_SIZE];
00077
00078 struct _Stack* stack_in;
00079 } Stack;
00080
00081 static int new_bbs = 0;
00082 static BB_MAP bb_stack_info_map;
00083
00084 static BB_MAP dfs_map;
00085
00086 #define BB_NOT_REACHABLE(b) ( BB_MAP32_Get( dfs_map, (b) ) == 0 )
00087
00088 static inline Stack* Get_Stack_Info( BB* bb )
00089 {
00090 Stack* stack = (Stack*)BB_MAP_Get(bb_stack_info_map,(bb));
00091 FmtAssert( stack != NULL, ("NYI") );
00092 return stack;
00093 }
00094
00095
00096
00097
00098
00099
00100 static bool OP_refs_x87( OP* op )
00101 {
00102
00103 if( TOP_is_x87(OP_code(op)) )
00104 return true;
00105
00106
00107 if( OP_call( op ) ){
00108 const ANNOTATION* ant = ANNOT_Get( BB_annotations(OP_bb(op)), ANNOT_CALLINFO );
00109 if( ant == NULL ){
00110 FmtAssert( TN_is_label( OP_opnd( op, 0 ) ), ("call has no annotations") );
00111 return FALSE;
00112 }
00113
00114 const CALLINFO* call_info = ANNOT_callinfo(ant);
00115 const ST* call_st = CALLINFO_call_st(call_info);
00116 const WN* call_wn = CALLINFO_call_wn(call_info);
00117 const TY_IDX call_ty = call_st != NULL ? ST_pu_type(call_st) : WN_ty(call_wn);
00118 const RETURN_INFO return_info = Get_Return_Info( TY_ret_type(call_ty),
00119 No_Simulated,
00120 call_st ? PU_ff2c_abi(Pu_Table[ST_pu(call_st)]) : FALSE);
00121
00122 for( int i = 0; i < RETURN_INFO_count(return_info); i++ ){
00123 const TYPE_ID type = RETURN_INFO_mtype( return_info, i );
00124
00125 if( MTYPE_is_quad( type ) ||
00126 ( MTYPE_is_float( type ) &&
00127 Is_Target_32bit() ) ){
00128 return TRUE;
00129 }
00130 }
00131
00132 return FALSE;
00133 }
00134
00135
00136 if( OP_code(op) == TOP_asm ){
00137 for( int i = 0; i < OP_results(op); i++ ){
00138 TN* result = OP_result( op, i );
00139 if( TN_register_class(result) == ISA_REGISTER_CLASS_x87 )
00140 return true;
00141 }
00142
00143 for( int i = 0; i < OP_opnds(op); i++ ){
00144 TN* opnd = OP_opnd( op, i );
00145 if( TN_is_register( opnd ) &&
00146 TN_register_class(opnd) == ISA_REGISTER_CLASS_x87 )
00147 return true;
00148 }
00149 }
00150
00151 return false;
00152 }
00153
00154
00155
00156 static VECTOR bbs_vector = NULL;
00157
00158 static MEM_POOL local_mem_pool;
00159 static MEM_POOL* pu_mem_pool = NULL;
00160
00161 static bool trace = false;
00162
00163 typedef struct {
00164 mINT8 result_st[ISA_OPERAND_max_results];
00165 mINT8 opnd_st[ISA_OPERAND_max_operands];
00166 } OP_stinfo;
00167
00168 extern BB_MAP BBs_Map;
00169
00170 static OP_stinfo* Get_OP_stinfo( OP* op )
00171 {
00172 BB_OP_MAP op_map = (BB_OP_MAP)BB_MAP_Get( BBs_Map, OP_bb(op) );
00173
00174 return op_map == NULL ? NULL : (OP_stinfo*)BB_OP_MAP_Get( op_map, op );
00175 }
00176
00177
00178
00179 int Get_OP_stack_reg( OP* op, int opnd )
00180 {
00181 const OP_stinfo* stinfo = Get_OP_stinfo( op );
00182 if( stinfo == NULL ){
00183 return FIRST_STACK_REG - 1;
00184 }
00185
00186 const int st = opnd < 0 ? stinfo->result_st[0] - 1 : stinfo->opnd_st[opnd] - 1;
00187 FmtAssert( st >= 0 && st < X87_STACK_SIZE, ("Invalie stack register.") );
00188
00189 return st;
00190 }
00191
00192
00193 static void Create_OP_stinfo( OP* op )
00194 {
00195 OP_stinfo* stinfo = TYPE_MEM_POOL_ALLOC( OP_stinfo, pu_mem_pool );
00196
00197 bzero( stinfo, sizeof(stinfo[0]) );
00198 FmtAssert( OP_bb(op) != NULL, ("NYI") );
00199 BB_OP_MAP bb_map = (BB_OP_MAP)BB_MAP_Get( BBs_Map, OP_bb(op) );
00200 BB_OP_MAP_Set( bb_map, op, stinfo );
00201 }
00202
00203
00204 static TOP Pop_Table[TOP_count+1];
00205 static TOP Reverse_Table[TOP_count+1];
00206
00207 static void Init_Pop_Table()
00208 {
00209 for( int i = 0; i <= TOP_count; i++ ){
00210 Reverse_Table[i] = Pop_Table[i] = TOP_UNDEFINED;
00211 }
00212
00213
00214
00215 Pop_Table[TOP_fadd] = TOP_faddp;
00216 Pop_Table[TOP_fmul] = TOP_fmulp;
00217 Pop_Table[TOP_fsub] = TOP_fsubp;
00218 Pop_Table[TOP_fsubr] = TOP_fsubrp;
00219 Pop_Table[TOP_fdiv] = TOP_fdivp;
00220 Pop_Table[TOP_fdivr] = TOP_fdivrp;
00221 Pop_Table[TOP_fucomi] = TOP_fucomip;
00222
00223
00224
00225 Pop_Table[TOP_fstp] = TOP_fst;
00226 Pop_Table[TOP_fstps] = TOP_fsts;
00227 Pop_Table[TOP_fstpl] = TOP_fstl;
00228 Pop_Table[TOP_fstps_n32] = TOP_fsts_n32;
00229 Pop_Table[TOP_fstpl_n32] = TOP_fstl_n32;
00230 Pop_Table[TOP_fistps] = TOP_fists;
00231 Pop_Table[TOP_fistpl] = TOP_fistl;
00232
00233
00234
00235 Reverse_Table[TOP_fsub] = TOP_fsubr;
00236 Reverse_Table[TOP_fsubr] = TOP_fsub;
00237 Reverse_Table[TOP_fsubp] = TOP_fsubrp;
00238 Reverse_Table[TOP_fsubrp] = TOP_fsubp;
00239
00240 Reverse_Table[TOP_fdiv] = TOP_fdivr;
00241 Reverse_Table[TOP_fdivr] = TOP_fdiv;
00242 Reverse_Table[TOP_fdivp] = TOP_fdivrp;
00243 Reverse_Table[TOP_fdivrp] = TOP_fdivp;
00244 }
00245
00246
00247
00248
00249 static bool Is_TN_Last_Use( Stack* stack, OP* op, TN* tn, bool is_opnd )
00250 {
00251 const ISA_REGISTER_CLASS cl = TN_register_class(tn);
00252 const REGISTER reg = TN_register(tn);
00253
00254 if( is_opnd && OP_Defs_Reg( op, cl, reg ) )
00255 return true;
00256
00257 for( OP* next = OP_next(op); next != NULL; next = OP_next(next) ){
00258
00259 if( OP_call( next ) )
00260 return true;
00261
00262
00263 if( OP_refs_x87( next ) ){
00264 if( OP_Refs_Reg( next, cl, reg ) )
00265 return false;
00266
00267 if( OP_Defs_Reg( next, cl, reg ) )
00268 return true;
00269 }
00270 }
00271
00272 return !REGISTER_SET_MemberP( stack->live_out, reg );
00273 }
00274
00275
00276 static bool Is_Opnd_Last_Use( Stack* stack, OP* op, TN* tn )
00277 {
00278 return Is_TN_Last_Use( stack, op, tn, true );
00279 }
00280
00281
00282 static bool Is_Result_Last_Use( Stack* stack, OP* op, TN* tn )
00283 {
00284 return Is_TN_Last_Use( stack, op, tn, false );
00285 }
00286
00287
00288
00289
00290
00291 static int Get_Stack_Index( Stack* stack, REGISTER reg )
00292 {
00293 if( reg < FIRST_STACK_REG ||
00294 reg > REGISTER_CLASS_last_register(ISA_REGISTER_CLASS_x87) ){
00295 FmtAssert( false, ("Invalid x87 register") );
00296 }
00297
00298 FmtAssert( stack->top >= -1, ("x87 stack underflows.") );
00299 FmtAssert( stack->top < X87_STACK_SIZE, ("x87 stack overflows.") );
00300
00301 for( int i = 0; i <= stack->top; i++ ){
00302 if( stack->reg[i] == reg )
00303 return i;
00304 }
00305
00306 return -1;
00307 }
00308
00309
00310
00311
00312 static void Alloc_Stack_Reg( Stack* stack, OP* op, int opnd, int stack_idx )
00313 {
00314 TN* tn = opnd < 0 ? OP_result( op, -opnd-1 ) : OP_opnd( op, opnd );
00315
00316 if( !TN_is_register(tn) ||
00317 TN_register(tn) == REGISTER_UNDEFINED ||
00318 TN_register_class(tn) != ISA_REGISTER_CLASS_x87 ||
00319 stack_idx < 0 ){
00320 FmtAssert( false, ("NYI") );
00321 }
00322
00323 OP_stinfo* stinfo = Get_OP_stinfo( op );
00324 if( opnd < 0 )
00325 stinfo->result_st[-opnd-1] = stack->top - stack_idx + 1;
00326 else
00327 stinfo->opnd_st[opnd] = stack->top - stack_idx + 1;
00328
00329 if( trace ){
00330 fprintf( TFile, "allocate ST(%d) to %s %d of %s%d(%s)\n",
00331 stack->top - stack_idx,
00332 opnd < 0 ? "result" : "opnd",
00333 opnd < 0 ? -opnd-1 : opnd,
00334 TN_is_global_reg(tn) ? "GTN" : "TN",
00335 TN_number(tn),
00336 REGISTER_name(TN_register_class(tn), TN_register(tn)) );
00337 }
00338 }
00339
00340
00341 static void Print_Stack( Stack* stack )
00342 {
00343 if( stack->top == STACK_IS_EMPTY ){
00344 fprintf( TFile, "stack is empty\n" );
00345 return;
00346
00347 } else if( stack->top == STACK_IS_WILD ){
00348 fprintf( TFile, "stack is uninitialized\n" );
00349 return;
00350 }
00351
00352 fprintf( TFile, "x87 stack [" );
00353
00354 #if 0
00355 REGISTER reg;
00356
00357 FOR_ALL_REGISTER_SET_members( stack->reg_set, reg ){
00358 fprintf( TFile, " %s ", REGISTER_name(ISA_REGISTER_CLASS_x87,reg) );
00359 }
00360 #endif
00361
00362 for( int i = 0; i <= stack->top; i++ ){
00363 fprintf( TFile, " %s",
00364 REGISTER_name( ISA_REGISTER_CLASS_x87,stack->reg[i] ) );
00365 }
00366
00367 fprintf( TFile, " <- TOP\n" );
00368 }
00369
00370
00371
00372
00373
00374 static void Expand_Fxch( Stack* stack, OP* op, TN* dest )
00375 {
00376 Is_True(TN_register_class(dest) == ISA_REGISTER_CLASS_x87,
00377 ("Expand_Fxch: invalid register class"));
00378
00379 const int st_idx = Get_Stack_Index( stack, TN_register(dest) );
00380 FmtAssert( st_idx >= 0, ("NYI") );
00381
00382 if( st_idx == stack->top )
00383 return;
00384
00385 const REGISTER reg = stack->reg[stack->top];
00386 stack->reg[stack->top] = stack->reg[st_idx];
00387 stack->reg[st_idx] = reg;
00388
00389
00390
00391
00392
00393 for( OP* prev = OP_prev(op); prev != NULL; prev = OP_prev(prev) ){
00394 if( !OP_refs_x87(prev) )
00395 continue;
00396
00397
00398
00399
00400 if( OP_copy(prev) ){
00401 TN* opnd = OP_opnd( prev, 0 );
00402 TN* result = OP_result( prev, 0 );
00403 if( TN_register(result) == stack->reg[st_idx] &&
00404 TN_register(opnd) == stack->reg[stack->top] )
00405 return;
00406 }
00407
00408
00409
00410 break;
00411 }
00412
00413 OP* fxch_op = Mk_OP( TOP_fxch, dest );
00414 BB_Insert_Op_Before( OP_bb(op), op, fxch_op );
00415
00416 Create_OP_stinfo( fxch_op );
00417 Alloc_Stack_Reg( stack, fxch_op, 0, st_idx );
00418
00419 if( trace )
00420 Print_Stack( stack );
00421 }
00422
00423
00424
00425
00426
00427 static void Pop_Stack( Stack* stack, int st_idx, OP* point, bool before_point )
00428 {
00429 const REGISTER reg = stack->reg[st_idx];
00430
00431
00432
00433
00434 TN* opnd = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00435 Set_TN_register( opnd, reg );
00436
00437 OP* pop_op = Mk_OP( TOP_fstp, opnd );
00438 if( before_point )
00439 BB_Insert_Op_Before( OP_bb(point), point, pop_op );
00440 else
00441 BB_Insert_Op_After( OP_bb(point), point, pop_op );
00442
00443 Create_OP_stinfo( pop_op );
00444 Alloc_Stack_Reg( stack, pop_op, 0, st_idx );
00445
00446 stack->reg[st_idx] = stack->reg[stack->top];
00447 stack->top--;
00448 }
00449
00450
00451
00452
00453
00454 static void Pop_Stack_Reg( Stack* stack, int stack_idx, BB* bb )
00455 {
00456 const REGISTER reg = stack->reg[stack_idx];
00457
00458
00459
00460
00461 TN* opnd = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00462 Set_TN_register( opnd, reg );
00463 OP* pop_op = Mk_OP( TOP_fstp, opnd );
00464 BB_Append_Op( bb, pop_op );
00465
00466 Create_OP_stinfo( pop_op );
00467 Alloc_Stack_Reg( stack, pop_op, 0, stack_idx );
00468
00469 stack->reg[stack_idx] = stack->reg[stack->top];
00470 stack->top--;
00471
00472 return;
00473 }
00474
00475
00476 static bool Stacks_Are_Equivalent( Stack* s1, Stack* s2 )
00477 {
00478 if( s1->top != s2->top )
00479 return false;
00480
00481 for( int i = 0; i < s1->top; i++ ){
00482 if( s1->reg[i] != s2->reg[i] )
00483 return false;
00484 }
00485
00486 return true;
00487 }
00488
00489
00490
00491
00492 static void Swap( int to, int from, BB* bb, Stack* stack )
00493 {
00494
00495 if( stack->top != from ){
00496 const REGISTER reg = stack->reg[stack->top];
00497 stack->reg[stack->top] = stack->reg[from];
00498 stack->reg[from] = reg;
00499
00500 TN* opnd = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00501 Set_TN_register( opnd, stack->reg[stack->top] );
00502 OP* fxch_op = Mk_OP( TOP_fxch, opnd );
00503 BB_Append_Op( bb, fxch_op );
00504
00505 Create_OP_stinfo( fxch_op );
00506 Alloc_Stack_Reg( stack, fxch_op, 0, from );
00507 }
00508
00509
00510
00511 if( stack->top != to ){
00512 const REGISTER reg = stack->reg[stack->top];
00513 stack->reg[stack->top] = stack->reg[to];
00514 stack->reg[to] = reg;
00515
00516 TN* opnd = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00517 Set_TN_register( opnd, stack->reg[stack->top] );
00518 OP* fxch_op = Mk_OP( TOP_fxch, opnd );
00519 BB_Append_Op( bb, fxch_op );
00520
00521 Create_OP_stinfo( fxch_op );
00522 Alloc_Stack_Reg( stack, fxch_op, 0, to );
00523 }
00524 }
00525
00526
00527
00528
00529 static BB* Insert_Compensate_BB( BB* from, BB* to )
00530 {
00531 FmtAssert( BB_in_succs( from, to ), ("NYI") );
00532
00533 BB* prev = BB_prev( to );
00534 const bool add_goto =
00535 (prev != from) && ( BB_Fall_Thru_Successor(prev) == to );
00536 BB* new_bb = Gen_And_Insert_BB_Before( to );
00537
00538 new_bbs++;
00539
00540 if( trace ){
00541 fprintf( TFile, "new bb:%d is created for edge %d -> %d\n",
00542 BB_id(new_bb), BB_id(from), BB_id(to) );
00543 }
00544
00545 BB_MAP_Set( BBs_Map, new_bb, BB_OP_MAP_Create( new_bb, pu_mem_pool ) );
00546 BB_MAP32_Set( dfs_map, new_bb, BB_MAP32_Get(dfs_map,from) );
00547
00548 BB_freq( new_bb ) = BB_freq( to );
00549 if( !BB_Retarget_Branch( from, to, new_bb ) )
00550 Change_Succ( from, to, new_bb );
00551 Link_Pred_Succ_with_Prob( new_bb, to, 1.0F );
00552
00553 if( add_goto ){
00554 OP* last = BB_last_op( prev );
00555 if( last != NULL && OP_cond( last ) ){
00556
00557 BB* ft_bb = Gen_And_Insert_BB_After( prev );
00558
00559 BB_MAP_Set( BBs_Map, ft_bb, BB_OP_MAP_Create( ft_bb, pu_mem_pool ) );
00560 BB_MAP32_Set( dfs_map, ft_bb, BB_MAP32_Get(dfs_map,prev) );
00561 new_bbs++;
00562
00563 if( trace ){
00564 fprintf( TFile, "new bb:%d is created for edge %d -> %d\n",
00565 BB_id(ft_bb), BB_id(prev), BB_id(to) );
00566 }
00567
00568
00569 Stack* ft_bb_stack = (Stack*)MEM_POOL_Alloc( &local_mem_pool,
00570 sizeof(ft_bb_stack[0]) );
00571 const Stack* prev_stack = Get_Stack_Info( prev );
00572 *ft_bb_stack = *prev_stack;
00573 ft_bb_stack->stack_in = NULL;
00574 BB_MAP_Set( bb_stack_info_map, ft_bb, ft_bb_stack );
00575
00576 BB_freq( ft_bb ) == BB_freq( to );
00577 if( !BB_Retarget_Branch( prev, to, ft_bb ) )
00578 Change_Succ( prev, to, ft_bb );
00579
00580
00581 Add_Goto( ft_bb, to );
00582
00583 } else {
00584 Add_Goto( prev, to );
00585 }
00586 }
00587
00588 return new_bb;
00589 }
00590
00591
00592
00593
00594 inline static bool Is_Back_Edge( BB* pred, BB* succ )
00595 {
00596 FmtAssert( BB_MAP32_Get( dfs_map, pred ) > 0, ("Invalid dfs number.") );
00597 FmtAssert( BB_MAP32_Get( dfs_map, succ ) > 0, ("Invalid dfs number.") );
00598
00599 return ( BB_MAP32_Get( dfs_map, pred ) >= BB_MAP32_Get( dfs_map, succ ) );
00600 }
00601
00602
00603
00604
00605
00606 static bool Compensate_Stack( BB* pred, BB* bb, bool is_back_edge )
00607 {
00608 Stack* tgt_stack = Get_Stack_Info( bb );
00609 Stack* src_stack = Get_Stack_Info( pred );
00610
00611 if( is_back_edge ){
00612 tgt_stack = tgt_stack->stack_in;
00613 }
00614
00615 FmtAssert( tgt_stack->top != STACK_IS_WILD, ("NYI") );
00616 FmtAssert( src_stack->top != STACK_IS_WILD, ("NYI") );
00617
00618
00619 if( Stacks_Are_Equivalent( tgt_stack, src_stack ) )
00620 return false;
00621
00622 FmtAssert( REGISTER_SET_ContainsP( src_stack->live_out, tgt_stack->live_in ),
00623 ("NYI") );
00624
00625
00626 BB* new_bb = Insert_Compensate_BB( pred, bb );
00627
00628
00629
00630 Stack stack = *src_stack;
00631
00632
00633
00634 for( int i = 0; i <= stack.top; i++ ){
00635 const REGISTER reg = stack.reg[i];
00636 if( !REGISTER_SET_MemberP( tgt_stack->live_in, reg ) ){
00637 Pop_Stack_Reg( &stack, i, new_bb );
00638 i--;
00639 }
00640 }
00641
00642 FmtAssert( stack.top == tgt_stack->top, ("NYI") );
00643
00644
00645 for( int i = 0; i <= stack.top; i++ ){
00646 if( stack.reg[i] == tgt_stack->reg[i] )
00647 continue;
00648
00649 int j = i + 1;
00650 for( ; stack.reg[j] != tgt_stack->reg[i]; j++ )
00651 ;
00652
00653 Swap( i, j, new_bb, &stack );
00654 }
00655
00656
00657 Stack* new_bb_stack = (Stack*)MEM_POOL_Alloc( &local_mem_pool,
00658 sizeof(new_bb_stack[0]) );
00659 *new_bb_stack = *tgt_stack;
00660 BB_MAP_Set( bb_stack_info_map, new_bb, new_bb_stack );
00661
00662 return true;
00663 }
00664
00665
00666
00667
00668 static void Adjust_Input_Stack( BB* bb, bool consider_back_edge )
00669 {
00670 BBLIST* bblst = BB_preds( bb );
00671
00672 while( bblst != NULL ){
00673 BB* pbb = BBLIST_item( bblst );
00674
00675 if( BB_NOT_REACHABLE( pbb ) ){
00676 bblst = BBLIST_next( bblst );
00677 continue;
00678 }
00679
00680 const bool is_back_edge = Is_Back_Edge( pbb, bb );
00681
00682 if( is_back_edge &&
00683 consider_back_edge &&
00684 !VECTOR_Member_Element( bbs_vector, pbb ) ){
00685
00686 Stack* pbb_stack = Get_Stack_Info( pbb );
00687
00688 if( pbb_stack->top == STACK_IS_WILD ){
00689
00690
00691
00692
00693
00694 BB* grand_pa = BB_Unique_Predecessor( pbb );
00695 const Stack* grand_pa_stack = Get_Stack_Info( grand_pa );
00696
00697 FmtAssert( grand_pa_stack->top != STACK_IS_WILD, ("NYI") );
00698
00699 pbb_stack->top = grand_pa_stack->top;
00700 for( int i = 0; i <= grand_pa_stack->top; i++ )
00701 pbb_stack->reg[i] = grand_pa_stack->reg[i];
00702 }
00703 }
00704
00705 if( ( is_back_edge == consider_back_edge ) &&
00706 Compensate_Stack( pbb, bb, is_back_edge ) ){
00707 bblst = BB_preds( bb );
00708
00709 } else {
00710 bblst = BBLIST_next( bblst );
00711 }
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720
00721 static void Repair_Entry_BB( BB* bb )
00722 {
00723 Stack* stack = Get_Stack_Info( bb );
00724 if( REGISTER_SET_EmptyP( stack->live_in ) )
00725 return;
00726
00727 REGISTER reg;
00728
00729 FOR_ALL_REGISTER_SET_members( stack->live_in, reg ){
00730 if( Get_Stack_Index( stack, reg ) < 0 ){
00731 DevWarn( "Repair_Entry_BB: pseudo load for ST(%d) is introduced.", reg-1 );
00732
00733 TN* dest = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00734 Set_TN_register( dest, reg );
00735
00736 OP* load_op = Mk_OP( TOP_fldz, dest );
00737 BB_Prepend_Op( bb, load_op );
00738
00739 stack->live_in = REGISTER_SET_Difference1( stack->live_in, reg );
00740 }
00741 }
00742 }
00743
00744
00745 static void Repair_Call_BB( BB* bb )
00746 {
00747 Stack* stack = Get_Stack_Info( bb );
00748 if( REGISTER_SET_EmptyP( stack->live_out ) )
00749 return;
00750
00751 REGISTER_SET reg_set = REGISTER_SET_EMPTY_SET;
00752 REGISTER_SET bb_live_out = REGISTER_SET_EMPTY_SET;
00753 REGISTER reg;
00754
00755
00756
00757 const ANNOTATION* ant = ANNOT_Get( BB_annotations(bb), ANNOT_CALLINFO );
00758 const CALLINFO* call_info = ANNOT_callinfo(ant);
00759 const ST* call_st = CALLINFO_call_st(call_info);
00760 const WN* call_wn = CALLINFO_call_wn(call_info);
00761 const TY_IDX call_ty = call_st != NULL ? ST_pu_type(call_st) : WN_ty(call_wn);
00762 const RETURN_INFO return_info = Get_Return_Info( TY_ret_type(call_ty),
00763 No_Simulated,
00764 call_st ? PU_ff2c_abi(Pu_Table[ST_pu(call_st)]) : FALSE);
00765
00766 for( int i = 0; i < RETURN_INFO_count(return_info); i++ ){
00767 const TYPE_ID type = RETURN_INFO_mtype( return_info, i );
00768 if( MTYPE_is_quad( type ) ||
00769 ( MTYPE_is_float( type ) &&
00770 Is_Target_32bit() ) ){
00771 const PREG_NUM retpreg = RETURN_INFO_preg (return_info, i);
00772 ISA_REGISTER_CLASS cl;
00773
00774 if( !CGTARG_Preg_Register_And_Class( retpreg, &cl, ®) )
00775 FmtAssert( false, ("NYI") );
00776
00777 bb_live_out = REGISTER_SET_Union1( bb_live_out, reg );
00778 }
00779 }
00780
00781 FOR_ALL_REGISTER_SET_members( stack->live_out, reg ){
00782 if( !REGISTER_SET_MemberP( bb_live_out, reg ) ){
00783 reg_set = REGISTER_SET_Union1( reg_set, reg );
00784 }
00785 }
00786
00787 if( REGISTER_SET_EmptyP( reg_set ) )
00788 return;
00789
00790
00791 BB* new_bb = Insert_Compensate_BB( bb, BB_next(bb) );
00792 Stack* new_bb_stack = (Stack*)MEM_POOL_Alloc( &local_mem_pool,
00793 sizeof(new_bb_stack[0]) );
00794 *new_bb_stack = *stack;
00795 new_bb_stack->stack_in = NULL;
00796 new_bb_stack->top = STACK_IS_EMPTY;
00797
00798 stack->live_out = bb_live_out;
00799
00800 FOR_ALL_REGISTER_SET_members( stack->live_out, reg ){
00801 new_bb_stack->reg[++new_bb_stack->top] = reg;
00802 }
00803
00804 FOR_ALL_REGISTER_SET_members( reg_set, reg ){
00805 DevWarn( "Repair_Call_BB: pseudo load for ST(%d) is introduced.", reg-1 );
00806
00807 TN* dest = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
00808 Set_TN_register( dest, reg );
00809
00810 OP* load_op = Mk_OP( TOP_fldz, dest );
00811 BB_Append_Op( new_bb, load_op );
00812
00813 new_bb_stack->reg[++new_bb_stack->top] = reg;
00814 }
00815
00816 new_bb_stack->live_in = stack->live_out;
00817
00818 BB_MAP_Set( bb_stack_info_map, new_bb, new_bb_stack );
00819 }
00820
00821
00822
00823
00824 static void Initialize_Stack( BB* bb )
00825 {
00826
00827
00828
00829
00830
00831
00832 {
00833 if( BB_preds( bb ) == NULL )
00834 Repair_Entry_BB( bb );
00835
00836 if( BB_call( bb ) )
00837 Repair_Call_BB( bb );
00838 }
00839
00840 Stack* tgt_stack = Get_Stack_Info( bb );
00841
00842 if( tgt_stack->top != STACK_IS_WILD ){
00843 return;
00844 }
00845
00846 BBLIST* bblst = NULL;
00847 BB* pred = NULL;
00848 float prob = 0.0;
00849
00850 if( trace ){
00851 FOR_ALL_BB_PREDS( bb, bblst ){
00852 BB* pbb = BBLIST_item(bblst);
00853
00854 if( BB_NOT_REACHABLE( pbb ) )
00855 continue;
00856
00857 if( Is_Back_Edge( pbb, bb ) )
00858 continue;
00859
00860 Stack* stack = Get_Stack_Info( pbb );
00861
00862 FmtAssert( stack->top != STACK_IS_WILD, ("NYI") );
00863 fprintf( TFile, "Input stack from bb:%d\n", BB_id(pbb) );
00864 Print_Stack( stack );
00865 }
00866 }
00867
00868
00869
00870
00871
00872
00873 FOR_ALL_BB_PREDS( bb, bblst ){
00874 BB* pbb = BBLIST_item(bblst);
00875
00876 if( BB_NOT_REACHABLE( pbb ) )
00877 continue;
00878
00879 if( !Is_Back_Edge( pbb, bb ) ){
00880 pred = pbb;
00881 break;
00882 }
00883 }
00884
00885 Stack* src_stack = Get_Stack_Info( pred );
00886 tgt_stack->top = STACK_IS_EMPTY;
00887
00888
00889
00890
00891 for( int i = 0; i <= src_stack->top; i++ ){
00892 const REGISTER reg = src_stack->reg[i];
00893 if( REGISTER_SET_MemberP( tgt_stack->live_in, reg ) ){
00894 tgt_stack->reg[++tgt_stack->top] = reg;
00895 }
00896 }
00897
00898 Adjust_Input_Stack( bb, false );
00899
00900 return;
00901 }
00902
00903
00904 static bool Check_Consistency( Stack* stack, REGISTER_SET set )
00905 {
00906 if( stack->top == STACK_IS_WILD )
00907 return false;
00908
00909 REGISTER reg;
00910
00911 for( int i = 0; i <= stack->top; i++ ){
00912 reg = stack->reg[i];
00913 if( !REGISTER_SET_MemberP( set, reg ) ){
00914 if( trace ){
00915 fprintf( TFile, "%s does not appear in the register set\n",
00916 REGISTER_name( ISA_REGISTER_CLASS_x87, reg ) );
00917 }
00918 return false;
00919 }
00920 }
00921
00922 FOR_ALL_REGISTER_SET_members( set, reg ){
00923 if( Get_Stack_Index( stack, reg ) < 0 ){
00924 if( trace ){
00925 fprintf( TFile, "%s does not appear in the stack\n",
00926 REGISTER_name( ISA_REGISTER_CLASS_x87, reg ) );
00927 }
00928 return false;
00929 }
00930 }
00931
00932 return true;
00933 }
00934
00935
00936
00937
00938
00939 static void Handle_Asm( Stack* stack, OP* op )
00940 {
00941
00942
00943 for( int i = 0; i < OP_opnds( op ); i++ ){
00944 TN* opnd = OP_opnd( op, i );
00945 if( !TN_is_register( opnd ) ||
00946 TN_register_class(opnd) != ISA_REGISTER_CLASS_x87 )
00947 continue;
00948
00949 int st_idx = Get_Stack_Index( stack, TN_register(opnd) );
00950 FmtAssert( st_idx >= 0, ("NYI") );
00951
00952
00953
00954
00955
00956 if( st_idx != stack->top &&
00957 OP_Defs_Reg( op, TN_register_class(opnd), TN_register(opnd) ) ){
00958 Expand_Fxch( stack, op, opnd );
00959 st_idx = stack->top;
00960 }
00961
00962 Alloc_Stack_Reg( stack, op, i, st_idx );
00963
00964 if( !OP_Defs_Reg( op, TN_register_class(opnd), TN_register(opnd) ) &&
00965 Is_Opnd_Last_Use( stack, op, opnd ) ){
00966 Pop_Stack( stack, st_idx, op, false );
00967 }
00968 }
00969
00970
00971
00972 for( int i = 0; i < OP_results( op ); i++ ){
00973 TN* result = OP_result( op, i );
00974 if( TN_register_class(result) != ISA_REGISTER_CLASS_x87 )
00975 continue;
00976
00977 int st_idx = Get_Stack_Index( stack, TN_register(result) );
00978 if( st_idx < 0 ){
00979 stack->reg[++stack->top] = TN_register( result );
00980 FmtAssert( stack->top < X87_STACK_SIZE, ("x87 stack overflows.") );
00981 st_idx = stack->top;
00982 }
00983
00984 Alloc_Stack_Reg( stack, op, -(i+1), st_idx );
00985
00986 if( Is_Result_Last_Use( stack, op, result ) ){
00987 Pop_Stack( stack, st_idx, op, false );
00988 }
00989 }
00990 }
00991
00992
00993 static void Convert_Regs( BB* bb )
00994 {
00995 Initialize_Stack( bb );
00996
00997 Stack* stack = Get_Stack_Info( bb );
00998 *stack->stack_in = *stack;
00999
01000 if( !Check_Consistency( stack, stack->live_in ) ){
01001 FmtAssert( false, ("x87 stack is inconsistent") );
01002 }
01003
01004 OP* next = NULL;
01005
01006 for( OP* op = BB_first_op(bb); op != NULL; op = next ){
01007 next = OP_next( op );
01008
01009 if( !OP_refs_x87(op) )
01010 continue;
01011
01012 if( trace ){
01013 Print_OP_No_SrcLine( op );
01014 Print_Stack( stack );
01015 }
01016
01017
01018 Create_OP_stinfo( op );
01019
01020 const TOP top = OP_code( op );
01021
01022
01023 if( top == TOP_asm ){
01024 Handle_Asm( stack, op );
01025
01026 continue;
01027 }
01028
01029
01030 if( top == TOP_fldcw || top == TOP_fnstcw ){
01031 continue;
01032 }
01033
01034
01035 if( OP_call( op ) ){
01036 FmtAssert( stack->top == STACK_IS_EMPTY, ("x87 stack is non-empty") );
01037
01038 const ANNOTATION* ant = ANNOT_Get( BB_annotations(OP_bb(op)), ANNOT_CALLINFO );
01039 const CALLINFO* call_info = ANNOT_callinfo(ant);
01040 const ST* call_st = CALLINFO_call_st(call_info);
01041 const WN* call_wn = CALLINFO_call_wn(call_info);
01042 const TY_IDX call_ty = call_st != NULL ? ST_pu_type(call_st) : WN_ty(call_wn);
01043
01044 Is_True( WHIRL_Return_Info_On, ("whirl return info is off") );
01045 const RETURN_INFO return_info = Get_Return_Info( TY_ret_type(call_ty),
01046 No_Simulated,
01047 call_st ? PU_ff2c_abi(Pu_Table[ST_pu(call_st)]) : FALSE);
01048
01049 REGISTER reg = FIRST_STACK_REG + RETURN_INFO_count(return_info) - 1;
01050
01051 for( int i = 0; i < RETURN_INFO_count(return_info); i++ ){
01052 const TYPE_ID type = RETURN_INFO_mtype( return_info, i );
01053
01054 if( MTYPE_is_quad( type ) ||
01055 ( MTYPE_is_float( type ) &&
01056 Is_Target_32bit() ) ){
01057 if( !REGISTER_SET_MemberP( stack->live_out, reg ) )
01058 stack->live_out = REGISTER_SET_Union1( stack->live_out, reg );
01059 stack->reg[++stack->top] = reg--;
01060 }
01061 }
01062
01063 FmtAssert( stack->top < X87_STACK_SIZE, ("x87 stack overflows.") );
01064
01065 continue;
01066 }
01067
01068
01069 if( OP_load( op ) ||
01070 top == TOP_fldz ){
01071 const REGISTER reg = TN_register( OP_result(op,0) );
01072 FmtAssert( Get_Stack_Index( stack, reg ) < 0, ("NYI") );
01073
01074 stack->reg[++stack->top] = reg;
01075 FmtAssert( stack->top < X87_STACK_SIZE, ("x87 stack overflows.") );
01076 Alloc_Stack_Reg( stack, op, -1, stack->top );
01077
01078 if( Is_Result_Last_Use( stack, op, OP_result(op,0) ) ){
01079 if( next == NULL )
01080 Pop_Stack( stack, stack->top, BB_last_op(bb), false );
01081 else
01082 Pop_Stack( stack, stack->top, next, true );
01083 }
01084
01085 continue;
01086 }
01087
01088
01089 if( OP_store( op ) ){
01090 const int idx = OP_find_opnd_use( op, OU_storeval );
01091 TN* opnd = OP_opnd( op, idx );
01092
01093 if( stack->reg[stack->top] != TN_register(opnd) ){
01094 Expand_Fxch( stack, op, opnd );
01095 }
01096
01097 Alloc_Stack_Reg( stack, op, idx, stack->top );
01098
01099 if( Is_Opnd_Last_Use( stack, op, opnd ) ){
01100 const REGISTER reg = TN_register( opnd );
01101 stack->top--;
01102
01103
01104 } else {
01105 const TOP new_top = Pop_Table[OP_code(op)];
01106
01107 if( new_top != TOP_UNDEFINED ){
01108 OP_Change_Opcode( op, new_top );
01109
01110 } else {
01111
01112
01113
01114
01115 if( stack->top + 1 >= X87_STACK_SIZE ){
01116
01117 TN* storeval = OP_opnd( op, OP_find_opnd_use( op, OU_storeval ) );
01118 const int base_indx = OP_find_opnd_use( op, OU_base );
01119 TN* base = ( base_indx >= 0 ) ? OP_opnd( op, base_indx ) : NULL;
01120 TN* offset = OP_opnd( op, OP_find_opnd_use( op, OU_offset ) );
01121 TN* dest = Build_TN_Like( storeval );
01122 Set_TN_register( dest, TN_register( storeval ) );
01123 OP* load_op = ( base != NULL )
01124 ? Mk_OP( TOP_fldt, dest, base, offset )
01125 : Mk_OP( TOP_fldt_n32, dest, offset );
01126
01127 BB_Insert_Op_After( bb, op, load_op );
01128 Create_OP_stinfo( load_op );
01129
01130 stack->top--;
01131 next = load_op;
01132
01133 } else {
01134
01135 OP* push_op = Mk_OP( TOP_fld, opnd );
01136 BB_Insert_Op_Before( bb, op, push_op );
01137
01138 Create_OP_stinfo( push_op );
01139 Alloc_Stack_Reg( stack, push_op, 0, stack->top );
01140 }
01141 }
01142 }
01143
01144 continue;
01145 }
01146
01147
01148 if( OP_copy( op ) ||
01149 TOP_is_move(top) ){
01150
01151 const REGISTER src_reg = TN_register( OP_opnd(op,0) );
01152 const int st_idx0 = Get_Stack_Index( stack, src_reg );
01153 Alloc_Stack_Reg( stack, op, 0, st_idx0 );
01154
01155
01156 const REGISTER reg = TN_register( OP_result(op,0) );
01157 if( reg == src_reg ){
01158 BB_Remove_Op( bb, op );
01159 continue;
01160 }
01161
01162 FmtAssert( Get_Stack_Index( stack, reg ) < 0, ("NYI") );
01163
01164 stack->reg[++stack->top] = reg;
01165 FmtAssert( stack->top < X87_STACK_SIZE, ("x87 stack overflows.") );
01166 Alloc_Stack_Reg( stack, op, -1, stack->top );
01167
01168 if( Is_Result_Last_Use( stack, op, OP_result(op,0) ) ){
01169 if( next == NULL )
01170 Pop_Stack( stack, stack->top, BB_last_op(bb), false );
01171 else
01172 Pop_Stack( stack, stack->top, next, true );
01173 }
01174
01175 if( Is_Opnd_Last_Use( stack, op, OP_opnd(op,0) ) ){
01176 if( next == NULL )
01177 Pop_Stack( stack, st_idx0, BB_last_op(bb), false );
01178 else
01179 Pop_Stack( stack, st_idx0, next, true );
01180 }
01181
01182 continue;
01183 }
01184
01185
01186 if( OP_icmp( op ) ){
01187 TN* opnd0 = OP_opnd( op, 0 );
01188 TN* opnd1 = OP_opnd( op, 1 );
01189
01190 int st_idx0 = Get_Stack_Index( stack, TN_register(opnd0) );
01191 int st_idx1 = Get_Stack_Index( stack, TN_register(opnd1) );
01192 FmtAssert( st_idx0 >= 0 && st_idx1 >= 0, ("NYI") );
01193
01194
01195 if( st_idx0 != stack->top ){
01196 Expand_Fxch( stack, op, opnd0 );
01197 st_idx0 = stack->top;
01198 st_idx1 = Get_Stack_Index( stack, TN_register(opnd1) );
01199 }
01200
01201 Alloc_Stack_Reg( stack, op, 0, st_idx0 );
01202 Alloc_Stack_Reg( stack, op, 1, st_idx1 );
01203
01204 if( Is_Opnd_Last_Use( stack, op, opnd0 ) ){
01205
01206 if( next == NULL )
01207 Pop_Stack( stack, st_idx0, BB_last_op(bb), false );
01208 else
01209 Pop_Stack( stack, st_idx0, next, true );
01210 }
01211
01212 if( Is_Opnd_Last_Use( stack, op, opnd1 ) ){
01213 st_idx1 = Get_Stack_Index( stack, TN_register(opnd1) );
01214 if( next == NULL )
01215 Pop_Stack( stack, st_idx1, BB_last_op(bb), false );
01216 else
01217 Pop_Stack( stack, st_idx1, next, true );
01218 }
01219
01220 continue;
01221 }
01222
01223
01224 if( OP_cond_move( op ) ){
01225 TN* result = OP_result( op, 0 );
01226 int st_result = Get_Stack_Index( stack, TN_register(result) );
01227 FmtAssert( st_result >= 0, ("NYI") );
01228
01229
01230 if( st_result != stack->top ){
01231 Expand_Fxch( stack, op, result );
01232 st_result = stack->top;
01233 }
01234
01235 Alloc_Stack_Reg( stack, op, -1, st_result );
01236
01237 TN* opnd0 = OP_opnd( op, 0 );
01238 int st_idx0 = Get_Stack_Index( stack, TN_register(opnd0) );
01239 Alloc_Stack_Reg( stack, op, 0, st_idx0 );
01240
01241 if( Is_Opnd_Last_Use( stack, op, opnd0 ) ){
01242 if( !TNs_Are_Equivalent( result, opnd0 ) ||
01243 Is_Result_Last_Use( stack, op, result ) )
01244 Pop_Stack( stack, st_idx0, op, false );
01245 }
01246
01247 continue;
01248 }
01249
01250
01251 if( OP_fadd( op ) ||
01252 OP_fsub( op ) ||
01253 OP_fdiv( op ) ||
01254 OP_fmul( op ) ){
01255 TN* opnd0 = OP_opnd( op, 0 );
01256 TN* opnd1 = OP_opnd( op, 1 );
01257 TN* result = OP_result( op, 0 );
01258 bool pop_stack = false;
01259
01260 int st_idx0 = Get_Stack_Index( stack, TN_register(opnd0) );
01261 int st_idx1 = Get_Stack_Index( stack, TN_register(opnd1) );
01262 FmtAssert( st_idx0 >= 0 && st_idx1 >= 0, ("NYI") );
01263
01264
01265 if( st_idx0 != stack->top &&
01266 st_idx1 != stack->top ){
01267 Expand_Fxch( stack, op, opnd0 );
01268 st_idx0 = stack->top;
01269 st_idx1 = Get_Stack_Index( stack, TN_register(opnd1) );
01270 }
01271
01272 Alloc_Stack_Reg( stack, op, 0, st_idx0 );
01273 Alloc_Stack_Reg( stack, op, 1, st_idx1 );
01274
01275 if( st_idx0 == st_idx1 ){
01276 Alloc_Stack_Reg( stack, op, -1, st_idx0 );
01277
01278 } else if( Is_Opnd_Last_Use( stack, op, opnd1 ) ){
01279 if( st_idx1 == stack->top ){
01280 Alloc_Stack_Reg( stack, op, -1, st_idx0 );
01281
01282 } else {
01283 Alloc_Stack_Reg( stack, op, -1, st_idx1 );
01284 stack->reg[st_idx1] = stack->reg[stack->top];
01285
01286
01287 if( OP_x86_style( op ) &&
01288 ( st_idx1 != st_idx0 ) ){
01289
01290 if( !TOP_is_commutative( OP_code(op) ) ){
01291 OP_Change_Opcode( op, Reverse_Table[OP_code(op)] );
01292 }
01293
01294 Alloc_Stack_Reg( stack, op, 0, st_idx1 );
01295 Alloc_Stack_Reg( stack, op, 1, st_idx0 );
01296 }
01297 }
01298
01299 pop_stack = true;
01300
01301 const TOP new_top = Pop_Table[OP_code(op)];
01302 OP_Change_Opcode( op, new_top );
01303
01304 } else if( Is_Opnd_Last_Use( stack, op, opnd0 ) ){
01305 Alloc_Stack_Reg( stack, op, -1, st_idx0 );
01306
01307 } else {
01308 Alloc_Stack_Reg( stack, op, -1, st_idx0 );
01309 }
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 if( !TOP_is_commutative( OP_code(op) ) &&
01326 OP_opnds( op ) == 2 &&
01327 Get_Stack_Index( stack, TN_register(OP_result(op,0)) ) != stack->top ){
01328 OP_Change_Opcode( op, Reverse_Table[OP_code(op)] );
01329 }
01330
01331 if( pop_stack )
01332 stack->top--;
01333
01334 continue;
01335 }
01336
01337
01338 if( top == TOP_fchs ||
01339 top == TOP_fabs ||
01340 top == TOP_frndint ||
01341 top == TOP_fsqrt ||
01342 top == TOP_fcos ||
01343 top == TOP_fsin ){
01344 TN* opnd0 = OP_opnd( op, 0 );
01345 const int st_idx0 = Get_Stack_Index( stack, TN_register(opnd0) );
01346
01347 if( st_idx0 != stack->top ){
01348 Expand_Fxch( stack, op, opnd0 );
01349 }
01350
01351
01352 Alloc_Stack_Reg( stack, op, 0, stack->top );
01353 Alloc_Stack_Reg( stack, op, -1, stack->top );
01354
01355 continue;
01356 }
01357
01358 FmtAssert( false, ("Unknown x87 operation %s", TOP_Name(OP_code(op))) );
01359 }
01360
01361
01362
01363
01364 if( BB_kind(bb) == BBKIND_RETURN &&
01365 stack->top == 1 ){
01366 OP* last = BB_last_op(bb);
01367 FmtAssert( OP_code(last) == TOP_ret, ("NYI") );
01368 TN* dest = Build_RCLASS_TN( ISA_REGISTER_CLASS_x87 );
01369 Set_TN_register( dest, FIRST_STACK_REG );
01370
01371 Expand_Fxch( stack, last, dest );
01372 }
01373
01374 if( !Check_Consistency( stack, stack->live_out ) ){
01375 FmtAssert( false, ("x87 stack is inconsistent.") );
01376 }
01377 }
01378
01379
01380 static bool PU_has_x87_op()
01381 {
01382 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next( bb ) ){
01383 for( OP* op = BB_first_op(bb); op != NULL; op = OP_next(op) ){
01384 if( OP_refs_x87( op ) )
01385 return true;
01386 }
01387 }
01388
01389 return false;
01390 }
01391
01392
01393
01394
01395 static void Register_Liveness_Analysis()
01396 {
01397 REG_LIVE_Analyze_Region();
01398
01399 const ISA_REGISTER_CLASS cl = ISA_REGISTER_CLASS_x87;
01400
01401 for( int bb_idx = 0; bb_idx < VECTOR_count(bbs_vector); bb_idx++ ){
01402 BB* bb = (BB*)VECTOR_element( bbs_vector, bb_idx );
01403 Stack* stack = Get_Stack_Info( bb );
01404
01405 for( REGISTER reg = FIRST_STACK_REG;
01406 reg <= REGISTER_CLASS_last_register(cl);
01407 reg++ ){
01408
01409 if( REG_LIVE_Into_BB( cl, reg, bb ) )
01410 stack->live_in = REGISTER_SET_Union1( stack->live_in, reg );
01411
01412
01413 if( REG_LIVE_Outof_BB( cl, reg, bb ) )
01414 stack->live_out = REGISTER_SET_Union1( stack->live_out, reg );
01415 }
01416
01417 if( trace ){
01418 REGISTER reg;
01419
01420 fprintf( TFile, "BB:%d live_in: ", BB_id(bb) );
01421 FOR_ALL_REGISTER_SET_members( stack->live_in, reg ){
01422 fprintf( TFile, " %s", REGISTER_name( cl, reg ) );
01423 }
01424 fprintf( TFile, "\n" );
01425
01426 fprintf( TFile, "BB:%d live_out: ", BB_id(bb) );
01427 FOR_ALL_REGISTER_SET_members( stack->live_out, reg ){
01428 fprintf( TFile, " %s", REGISTER_name( cl, reg ) );
01429 }
01430 fprintf( TFile, "\n" );
01431 }
01432 }
01433
01434 REG_LIVE_Finish();
01435 }
01436
01437
01438
01439
01440
01441 static int dfs( BB* bb, int max_id, VECTOR vector )
01442 {
01443 Is_True( BB_MAP32_Get(dfs_map, bb) == 0,
01444 ("dfs visited BB:%d twice", BB_id(bb)));
01445
01446 BB_MAP32_Set( dfs_map, bb, ++max_id );
01447
01448
01449
01450 BBLIST* succs = NULL;
01451
01452 FOR_ALL_BB_SUCCS( bb, succs ){
01453 BB* succ = BBLIST_item(succs);
01454 if( BB_MAP32_Get(dfs_map, succ) == 0 )
01455 max_id = dfs( succ, max_id, vector );
01456 }
01457
01458 VECTOR_Add_Element( vector, bb );
01459
01460 return max_id;
01461 }
01462
01463
01464 static void Create_bbs_vector()
01465 {
01466 bbs_vector = VECTOR_Init( PU_BB_Count, &local_mem_pool );
01467
01468
01469 BB_LIST* Entry = NULL;
01470
01471 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next( bb ) ){
01472 if( BB_preds(bb) == NULL )
01473 Entry = BB_LIST_Push( bb, Entry, &local_mem_pool );
01474 }
01475
01476
01477
01478
01479
01480
01481 int max_id = 0;
01482
01483 for( BB_LIST* entries = Entry; entries != NULL; entries = BB_LIST_rest(entries) ){
01484 max_id = dfs( BB_LIST_first(entries), max_id, bbs_vector );
01485 }
01486
01487 VECTOR_count( bbs_vector ) = max_id;
01488
01489
01490
01491 int from = 0;
01492 int to = VECTOR_count( bbs_vector ) - 1;
01493
01494
01495
01496
01497
01498 while( from <= to ){
01499 BB* f_b = (BB*)VECTOR_element( bbs_vector, from );
01500 BB* t_b = (BB*)VECTOR_element( bbs_vector, to );
01501
01502 VECTOR_element( bbs_vector, from ) = t_b;
01503 VECTOR_element( bbs_vector, to ) = f_b;
01504
01505 BB_MAP32_Set( dfs_map, t_b, from+1 );
01506 BB_MAP32_Set( dfs_map, f_b, to+1 );
01507
01508 from++;
01509 to--;
01510 }
01511
01512 if( trace ){
01513 fprintf( TFile, "BBs visiting order: " );
01514
01515 for( int bb_idx = 0; bb_idx < VECTOR_count(bbs_vector); bb_idx++ ){
01516 BB* bb = (BB*)VECTOR_element( bbs_vector, bb_idx );
01517 FmtAssert( bb_idx + 1 == BB_MAP32_Get(dfs_map,bb), ("NYI") );
01518 fprintf( TFile, "%d ", BB_id(bb) );
01519 }
01520
01521 fprintf( TFile, "\n" );
01522 }
01523 }
01524
01525
01526 void Convert_x87_Regs( MEM_POOL* _mem_pool )
01527 {
01528
01529 if( !PU_has_x87_op() )
01530 return;
01531
01532 const char* prev_phase = Get_Error_Phase();
01533 Set_Error_Phase( "Converting x87 stack registers" );
01534
01535 pu_mem_pool = _mem_pool;
01536
01537 MEM_POOL_Initialize( &local_mem_pool, "CG_Convert_x87_Pool", TRUE );
01538 MEM_POOL_Push( &local_mem_pool );
01539
01540
01541
01542 dfs_map = BB_MAP32_Create();
01543 Create_bbs_vector();
01544
01545
01546
01547 Init_Pop_Table();
01548 new_bbs = 0;
01549 bb_stack_info_map = BB_MAP_Create();
01550
01551 for( int bb_idx = 0; bb_idx < VECTOR_count(bbs_vector); bb_idx++ ){
01552 BB* bb = (BB*)VECTOR_element( bbs_vector, bb_idx );
01553 Stack* stack = (Stack*)MEM_POOL_Alloc( &local_mem_pool, sizeof(stack[0]) );
01554
01555 stack->top = BB_preds( bb ) == NULL ? STACK_IS_EMPTY : STACK_IS_WILD;
01556 stack->live_in = REGISTER_SET_EMPTY_SET;
01557 stack->live_out = REGISTER_SET_EMPTY_SET;
01558 for( int i = sizeof(stack->reg) / sizeof(stack->reg[0]) - 1; i >= 0; i-- ){
01559 stack->reg[i] = REGISTER_UNDEFINED;
01560 }
01561
01562 stack->stack_in = (Stack*)MEM_POOL_Alloc( &local_mem_pool, sizeof(stack[0]) );
01563 stack->stack_in->top = STACK_IS_WILD;
01564
01565 BB_MAP_Set( bb_stack_info_map, bb, stack );
01566 }
01567
01568 Register_Liveness_Analysis();
01569
01570
01571
01572 for( int bb_idx = 0; bb_idx < VECTOR_count(bbs_vector); bb_idx++ ){
01573 BB* bb = (BB*)VECTOR_element( bbs_vector, bb_idx );
01574 BB_Update_OP_Order( bb );
01575 BB_MAP_Set( BBs_Map, bb, BB_OP_MAP_Create( bb, pu_mem_pool ) );
01576
01577 Convert_Regs( bb );
01578 }
01579
01580 for( int bb_idx = 0; bb_idx < VECTOR_count(bbs_vector); bb_idx++ ){
01581 BB* bb = (BB*)VECTOR_element( bbs_vector, bb_idx );
01582 Adjust_Input_Stack( bb, true );
01583 }
01584
01585 #if 0
01586
01587
01588
01589 if( CG_opt_level > 0 && CFLOW_opt_after_cgprep && new_bbs > 5 ){
01590 CFLOW_Optimize( CFLOW_BRANCH | CFLOW_MERGE | CFLOW_FREQ_ORDER,
01591 "CFLOW (from cg_convert_x87)" );
01592 }
01593 #endif
01594
01595 BB_MAP_Delete( bb_stack_info_map );
01596 BB_MAP_Delete( dfs_map );
01597
01598 MEM_POOL_Pop( &local_mem_pool );
01599 MEM_POOL_Delete( &local_mem_pool );
01600 Set_Error_Phase( prev_phase );
01601 }