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 #define USE_STANDARD_TYPES
00042 #include <vector>
00043 #include "defs.h"
00044 #include "cg.h"
00045 #include "cg_swp.h"
00046 #include "cg_swp_bundle.h"
00047 #include "cg_swp_options.h"
00048 #include "cgprep.h"
00049 #include "errors.h"
00050 #include "tracing.h"
00051 #include "timing.h"
00052 #include "glob.h"
00053 #include "op.h"
00054 #include "bb.h"
00055 #include "cg_swp_target.h"
00056 #include "cg_dep_graph.h"
00057 #include "cg_loop.h"
00058 #include "cg_loop_mii.h"
00059 #include "cgtarget.h"
00060 #include "findloops.h"
00061 #include "ti_res_count.h"
00062 #include "config_asm.h"
00063
00064 static INT loop_index;
00065
00066
00067
00068 SWP_OPTIONS SWP_Options;
00069
00070
00071 void SWP_OPTIONS::PU_Configure()
00072 {
00073 if (Opt_Level == 0) {
00074 Sched_Direction = 2;
00075 Heuristics = 2;
00076 }
00077
00078 if (!CGTARG_Can_Predicate())
00079 Enable_While_Loop = FALSE;
00080
00081 if (!Max_Unroll_Times_Set)
00082 Max_Unroll_Times = (CG_opt_level > 2) ? 8 : 4;
00083
00084 Min_Unroll_Times = std::max(1, Min_Unroll_Times);
00085 Max_Unroll_Times = std::max(1, Max_Unroll_Times);
00086
00087 if (Min_Unroll_Times_Set)
00088 Max_Unroll_Times = Max(Max_Unroll_Times, Min_Unroll_Times);
00089
00090 if (Max_Unroll_Times_Set)
00091 Min_Unroll_Times = Min(Min_Unroll_Times, Max_Unroll_Times);
00092
00093 if (!Implicit_Prefetch_Set) {
00094
00095
00096 #if !defined(TARG_MIPS) && !defined(TARG_SL)
00097 if (Is_Target_Itanium()) Implicit_Prefetch = FALSE;
00098 #endif
00099 }
00100 }
00101
00102
00103 void SWP_OP::Print(FILE *fp) const {
00104 if (op)
00105 #ifdef TARG_IA64
00106 fprintf(fp, "[%d] %s scale=%g cycle=%d mod=%d slot=%d trials=%d dir=%s\n",
00107 Index(), placed?"placed":"not-placed", scale, cycle, modulo_cycle,
00108 #else
00109 fprintf(fp, "[%d](%s) %s scale=%g cycle=%d mod=%d slot=%d trials=%d dir=%s\n",
00110 Index(), TOP_Name(OP_code(op)),
00111 placed?"placed":"not-placed", scale, cycle, modulo_cycle,
00112 #endif
00113 slot, trials,
00114 (direction==SWP_TOP_DOWN) ? "top_down" :
00115 ((direction==SWP_BOTTOM_UP) ? "bottom_up" : "unknown"));
00116 else
00117 fprintf(fp, "not an SWP op");
00118 }
00119
00120 void SWP_OP_vector::Verify() const {
00121 for (INT i = 0; i < size(); i++) {
00122 if (v[i].op)
00123 FmtAssert(v[i].Index() == i, ("SWP_OP_vector::Verify: v[i].Index() != i"));
00124 }
00125 }
00126
00127 void SWP_OP_vector::Print(FILE *fp) const {
00128 for (INT i = 0; i < size(); i++) {
00129 if (v[i].op)
00130 v[i].Print(fp);
00131 }
00132 fprintf(TFile, "Invariants: ");
00133 TN_SET_Print(tn_invariants, fp);
00134 fprintf(TFile, "\n");
00135 fprintf(TFile, "Non-rotating: ");
00136 TN_SET_Print(tn_non_rotating, fp);
00137 fprintf(TFile, "\n");
00138 }
00139
00140
00141 INT *swp_map_tbl;
00142 INT swp_map_tbl_max;
00143
00144 SWP_OP_vector::SWP_OP_vector(BB *body, BOOL doloop, MEM_POOL *pool)
00145 {
00146 OP *op;
00147 INT max_idx = 0;
00148 FOR_ALL_BB_OPs(body, op) {
00149 #ifdef TARG_IA64
00150 max_idx = MAX(max_idx, OP_map_idx(op));
00151 #else
00152 max_idx = std::max(max_idx, OP_map_idx(op));
00153 #endif
00154 }
00155 swp_map_tbl_max = max_idx + 1;
00156 swp_map_tbl = TYPE_MEM_POOL_ALLOC_N(INT, pool, swp_map_tbl_max);
00157 INT count = 0;
00158 FOR_ALL_BB_OPs(body, op) {
00159 swp_map_tbl[OP_map_idx(op)] = count++;
00160 }
00161 const bool trace = Get_Trace(TP_SWPIPE, 2);
00162 if (trace) {
00163 for (INT i = 0; i < swp_map_tbl_max; i++)
00164 fprintf(TFile, "swp_map[%d] = %d\n", i, swp_map_tbl[i]);
00165 }
00166
00167 INT size = count;
00168 start = size++;
00169 stop = size++;
00170 previous_trials = 0;
00171
00172 #if SWP_USE_STL
00173 v.insert(v.begin(), size, SWP_OP());
00174 #else
00175 {
00176 Is_True(size <= SWP_OPS_LIMIT,
00177 ("SWP_OP_vector: loop has too many (%d) ops.", size));
00178 v_size = size;
00179 for (INT i = 0; i < size; i++)
00180 v[i] = SWP_OP();
00181 }
00182 #endif
00183
00184 tn_non_rotating = TN_SET_Create_Empty(Last_TN + 1, pool);
00185 TN_SET *tn_defs = TN_SET_Create_Empty(Last_TN + 1, pool);
00186 TN_SET *tn_uses = TN_SET_Create_Empty(Last_TN + 1, pool);
00187 num_mops = 0;
00188 num_flops = 0;
00189 FOR_ALL_BB_OPs(body, op) {
00190 INT idx = SWP_index(op);
00191 v[idx].op = op;
00192 if (OP_memory(op))
00193 num_mops++;
00194 if (OP_flop(op))
00195 num_flops++;
00196 for (INT i = 0; i < OP_results(op); i++) {
00197 TN *tn = OP_result(op, i);
00198 if (TN_is_register(tn) && !TN_is_dedicated(tn))
00199 tn_defs = TN_SET_Union1D(tn_defs, tn, pool);
00200 if (TN_is_dedicated(tn))
00201 tn_non_rotating = TN_SET_Union1D(tn_non_rotating, tn, pool);
00202 }
00203 for (INT j = 0; j < OP_opnds(op); j++) {
00204 TN *tn = OP_opnd(op, j);
00205 if (TN_is_register(tn) && !TN_is_dedicated(tn))
00206 tn_uses = TN_SET_Union1D(tn_uses, tn, pool);
00207 if (TN_is_dedicated(tn))
00208 tn_non_rotating = TN_SET_Union1D(tn_non_rotating, tn, pool);
00209 }
00210 TN *bu_tn = Base_update_tn(op);
00211 if (bu_tn)
00212 tn_non_rotating = TN_SET_Union1D(tn_non_rotating, bu_tn, pool);
00213 }
00214
00215 tn_invariants = TN_SET_Difference(tn_uses, tn_defs, pool);
00216 tn_non_rotating = TN_SET_UnionD(tn_non_rotating, tn_invariants, pool);
00217 #ifndef TARG_IA64
00218
00219 FOR_ALL_BB_OPs(body, op) {
00220 for (INT j = 0; j < OP_opnds(op); j++) {
00221 TN *tn = OP_opnd(op, j);
00222 if( TN_is_register(tn) )
00223 tn_non_rotating = TN_SET_Union1D( tn_non_rotating, tn, pool );
00224 }
00225 }
00226 branch = 0;
00227 control_predicate_tn = NULL;
00228 #else
00229 OP *br_op = BB_branch_op(body);
00230 branch = SWP_index(br_op);
00231 control_predicate_tn = OP_has_predicate(br_op) ? OP_opnd(br_op, OP_PREDICATE_OPND) : NULL;
00232 #endif
00233 is_doloop = doloop;
00234 succeeded = false;
00235 loop_one_more_time = false;
00236 }
00237
00238 template <class T1>
00239 inline T1 linear_func(T1 x, double alpha, double beta)
00240 {
00241 return (T1)((double)x * beta + alpha);
00242 }
00243
00244 void SWP_Show_Statistics(const SWP_OP_vector& swp_op_vector, BB *body)
00245 {
00246 INT nops = 0;
00247 INT trials = 0;
00248 for (INT i = 0; i < swp_op_vector.size(); i++) {
00249 if (swp_op_vector[i].op) {
00250 nops++;
00251 trials += swp_op_vector[i].trials;
00252 }
00253 }
00254 const char *banner = "<swps>";
00255 INT ii = swp_op_vector.ii;
00256 fprintf(TFile, "%s SWP for PU %s BB %d: %s\n", banner,
00257 Cur_PU_Name ? Cur_PU_Name : "noname", BB_id(body),
00258 (ii == 0) ? "failed" :
00259 ((ii == CG_LOOP_min_ii) ? "optimal" : "non-optimal"));
00260 fprintf(TFile, "%s min II: %d\n", banner, swp_op_vector.min_ii);
00261 fprintf(TFile, "%s ResMII: %d\n", banner, swp_op_vector.res_min_ii);
00262 fprintf(TFile, "%s RecMII: %d\n", banner, swp_op_vector.rec_min_ii);
00263 fprintf(TFile, "%s min SL: %d\n", banner, swp_op_vector.min_sl);
00264 fprintf(TFile, "%s found II: %d\n", banner, swp_op_vector.ii);
00265 fprintf(TFile, "%s found SL: %d\n", banner, swp_op_vector.sl);
00266 fprintf(TFile, "%s found SC: %d\n", banner, swp_op_vector.sc);
00267 fprintf(TFile, "%s # ops: %d\n", banner, nops);
00268 fprintf(TFile, "%s # trials: %d\n", banner, trials);
00269 fprintf(TFile, "%s # total trials: %d\n", banner, trials + swp_op_vector.previous_trials);
00270 fprintf(TFile, "%s prep time: %g\n", banner, swp_op_vector.prep_time);
00271 fprintf(TFile, "%s sched time: %g\n", banner, swp_op_vector.sched_time);
00272 fprintf(TFile, "%s reg alloc time: %g\n", banner, swp_op_vector.reg_alloc_time);
00273 fprintf(TFile, "%s code gen time: %g\n", banner, swp_op_vector.code_gen_time);
00274 }
00275
00276
00277 BOOL SWP_Failure(BB *body, SWP_RETURN_CODE code)
00278 {
00279
00280 ROTATING_KERNEL_INFO *info = TYPE_PU_ALLOC(ROTATING_KERNEL_INFO);
00281 bzero(info, sizeof(ROTATING_KERNEL_INFO));
00282 ROTATING_KERNEL_INFO_succeeded(info) = FALSE;
00283 ROTATING_KERNEL_INFO_failure_code(info) = code;
00284 BB_Add_Annotation(body, ANNOT_ROTATING_KERNEL, (void *)info);
00285 Reset_BB_rotating_kernel(body);
00286 return FALSE;
00287 }
00288
00289
00290
00291
00292 SWP_RETURN_CODE Detect_SWP_Constraints(CG_LOOP &cl, bool trace)
00293 {
00294 if (SWP_Options.Prep_Only)
00295 return SWP_PREP_ONLY;
00296
00297 LOOP_DESCR *loop = cl.Loop();
00298 BB *body = LOOP_DESCR_loophead(loop);
00299 OP *op;
00300 INT op_count = 0;
00301 INT total_op_count = 0;
00302 FOR_ALL_BB_OPs(body, op) {
00303 if (!OP_br(op) && !OP_dummy(op))
00304 op_count++;
00305 total_op_count++;
00306
00307 if (OP_code(op) == TOP_asm) {
00308 if (trace)
00309 fprintf(TFile, "SWP: skip optimization due to TOP_asm.\n");
00310 return SWP_ASM;
00311 }
00312
00313 if (SWP_Options.Enable_Workaround) {
00314 #ifdef TARG_IA64
00315 if (OP_code(op) == TOP_setf_sig) {
00316 DevWarn("SWP: skip optimization due to simulation of frcpa");
00317 if (trace)
00318 fprintf(TFile, "SWP: skip optimization due to simulation of frcpa.\n");
00319 return SWP_WORKAROUND;
00320 }
00321 #endif
00322 }
00323
00324 TN *found_ded_tn = NULL;
00325 for (INT i = 0; i < OP_results(op); i++) {
00326 TN *tn = OP_result(op, i);
00327 if (TN_is_dedicated(tn) &&
00328 !TN_is_const_reg(tn) &&
00329 REGISTER_Is_Rotating(TN_register_class(tn), TN_register(tn))) {
00330 found_ded_tn = tn;
00331 break;
00332 }
00333 }
00334 for (INT j = 0; j < OP_opnds(op); j++) {
00335 TN *tn = OP_opnd(op, j);
00336 if (TN_is_dedicated(tn) &&
00337 !TN_is_const_reg(tn) &&
00338 REGISTER_Is_Rotating(TN_register_class(tn), TN_register(tn))) {
00339 found_ded_tn = tn;
00340 break;
00341 }
00342 }
00343 if (found_ded_tn) {
00344 if (trace)
00345 fprintf(TFile, "SWP: skip optimization due to rotating dedicated TN%d.\n",
00346 TN_number(found_ded_tn));
00347 return SWP_DEDICATED_ROT_REG;
00348 }
00349 }
00350
00351 if (op_count == 0)
00352 return SWP_LOOP_EMPTY;
00353
00354 if (total_op_count + SWP_OPS_OVERHEAD > SWP_Options.OPS_Limit)
00355 return SWP_LOOP_LIMIT;
00356
00357 #ifdef TARG_IA64
00358
00359 if (CG_PU_Has_Feedback)
00360 {
00361 BBLIST *bb_succs = BB_succs(body);
00362 if (BBlist_Len(bb_succs) > 1 && BB_freq_fb_based(body)) {
00363 BBLIST *succ;
00364 FOR_ALL_BBLIST_ITEMS(bb_succs,succ) {
00365 if (BB_id(body) == BB_id(BBLIST_item(succ))) {
00366 if ((BBLIST_prob(succ) >= 0 && BBLIST_prob(succ) <= 1.0) &&
00367 (BBLIST_prob(succ) <= SWP_Options.FB_Prob1/100.0 ||
00368 BBLIST_prob(succ) <= SWP_Options.FB_Prob2/100.0 &&
00369 BB_freq(body) < SWP_Options.FB_Freq && BB_freq(body) > 0)) {
00370 if (trace) {
00371 fprintf(TFile, "SWP: skip optimization due to feedback low trip count.\n");
00372 }
00373 return SWP_LOW_TRIP_COUNT;
00374 }
00375 }
00376 }
00377 }
00378 }
00379 #endif
00380
00381 return SWP_OK;
00382 }
00383
00384
00385
00386 static void
00387 Prune_Regout_Deps(BB *body, TN_SET *non_rotating)
00388 {
00389 vector<ARC*> arcs_to_delete;
00390 OP *op;
00391 FOR_ALL_BB_OPs(body, op) {
00392 if (_CG_DEP_op_info(op)) {
00393 for (ARC_LIST *arcs = OP_succs(op); arcs; arcs = ARC_LIST_rest(arcs)) {
00394 ARC *arc = ARC_LIST_first(arcs);
00395
00396 if (ARC_kind(arc) == CG_DEP_REGOUT && ARC_omega(arc) > 0) {
00397
00398 bool redundant = true;
00399 for (INT i = 0; i < OP_results(op); i++) {
00400 TN *tn = OP_result(op,i);
00401 if (!TN_is_register(tn) ||
00402 TN_is_dedicated(tn) ||
00403 TN_SET_MemberP(non_rotating, tn)) {
00404 redundant = false;
00405 break;
00406 }
00407 }
00408 if (redundant) {
00409 arcs_to_delete.push_back(arc);
00410 }
00411 }
00412 }
00413 }
00414 }
00415 for (size_t i = 0; i < arcs_to_delete.size(); i++) {
00416 CG_DEP_Detach_Arc(arcs_to_delete[i]);
00417 }
00418 }
00419
00420
00421 static BOOL Is_Loop_Skipped(void)
00422
00423
00424
00425
00426
00427 {
00428 const BOOL skip_it = ( loop_index < CG_local_skip_before
00429 || loop_index > CG_local_skip_after
00430 || loop_index == CG_local_skip_equal);
00431
00432 if (CG_skip_local_swp) {
00433 DevWarn("%s swp for loop: index=%d",
00434 skip_it ? "Skipping" : "Attempting",
00435 loop_index);
00436 }
00437
00438 ++loop_index;
00439
00440 return skip_it;
00441 }
00442
00443
00444 BOOL Perform_SWP(CG_LOOP& cl, SWP_FIXUP_VECTOR& fixup, bool is_doloop)
00445 {
00446 Set_Error_Phase("Software Pipelining");
00447 LOOP_DESCR *loop = cl.Loop();
00448 BB *body = LOOP_DESCR_loophead(loop);
00449 BB *head = CG_LOOP_prolog;
00450 BB *tail = CG_LOOP_epilog;
00451 Is_True(BB_SET_Size(LOOP_DESCR_bbset(loop)) == 1,("can't SWP multi-bb loops."));
00452
00453 const bool trace = Get_Trace(TP_SWPIPE, 2);
00454 const bool trace_details = Get_Trace(TP_SWPIPE, 4);
00455 const bool trace_bundling = Get_Trace(TP_SWPIPE, 0x1000);
00456 const bool show_result = Get_Trace(TP_SWPIPE, 1);
00457
00458 if (CG_skip_local_swp && Is_Loop_Skipped()) return FALSE;
00459
00460 SWP_RETURN_CODE code = Detect_SWP_Constraints(cl, trace);
00461 if (code != SWP_OK)
00462 return SWP_Failure(body, code);
00463
00464 if (trace)
00465 CG_LOOP_Trace_Loop(loop, "**** Before SWP ****");
00466
00467
00468 double max_ii_alpha = SWP_Options.Max_II_Alpha;
00469 double max_ii_beta = SWP_Options.Max_II_Beta;
00470 double ii_incr_alpha = SWP_Options.II_Incr_Alpha;
00471 #ifdef TARG_IA64
00472 double ii_incr_beta = 1.0 + (SWP_Options.II_Incr_Beta - 1.0) / MAX(1,SWP_Options.Opt_Level);
00473 INT sched_budget = SWP_Options.Budget * MAX(1,SWP_Options.Opt_Level);
00474 #else
00475 double ii_incr_beta = 1.0 + (SWP_Options.II_Incr_Beta - 1.0) /
00476 std::max(1,SWP_Options.Opt_Level);
00477 INT sched_budget = SWP_Options.Budget * std::max(1,SWP_Options.Opt_Level);
00478 #endif
00479
00480 {
00481 Start_Timer(T_SWpipe_CU);
00482 double time0 = Get_User_Time(T_SWpipe_CU);
00483
00484 CXX_MEM_POOL swp_local_pool("swp pool", FALSE);
00485 SWP_OP_vector swp_op_vector(body, is_doloop, swp_local_pool());
00486
00487
00488 SWP_REG_ASSIGNMENT swp_assign;
00489
00490 #ifdef TARG_IA64
00491 if (!swp_assign.Enough_Non_Rotating_Registers(swp_op_vector.tn_non_rotating)) {
00492
00493
00494 return SWP_Failure(body, NON_ROT_REG_ALLOC_FAILED );
00495 }
00496 #endif
00497
00498 CG_LOOP_rec_min_ii = CG_LOOP_res_min_ii = CG_LOOP_min_ii = 0;
00499
00500
00501 CYCLIC_DEP_GRAPH cyclic_graph( body, swp_local_pool());
00502
00503 if (trace)
00504 CG_DEP_Trace_Graph(body);
00505
00506 #ifdef TARG_IA64
00507
00508 Prune_Regout_Deps(body, swp_op_vector.tn_non_rotating);
00509
00510 if (trace)
00511 CG_DEP_Trace_Graph(body);
00512 #endif
00513
00514 {
00515
00516 MEM_POOL_Push(&MEM_local_pool);
00517 BOOL ignore_non_def_mem_deps = FALSE;
00518 CG_LOOP_Make_Strongly_Connected_Components(body, &MEM_local_pool, ignore_non_def_mem_deps);
00519 CG_LOOP_Calculate_Min_Resource_II(body, NULL, FALSE , TRUE );
00520 CG_LOOP_Calculate_Min_Recurrence_II(body, ignore_non_def_mem_deps);
00521
00522 CG_LOOP_Clear_SCCs(loop);
00523 MEM_POOL_Pop(&MEM_local_pool);
00524 }
00525
00526 double time1 = Get_User_Time(T_SWpipe_CU);
00527
00528
00529 CG_LOOP_min_ii = std::max(CG_LOOP_min_ii, SWP_Options.Starting_II);
00530 INT max_ii = (INT)linear_func(CG_LOOP_min_ii, max_ii_alpha, max_ii_beta);
00531
00532
00533 MinDist mindist(swp_op_vector, swp_op_vector.start, swp_op_vector.stop,
00534 swp_op_vector.branch, CG_LOOP_min_ii);
00535
00536 if (mindist.Found_ii() != CG_LOOP_min_ii) {
00537 DevWarn("CG_LOOP_min_ii (%d) is different from RecMII (%d) identified by MinDist.",
00538 CG_LOOP_min_ii, mindist.Found_ii());
00539 CG_LOOP_min_ii = mindist.Found_ii();
00540 }
00541
00542 Modulo_Schedule(swp_op_vector, CG_LOOP_min_ii, max_ii, ii_incr_alpha, ii_incr_beta,
00543 sched_budget, trace, trace_details);
00544
00545 if (!swp_op_vector.succeeded)
00546 return SWP_Failure(body, MOD_SCHED_FAILED );
00547
00548
00549 if (SWP_Options.Enable_Bundling)
00550 SWP_Bundle(swp_op_vector, trace_bundling);
00551 else
00552 SWP_Dont_Bundle(swp_op_vector);
00553
00554 if (trace)
00555 swp_op_vector.Print(TFile);
00556
00557 double time2 = Get_User_Time(T_SWpipe_CU);
00558
00559 #ifdef TARG_IA64
00560
00561
00562
00563
00564
00565
00566
00567 if (!swp_assign.Allocate_Loop_Variants(swp_op_vector, head, tail)) {
00568
00569 SWP_Undo_Bundle(swp_op_vector, body);
00570 return SWP_Failure(body, REG_ALLOC_FAILED );
00571 }
00572
00573
00574
00575
00576
00577 REGISTER_Reserve_Rotating_Registers(ISA_REGISTER_CLASS_integer,
00578 swp_assign.rotating_reg_used[ISA_REGISTER_CLASS_integer]);
00579 #endif
00580
00581 double time3 = Get_User_Time(T_SWpipe_CU);
00582
00583
00584 LOOPINFO *info = LOOP_DESCR_loopinfo(loop);
00585 TN *trip_count_tn = info ? LOOPINFO_trip_count_tn(info) : NULL;
00586 SWP_Emit(swp_op_vector, swp_assign, trip_count_tn,
00587 head, body, tail,
00588 is_doloop, trace);
00589
00590 fixup.push_back( SWP_FIXUP(head, body, tail,
00591 swp_assign.control_predicate_loc) );
00592
00593 double time4 = Get_User_Time(T_SWpipe_CU);
00594
00595 if (trace)
00596 CG_LOOP_Trace_Loop(loop, "**** After SWP ****");
00597
00598
00599 swp_op_vector.prep_time = time1 - time0;
00600 swp_op_vector.sched_time = time2 - time1;
00601 swp_op_vector.reg_alloc_time = time3 - time2;
00602 swp_op_vector.code_gen_time = time4 - time3;
00603 if (show_result)
00604 SWP_Show_Statistics(swp_op_vector, body);
00605
00606 Stop_Timer(T_SWpipe_CU);
00607 }
00608
00609 return TRUE;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 void
00622 Emit_SWP_Note(BB *bb, FILE *file)
00623 {
00624 ANNOTATION *ant = ANNOT_Get(BB_annotations(bb), ANNOT_ROTATING_KERNEL);
00625 ROTATING_KERNEL_INFO *info = ANNOT_rotating_kernel(ant);
00626 char prefix[20];
00627
00628 if (ROTATING_KERNEL_INFO_succeeded(info)) {
00629 sprintf( prefix, "%s<swps> ", ASM_CMNT_LINE );
00630 fprintf(file, "%s\n", prefix);
00631 fprintf(file, "%s%3d cycles per 1 iteration in steady state\n",
00632 prefix, ROTATING_KERNEL_INFO_ii(info));
00633 fprintf(file, "%s%3d pipeline stages\n",
00634 prefix, ROTATING_KERNEL_INFO_stage_count(info));
00635 fprintf(file, "%s\n", prefix);
00636
00637 sprintf( prefix, "%s<swps> ", ASM_CMNT_LINE );
00638
00639 fprintf(file, "%smin %d cycles required by resources\n",
00640 prefix, ROTATING_KERNEL_INFO_res_min_ii(info));
00641 fprintf(file, "%smin %d cycles required by recurrences\n",
00642 prefix, ROTATING_KERNEL_INFO_rec_min_ii(info));
00643 fprintf(file, "%smin %d cycles required by resources/recurrence\n",
00644 prefix, ROTATING_KERNEL_INFO_min_ii(info));
00645 fprintf(file, "%smin %d cycles (actual %d cycles) required to schedule one iteration\n",
00646 prefix, ROTATING_KERNEL_INFO_min_sched_len(info), ROTATING_KERNEL_INFO_sched_len(info));
00647 fprintf(file, "%s\n", prefix);
00648 TI_RES_COUNT_Emit_Note(prefix, file, ROTATING_KERNEL_INFO_res_counts(info),
00649 ROTATING_KERNEL_INFO_ii(info));
00650 fprintf(file, "%s\n", prefix);
00651 } else {
00652 sprintf( prefix, "%s<swpf> ", ASM_CMNT_LINE );
00653 fprintf(file, "%s\n", prefix);
00654 const char *failure_msg;
00655 switch (ROTATING_KERNEL_INFO_failure_code(info)) {
00656 case SWP_PREP_ONLY:
00657 failure_msg = "disable by -SWP:prep_only";
00658 break;
00659 case SWP_ASM:
00660 failure_msg = "unable to swp a loop containing ASM statements";
00661 break;
00662 case SWP_WORKAROUND:
00663 failure_msg = "disable swp to workaround hardware bugs";
00664 break;
00665 case SWP_DEDICATED_ROT_REG:
00666 failure_msg = "unable to swp a loop with dedicated rotating register binding";
00667 break;
00668 case MOD_SCHED_FAILED:
00669 failure_msg = "unable to find a modulo schedule";
00670 break;
00671 case REG_ALLOC_FAILED:
00672 failure_msg = "not enough rotating register";
00673 break;
00674 case NON_ROT_REG_ALLOC_FAILED:
00675 failure_msg = "not enough non-rotating register";
00676 break;
00677 case SWP_LOOP_EMPTY:
00678 failure_msg = "loop is empty";
00679 break;
00680 case SWP_LOOP_LIMIT:
00681 failure_msg = "loop is too big";
00682 break;
00683 #ifdef TARG_IA64
00684 case SWP_LOW_TRIP_COUNT:
00685 failure_msg = "loop has low trip count";
00686 break;
00687 #endif
00688 default:
00689 Is_True(FALSE, ("unknown SWP RETURN CODE."));
00690 }
00691 fprintf(file, "%s %s\n", prefix, failure_msg);
00692 fprintf(file, "%s\n", prefix);
00693 }
00694 }