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 #if defined(BUILD_OS_DARWIN)
00041 #include <darwin_elf.h>
00042 #else
00043 #include <elf.h>
00044 #endif
00045 #include <sys/elf_whirl.h>
00046 #include <sys/types.h>
00047 #include "defs.h"
00048 #include "mtypes.h"
00049 #include "access_vector.h"
00050 #include "ipl_lno_util.h"
00051 #include "ipl_summary.h"
00052 #include "ipl_summarize.h"
00053 #include "ipa_cost_util.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062 static WN* IPL_LNO_Make_Icon(TYPE_ID wtype, INT64 i)
00063 {
00064 OPCODE intconst_opc = OPCODE_make_op(OPR_INTCONST, wtype, MTYPE_V);
00065 return WN_CreateIntconst(intconst_opc, i);
00066 }
00067
00068
00069
00070
00071
00072
00073 static TYPE_ID IPL_LNO_Do_Wtype(WN* wn)
00074 {
00075 Is_True(WN_opcode(wn) == OPC_DO_LOOP,
00076 ("IPL_LNO_Do_Wtype: requires do parameter"));
00077 Is_True(WN_start(wn) && WN_operator(WN_start(wn)) == OPR_STID,
00078 ("IPL_LNO_Do_Wtype: bad do start, op=%d", WN_opcode(WN_start(wn))));
00079 return WN_desc(WN_start(wn));
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 static INT64 Step_Size(WN* loop,
00090 INT64 newstep)
00091 {
00092 WN* step;
00093
00094 if (WN_opcode(loop) == OPC_DO_LOOP) {
00095 step = WN_step(loop);
00096 WN* index = WN_index(loop);
00097
00098 if (WN_st(step) != WN_st(index) || WN_offset(step) != WN_offset(index)) {
00099 DevWarn("Index %s/%d but assignment to %s/%d in step",
00100 ST_name(WN_st(step)), WN_offset(step),
00101 ST_name(WN_st(index)), WN_offset(index));
00102 FmtAssert(newstep == 0, ("Bug in Step_Size"));
00103 return 0;
00104 }
00105 }
00106 else {
00107 step = loop;
00108 }
00109
00110 if (WN_operator(step) != OPR_STID) {
00111 DevWarn("Step expression operator not STID: %s",
00112 OPERATOR_name(WN_operator(step)));
00113 FmtAssert(newstep == 0, ("Bug in Step_Size"));
00114 return 0;
00115 }
00116
00117 WN* kid = WN_kid0(step);
00118
00119 OPERATOR opr = WN_operator(kid);
00120 if (opr != OPR_ADD && opr != OPR_SUB) {
00121 FmtAssert(newstep == 0,
00122 ("Require ADD or SUB for step, but saw `%s'",
00123 OPERATOR_name(opr)));
00124 return 0;
00125 }
00126
00127 BOOL neg = (opr == OPR_SUB);
00128
00129 WN* ldkid = WN_kid0(kid);
00130 WN* constkid = WN_kid1(kid);
00131 INT constkidno = 1;
00132
00133 if (WN_operator(ldkid) != OPR_LDID) {
00134 if (!neg) {
00135 WN* tmp = ldkid;
00136 ldkid = constkid;
00137 constkid = tmp;
00138 constkidno = 0;
00139 }
00140 if (WN_operator(ldkid) != OPR_LDID) {
00141 FmtAssert(newstep == 0, ("Saw the add, but not of the right thing"));
00142 return 0;
00143 }
00144 }
00145
00146 if (WN_operator(constkid) != OPR_INTCONST) {
00147 if (newstep != 0) {
00148 LWN_Delete_Tree(constkid);
00149 WN_kid(kid,constkidno) = IPL_LNO_Make_Icon(IPL_LNO_Do_Wtype(loop),
00150 neg?-newstep:newstep);
00151 LWN_Set_Parent(WN_kid(kid,constkidno), kid);
00152 }
00153 return 0;
00154 }
00155 else {
00156 INT64 rval = WN_const_val(constkid);
00157 if (newstep != 0)
00158 WN_const_val(constkid) = neg ? -newstep : newstep;
00159 return neg ? -rval : rval;
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 static INT64 Step_Size(WN* loop)
00170 {
00171 return Step_Size((WN*)loop, 0);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 template <PROGRAM program>
00182 INT SUMMARIZE<program>::IPL_GEN_Value(WN* wn_value,
00183 DYN_ARRAY<SUMMARY_VALUE>* sv,
00184 DYN_ARRAY<SUMMARY_EXPR>* sx)
00185 {
00186 SUMMARY_DESC result;
00187 INT old_value_idx = _value.Lastidx();
00188 Classify_const_value(result, wn_value);
00189 switch (result.Get_type()) {
00190 case VALUE_EXPR: {
00191 INT sx_index = IPL_EX_Expr(result.Get_wn(), sv, sx);
00192 return sx_index;
00193 }
00194 case VALUE_FORMAL:
00195 case VALUE_GLOBAL:
00196 break;
00197 case VALUE_UNKNOWN:
00198 case VALUE_INT_CONST:
00199 case VALUE_TWO_CONSTS:
00200 case VALUE_CONST:
00201 case VALUE_SYMBOL:
00202 case VALUE_PHI:
00203 case VALUE_CHI:
00204 case VALUE_CALLSITE:
00205 case VALUE_NOT_CONST:
00206 return -1;
00207 }
00208 INT value_index = Process_jump_function(&result);
00209 if (value_index == -1)
00210 return -1;
00211 INT sv_index = sv->Newidx();
00212 SUMMARY_VALUE* svv = &(*sv)[sv_index];
00213 SUMMARY_VALUE* svv_new = Get_value(value_index);
00214 INT new_value_idx = _value.Lastidx();
00215 BCOPY(svv_new, svv, sizeof(SUMMARY_VALUE));
00216 if (new_value_idx > old_value_idx)
00217 _value.Decidx();
00218 INT sx_index = sx->Newidx();
00219 SUMMARY_EXPR* sxx = &(*sx)[sx_index];
00220 sxx->Clear_is_trip_count();
00221 sxx->Set_has_const_operand();
00222 sxx->Set_const_value((INT64) 0);
00223 OPERATOR opr = OPR_ADD;
00224 TYPE_ID type = MTYPE_I4;
00225 OPCODE opcode = OPCODE_make_op(opr, type, MTYPE_V);
00226 sxx->Set_opcode(opcode);
00227 sxx->Set_expr_value(0);
00228 sxx->Set_node_index(0, sv_index);
00229 sxx->Set_mtype(type);
00230 return sx_index;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 template <PROGRAM program>
00240 INT SUMMARIZE<program>::IPL_GEN_Expr(OPERATOR opr,
00241 INT exp_one,
00242 INT exp_two,
00243 DYN_ARRAY<SUMMARY_EXPR>* sx)
00244 {
00245 INT index = sx->Newidx();
00246 SUMMARY_EXPR* sxx = &(*sx)[index];
00247 sxx->Clear_is_trip_count();
00248 sxx->Clear_has_const_operand();
00249 TYPE_ID type = MTYPE_I4;
00250 OPCODE opcode = OPCODE_make_op(opr, type, MTYPE_V);
00251 sxx->Set_opcode(opcode);
00252 sxx->Set_expr_expr(0);
00253 sxx->Set_expr_expr(1);
00254 sxx->Set_node_index(0, exp_one);
00255 sxx->Set_node_index(1, exp_two);
00256 sxx->Set_mtype(type);
00257 return index;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 template <PROGRAM program>
00270 INT SUMMARIZE<program>::IPL_GEN_Const(INT value,
00271 DYN_ARRAY<SUMMARY_VALUE>* sv,
00272 DYN_ARRAY<SUMMARY_EXPR>* sx)
00273 {
00274 TYPE_ID type = MTYPE_I4;
00275 INT sv_index = IPL_EX_New_Constant(sv, value);
00276 INT sx_index = sx->Newidx();
00277 SUMMARY_EXPR* sxx = &(*sx)[sx_index];
00278 sxx->Clear_is_trip_count();
00279 sxx->Set_has_const_operand();
00280 sxx->Set_const_value((INT64) 0);
00281 OPERATOR opr = OPR_ADD;
00282 OPCODE opcode = OPCODE_make_op(opr, MTYPE_I4, MTYPE_V);
00283 sxx->Set_opcode(opcode);
00284 sxx->Set_expr_value(0);
00285 sxx->Set_node_index(0, sv_index);
00286 sxx->Set_mtype(type);
00287 return sx_index;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 template <PROGRAM program>
00301 BOOL SUMMARIZE<program>::Easy_Trip_Count(WN* wn_loop,
00302 WN** wn_addr_ub,
00303 WN** wn_addr_lb,
00304 INT* addr_intconst)
00305 {
00306 INT64 step_size = Step_Size(wn_loop);
00307 if (step_size != 1 && step_size != -1)
00308 return FALSE;
00309 WN* wn_end = WN_end(wn_loop);
00310 if (WN_operator(wn_end) != OPR_LT && WN_operator(wn_end) != OPR_GT
00311 && WN_operator(wn_end) != OPR_LE && WN_operator(wn_end) != OPR_GE)
00312 return FALSE;
00313 if (step_size == 1) {
00314 if (WN_operator(wn_end) == OPR_LT || WN_operator(wn_end) == OPR_LE) {
00315 WN* wn_index = WN_kid0(wn_end);
00316 if (WN_operator(wn_index) != OPR_LDID)
00317 return FALSE;
00318 if (SYMBOL(WN_index(wn_loop)) != SYMBOL(wn_index))
00319 return FALSE;
00320 *wn_addr_lb = WN_kid0(WN_start(wn_loop));
00321 *wn_addr_ub = WN_kid1(WN_end(wn_loop));
00322 *addr_intconst = WN_operator(wn_end) == OPR_LE ? 1 : 0;
00323 } else {
00324 WN* wn_index = WN_kid1(wn_end);
00325 if (WN_operator(wn_index) != OPR_LDID)
00326 return FALSE;
00327 if (SYMBOL(WN_index(wn_loop)) != SYMBOL(wn_index))
00328 return FALSE;
00329 *wn_addr_ub = WN_kid0(WN_start(wn_loop));
00330 *wn_addr_lb = WN_kid0(WN_end(wn_loop));
00331 *addr_intconst = WN_operator(wn_end) == OPR_GE ? 1 : 0;
00332 }
00333 } else {
00334 if (WN_operator(wn_end) == OPR_LT || WN_operator(wn_end) == OPR_LE) {
00335 WN* wn_index = WN_kid0(wn_end);
00336 if (WN_operator(wn_index) != OPR_LDID)
00337 return FALSE;
00338 if (SYMBOL(WN_index(wn_loop)) != SYMBOL(wn_index))
00339 return FALSE;
00340 *wn_addr_ub = WN_kid0(WN_start(wn_loop));
00341 *wn_addr_lb = WN_kid1(WN_end(wn_loop));
00342 *addr_intconst = WN_operator(wn_end) == OPR_LE ? 1 : 0;
00343 } else {
00344 WN* wn_index = WN_kid1(wn_end);
00345 if (WN_operator(wn_index) != OPR_LDID)
00346 return FALSE;
00347 if (SYMBOL(WN_index(wn_loop)) != SYMBOL(wn_index))
00348 return FALSE;
00349 *wn_addr_lb = WN_kid0(WN_start(wn_loop));
00350 *wn_addr_ub = WN_kid0(WN_end(wn_loop));
00351 *addr_intconst = WN_operator(wn_end) == OPR_GE ? 1 : 0;
00352 }
00353 }
00354 return TRUE;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364 template <PROGRAM program>
00365 INT SUMMARIZE<program>::IPL_EX_Expr(WN* wn_expr,
00366 DYN_ARRAY<SUMMARY_VALUE>* sv,
00367 DYN_ARRAY<SUMMARY_EXPR>* sx)
00368 {
00369 if (IPL_EXS_Too_Complicated(sv, sx, 1))
00370 return -1;
00371 switch (WN_operator(wn_expr)) {
00372 case OPR_ADD:
00373 case OPR_SUB:
00374 case OPR_MPY:
00375 case OPR_DIV: {
00376 INT expr_one = IPL_EX_Expr(WN_kid0(wn_expr), sv, sx);
00377 if (expr_one == -1)
00378 return -1;
00379 INT expr_two = IPL_EX_Expr(WN_kid1(wn_expr), sv, sx);
00380 if (expr_two == -1)
00381 return -1;
00382 INT expr_result = IPL_GEN_Expr(WN_operator(wn_expr), expr_one,
00383 expr_two, sx);
00384 return expr_result;
00385 }
00386 case OPR_NEG: {
00387 INT expr_one = IPL_GEN_Const(0, sv, sx);
00388 INT expr_two = IPL_EX_Expr(WN_kid0(wn_expr), sv, sx);
00389 if (expr_two == -1)
00390 return -1;
00391 INT expr_result = IPL_GEN_Expr(OPR_SUB, expr_one, expr_two, sx);
00392 return expr_result;
00393 }
00394 case OPR_LDID: {
00395 INT expr_value = IPL_GEN_Value(wn_expr, sv, sx);
00396 return expr_value;
00397 }
00398 case OPR_INTCONST: {
00399 INT const_value = WN_const_val(wn_expr);
00400 INT expr_value = IPL_GEN_Const(const_value, sv, sx);
00401 return expr_value;
00402 }
00403 default:
00404 return -1;
00405 }
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 template <PROGRAM program>
00416 INT SUMMARIZE<program>::IPL_EX_Trip_Count(WN* wn_loop,
00417 DYN_ARRAY<SUMMARY_VALUE>* sv,
00418 DYN_ARRAY<SUMMARY_EXPR>* sx,
00419 BOOL constant_estimate)
00420 {
00421 if (IPL_EXS_Too_Complicated(sv, sx, 1))
00422 return -1;
00423 WN* wn_ub = NULL;
00424 WN* wn_lb = NULL;
00425 INT int_const = -1;
00426 if (constant_estimate
00427 || !Easy_Trip_Count(wn_loop, &wn_ub, &wn_lb, &int_const))
00428 return IPL_GEN_Const(DEFAULT_TRIP_COUNT, sv, sx);
00429 INT expr_end = IPL_EX_Expr(wn_ub, sv, sx);
00430 if (expr_end == -1)
00431 return IPL_GEN_Const(DEFAULT_TRIP_COUNT, sv, sx);
00432 INT expr_start = IPL_EX_Expr(wn_lb, sv, sx);
00433 if (expr_start == -1)
00434 return IPL_GEN_Const(DEFAULT_TRIP_COUNT, sv, sx);
00435 INT expr_sum = IPL_GEN_Expr(OPR_SUB, expr_end, expr_start, sx);
00436 if (int_const == 0) {
00437 SUMMARY_EXPR* sxx = &(*sx)[expr_sum];
00438 sxx->Set_is_trip_count();
00439 return expr_sum;
00440 }
00441 INT expr_one = IPL_GEN_Const(1, sv, sx);
00442 INT expr_result = IPL_GEN_Expr(OPR_ADD, expr_sum, expr_one, sx);
00443 SUMMARY_EXPR* sxx = &(*sx)[expr_result];
00444 sxx->Set_is_trip_count();
00445 return expr_result;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 template <PROGRAM program>
00455 INT SUMMARIZE<program>::IPL_EX_Call(WN* wn_call,
00456 DYN_ARRAY<SUMMARY_VALUE>* sv,
00457 DYN_ARRAY<SUMMARY_EXPR>* sx)
00458 {
00459 ST_IDX st_idx = ST_st_idx(WN_st(wn_call));
00460 INT i;
00461
00462 for (i = Summary->Get_callsite_idx(); i >= 0; i--) {
00463 SUMMARY_CALLSITE* sc = Summary->Get_callsite(i);
00464 if (sc->Get_map_id() == WN_map_id(wn_call))
00465 break;
00466 }
00467
00468 FmtAssert(i >= 0, ("IPL_EX_Call: Expected to find map-id for call"));
00469 INT sv_index = sv->Newidx();
00470 SUMMARY_VALUE* svv = &(*sv)[sv_index];
00471 svv->Set_callsite();
00472 svv->Set_callsite_index(i);
00473 svv->Set_mtype(WN_rtype(wn_call));
00474 svv->Clear_is_addr_of();
00475 svv->Clear_is_trip_count();
00476 INT sx_index = sx->Newidx();
00477 SUMMARY_EXPR* sxx = &(*sx)[sx_index];
00478 sxx->Clear_is_trip_count();
00479 sxx->Set_has_const_operand();
00480 sxx->Set_const_value((INT64) 0);
00481 OPERATOR opr = OPR_ADD;
00482 TYPE_ID type = MTYPE_I4;
00483 OPCODE opcode = OPCODE_make_op(opr, type, MTYPE_V);
00484 sxx->Set_opcode(opcode);
00485 sxx->Set_expr_value(0);
00486 sxx->Set_node_index(0, sv_index);
00487 sxx->Set_mtype(type);
00488 return sx_index;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 template <PROGRAM program>
00499 INT SUMMARIZE<program>::IPL_EX_Statement(WN* wn_statement,
00500 DYN_ARRAY<SUMMARY_VALUE>* sv,
00501 DYN_ARRAY<SUMMARY_EXPR>* sx,
00502 BOOL constant_estimate)
00503 {
00504 if (IPL_EXS_Too_Complicated(sv, sx, 1))
00505 return -1;
00506 switch (WN_operator(wn_statement)) {
00507 case OPR_DO_LOOP: {
00508 INT exp_trip = IPL_EX_Trip_Count(wn_statement, sv, sx, constant_estimate);
00509 if (exp_trip == -1)
00510 return -1;
00511 INT exp_body = IPL_EX_Block(WN_do_body(wn_statement), sv, sx,
00512 constant_estimate);
00513 if (exp_body == -1)
00514 return -1;
00515 INT exp_result = IPL_GEN_Expr(OPR_MPY, exp_trip, exp_body, sx);
00516 return exp_result;
00517 }
00518 case OPR_DO_WHILE:
00519 case OPR_WHILE_DO:
00520 return IPL_EX_Block(WN_while_body(wn_statement), sv, sx,
00521 constant_estimate);
00522 case OPR_IF: {
00523 INT if_nodes = Node_Count(WN_if_test(wn_statement));
00524 INT exp_if = IPL_GEN_Const(if_nodes, sv, sx);
00525 INT exp_then = IPL_EX_Block(WN_then(wn_statement), sv, sx,
00526 constant_estimate);
00527 if (exp_then == -1)
00528 return -1;
00529 INT exp_sum_one = IPL_GEN_Expr(OPR_ADD, exp_if, exp_then, sx);
00530 INT exp_else = IPL_EX_Block(WN_else(wn_statement), sv, sx,
00531 constant_estimate);
00532 if (exp_else == -1)
00533 return -1;
00534 INT exp_sum_two = IPL_GEN_Expr(OPR_ADD, exp_sum_one, exp_else, sx);
00535 return exp_sum_two;
00536 }
00537 case OPR_REGION:
00538 return IPL_EX_Block(WN_region_body(wn_statement), sv, sx,
00539 constant_estimate);
00540 case OPR_CALL:
00541 return IPL_EX_Call(wn_statement, sv, sx);
00542 default: {
00543 INT default_nodes = Node_Count(wn_statement);
00544 INT exp_const = IPL_GEN_Const(default_nodes, sv, sx);
00545 return exp_const;
00546 }
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557 template <PROGRAM program>
00558 INT SUMMARIZE<program>::IPL_EX_Block(WN* wn_block,
00559 DYN_ARRAY<SUMMARY_VALUE>* sv,
00560 DYN_ARRAY<SUMMARY_EXPR>* sx,
00561 BOOL constant_estimate)
00562 {
00563 if (IPL_EXS_Too_Complicated(sv, sx, 1))
00564 return -1;
00565 WN* wn_first = WN_first(wn_block);
00566 if (wn_first == NULL)
00567 return IPL_GEN_Const(0, sv, sx);
00568 INT exp_one = IPL_EX_Statement(wn_first, sv, sx, constant_estimate);
00569 if (exp_one == -1)
00570 return -1;
00571 WN* wn_next = WN_next(wn_first);
00572 if (wn_next == NULL)
00573 return exp_one;
00574 INT exp_old = exp_one;
00575 for (WN* wn = wn_next; wn != NULL; wn = WN_next(wn)) {
00576 INT exp_new = IPL_EX_Statement(wn, sv, sx, constant_estimate);
00577 if (exp_new == -1)
00578 return -1;
00579 INT exp_result = IPL_GEN_Expr(OPR_ADD, exp_old, exp_new, sx);
00580 exp_old = exp_result;
00581 }
00582 return exp_old;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 template <PROGRAM program>
00594 void SUMMARIZE<program>::IPL_Execution_Cost(WN* wn_func,
00595 SUMMARY_PROCEDURE* sp,
00596 MEM_POOL* mem_pool,
00597 BOOL constant_estimate)
00598 {
00599 INT i;
00600 DYN_ARRAY<SUMMARY_VALUE>* sv
00601 = CXX_NEW(DYN_ARRAY<SUMMARY_VALUE>(mem_pool), mem_pool);
00602 DYN_ARRAY<SUMMARY_EXPR>* sx
00603 = CXX_NEW(DYN_ARRAY<SUMMARY_EXPR>(mem_pool), mem_pool);
00604 INT expr_index = IPL_EX_Block(WN_func_body(wn_func), sv, sx,
00605 constant_estimate);
00606 if (expr_index == -1)
00607 IPL_EXS_Chop_Down_Estimate(sv, sx);
00608 if (Get_Trace(TP_IPL, TT_IPL_EXCOST)) {
00609 fprintf(stdout, "BEFORE SIMPLIFICATION: \n");
00610 Print_Exprs(stdout, sv, sx);
00611 }
00612 IPL_EX_Simplify(sv, sx);
00613 if (Get_Trace(TP_IPL, TT_IPL_EXCOST)) {
00614 fprintf(stdout, "AFTER SIMPLIFICATION: \n");
00615 Print_Exprs(stdout, sv, sx);
00616 }
00617 INT value_offset = _value.Lastidx() + 1;
00618 INT expr_offset = _expr.Lastidx() + 1;
00619 IPL_EX_Add_Expr_Offsets(sx, value_offset, expr_offset);
00620 for (i = 0; i <= sv->Lastidx(); i++)
00621 _value.AddElement((*sv)[i]);
00622 for (i = 0; i <= sx->Lastidx(); i++)
00623 _expr.AddElement((*sx)[i]);
00624 INT ex_value_index = value_offset;
00625 INT ex_value_count = sv->Lastidx() + 1;
00626 INT ex_expr_index = expr_offset;
00627 INT ex_expr_count = sx->Lastidx() + 1;
00628 sp->Set_ex_value_index(ex_value_index);
00629 sp->Set_ex_value_count(ex_value_count);
00630 sp->Set_ex_expr_index(ex_expr_index);
00631 sp->Set_ex_expr_count(ex_expr_count);
00632 }
00633