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 #define __STDC_LIMIT_MACROS
00044 #include <stdint.h>
00045 #if defined(BUILD_OS_DARWIN)
00046 #include <darwin_elf.h>
00047 #else
00048 #include <elf.h>
00049 #include <sys/elf_whirl.h>
00050 #endif
00051 #include <sys/types.h>
00052 #include "defs.h"
00053 #include "mtypes.h"
00054 #include "access_vector.h"
00055 #include "ipl_lno_util.h"
00056 #include "ipl_summary.h"
00057 #include <alloca.h>
00058 #include "ipa_cost_util.h"
00059 #include "call_info.h"
00060 #include "be_util.h"
00061 #include "lwn_util.h"
00062 #include "ipa_lno_summary.h"
00063 #include "ipa_lno_read.h"
00064 #include "opt_du.h"
00065 #include "const.h"
00066
00067
00068
00069
00070
00071
00072
00073
00074 extern TYPE_ID Cast_Float_Operands(WN** wn_addr_one,
00075 WN** wn_addr_two)
00076 {
00077 WN* wn_one = *wn_addr_one;
00078 WN* wn_two = *wn_addr_two;
00079 TYPE_ID mtype_one = OPCODE_rtype(WN_opcode(wn_one));
00080 TYPE_ID mtype_two = OPCODE_rtype(WN_opcode(wn_two));
00081 TYPE_ID mtype = MTYPE_UNKNOWN;
00082 if (mtype_one < mtype_two) {
00083 OPCODE op = OPCODE_make_op(OPR_CVT, mtype_two, mtype_one);
00084 wn_one = LWN_CreateExp1(op, wn_one);
00085 mtype = mtype_two;
00086 } else if (mtype_two < mtype_one) {
00087 OPCODE op = OPCODE_make_op(OPR_CVT, mtype_one, mtype_two);
00088 wn_two = LWN_CreateExp1(op, wn_two);
00089 mtype = mtype_one;
00090 } else {
00091 mtype = mtype_one;
00092 }
00093 wn_addr_one = &wn_one;
00094 wn_addr_two = &wn_two;
00095 return mtype;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 static INT64 Simple_Cost_Value(DYN_ARRAY<SUMMARY_VALUE>* sv,
00105 INT sv_index)
00106 {
00107 SUMMARY_VALUE* svv = &(*sv)[sv_index];
00108 if (svv->Is_trip_count())
00109 return DEFAULT_TRIP_COUNT;
00110 if (svv->Is_int_const())
00111 return svv->Get_int_const_value();
00112 INT64 value = -1;
00113 if (svv->Is_const_st())
00114 if (St_Idx_Is_Intconst(svv->Get_const_st_idx(), &value))
00115 return value;
00116 FmtAssert(FALSE,
00117 ("Simple_Cost_Value: Non-const VALUE not part of trip count"));
00118 return -1;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 static INT64 Simple_Cost_Traverse(DYN_ARRAY<SUMMARY_VALUE>* sv,
00128 DYN_ARRAY<SUMMARY_EXPR>* sx,
00129 INT sx_index)
00130 {
00131 INT64 value_left = -1;
00132 INT64 value_right = -1;
00133 INT64 value_result = -1;
00134 SUMMARY_EXPR* sxx = &(*sx)[sx_index];
00135 if (sxx->Is_trip_count())
00136 return DEFAULT_TRIP_COUNT;
00137 if (sxx->Has_const_operand()) {
00138 if (sxx->Is_expr_value(0)) {
00139 INT sv_index = sxx->Get_node_index(0);
00140 value_left = Simple_Cost_Value(sv, sv_index);
00141 } else if (sxx->Is_expr_expr(0)) {
00142 INT sx_index = sxx->Get_node_index(0);
00143 value_left = Simple_Cost_Traverse(sv, sx, sx_index);
00144 }
00145 value_right = sxx->Get_const_value();
00146 } else {
00147 if (sxx->Is_expr_value(0)) {
00148 INT sv_index = sxx->Get_node_index(0);
00149 value_left = Simple_Cost_Value(sv, sv_index);
00150 } else if (sxx->Is_expr_expr(0)) {
00151 INT sx_index = sxx->Get_node_index(0);
00152 value_left = Simple_Cost_Traverse(sv, sx, sx_index);
00153 }
00154 if (sxx->Is_expr_value(0)) {
00155 INT sv_index = sxx->Get_node_index(0);
00156 value_right = Simple_Cost_Value(sv, sv_index);
00157 } else if (sxx->Is_expr_expr(0)) {
00158 INT sx_index = sxx->Get_node_index(0);
00159 value_right = Simple_Cost_Traverse(sv, sx, sx_index);
00160 }
00161 }
00162 switch (OPCODE_operator(sxx->Get_opcode())) {
00163 case OPR_ADD:
00164 value_result = value_left + value_right;
00165 break;
00166 case OPR_SUB:
00167 value_result = value_left - value_right;
00168 break;
00169 case OPR_MPY:
00170 value_result = value_left * value_right;
00171 break;
00172 case OPR_DIV:
00173 value_result = value_left / value_right;
00174 break;
00175 default:
00176 FmtAssert(FALSE,
00177 ("Simple_Cost_Traverse: Unexpected operator in SUMMARY_EXPR"));
00178 }
00179 return value_result;
00180 }
00181
00182
00183
00184
00185
00186
00187 extern INT64 Simple_Execution_Cost(WN* wn_call)
00188 {
00189 CALL_INFO* call_info = (CALL_INFO *) WN_MAP_Get(LNO_Info_Map, wn_call);
00190 DYN_ARRAY<SUMMARY_VALUE>* sv = call_info->Value();
00191 DYN_ARRAY<SUMMARY_EXPR>* sx = call_info->Expr();
00192 INT sx_index = sx->Lastidx();
00193 return Simple_Cost_Traverse(sv, sx, sx_index);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203 static BOOL Can_Evaluate_Cost(WN* wn_call)
00204 {
00205 CALL_INFO* call_info = (CALL_INFO *) WN_MAP_Get(LNO_Info_Map, wn_call);
00206 DYN_ARRAY<SUMMARY_VALUE>* sv = call_info->Value();
00207 for (INT i = 0; i <= sv->Lastidx(); i++) {
00208 SUMMARY_VALUE* svv = &(*sv)[i];
00209 if (svv->Is_formal()) {
00210 INT formal_position = svv->Get_formal_index();
00211 if (!(formal_position >= 0 && formal_position < WN_kid_count(wn_call)))
00212 return FALSE;
00213 WN* wn_parm = WN_kid(wn_call, formal_position);
00214 if (WN_operator(wn_parm) != OPR_PARM)
00215 return FALSE;
00216 WN* wn_arg = WN_kid0(wn_parm);
00217 if (!OPCODE_has_sym(WN_opcode(wn_arg)))
00218 return FALSE;
00219 }
00220 }
00221 return TRUE;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 static void Make_Def_List_For_Global(WN* wn_call,
00231 WN* wn_ldid)
00232 {
00233 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(wn_call);
00234 if (def_list == NULL)
00235 return;
00236 DEF_LIST_ITER iter(def_list);
00237 const DU_NODE* node = NULL;
00238 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00239 WN* wn_def = node->Wn();
00240 if (Aliased(Alias_Mgr, wn_def, wn_ldid) == NOT_ALIASED)
00241 continue;
00242 BOOL is_preg_def = OPCODE_has_sym(WN_opcode(wn_def))
00243 && ST_class(WN_st(wn_def)) == CLASS_PREG;
00244 BOOL is_preg_ldid = OPCODE_has_sym(WN_opcode(wn_ldid))
00245 && ST_class(WN_st(wn_ldid)) == CLASS_PREG;
00246 if (is_preg_def && !is_preg_ldid || !is_preg_def && is_preg_ldid)
00247 continue;
00248 if (is_preg_def && is_preg_ldid && WN_offset(wn_def) != WN_offset(wn_ldid))
00249 continue;
00250 Du_Mgr->Add_Def_Use(wn_def, wn_ldid);
00251 }
00252 DEF_LIST* dl_new = Du_Mgr->Ud_Get_Def(wn_ldid);
00253 if (dl_new != NULL && def_list->Incomplete())
00254 dl_new->Set_Incomplete();
00255 Update_Loop_Stmt(wn_ldid);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265 static void Find_And_Make_Alias(WN* wn_call,
00266 WN* wn_ldid)
00267 {
00268 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(wn_call);
00269 if (def_list == NULL)
00270 return;
00271 DEF_LIST_ITER iter(def_list);
00272 const DU_NODE* node = NULL;
00273 WN* wn_good_def = NULL;
00274 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00275 WN* wn_def = node->Wn();
00276 if (OPCODE_has_sym(WN_opcode(wn_def))
00277 && SYMBOL(wn_def) == SYMBOL(wn_ldid)) {
00278 wn_good_def = wn_def;
00279 break;
00280 }
00281 }
00282 if (wn_good_def == NULL)
00283 return;
00284 Copy_alias_info(Alias_Mgr, wn_good_def, wn_ldid);
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 static WN* Execution_Cost_Value(WN* wn_call,
00296 DYN_ARRAY<SUMMARY_VALUE>* sv,
00297 INT sv_index)
00298 {
00299 SUMMARY_VALUE* svv = &(*sv)[sv_index];
00300 if (svv->Is_int_const()) {
00301 INT64 const_value = svv->Get_int_const_value();
00302 float float_value = (float) const_value;
00303 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00304 } else if (svv->Is_const_st()) {
00305 ST_IDX st_idx = svv->Get_const_st_idx();
00306 TYPE_ID mtype = TY_mtype(ST_type(st_idx));
00307 if (MTYPE_is_integral(mtype)) {
00308 ST* st = &St_Table[st_idx];
00309 INT64 const_value = Targ_To_Host(STC_val(st));
00310 float float_value = (float) const_value;
00311 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00312 }
00313 WN* wn_ldid = WN_CreateLdid(OPR_LDID, Promote_Type(mtype), mtype, 0,
00314 st_idx, ST_type(st_idx));
00315 Find_And_Make_Alias(wn_call, wn_ldid);
00316 Du_Mgr->Add_Def_Use(Current_Func_Node, wn_ldid);
00317 OPCODE op_float = OPCODE_make_op(OPR_CVT, MTYPE_F8, WN_rtype(wn_ldid));
00318 WN* wn_fldid = LWN_CreateExp1(op_float, wn_ldid);
00319 return wn_fldid;
00320 } else if (svv->Is_formal()) {
00321 INT formal_position = svv->Get_formal_index();
00322 FmtAssert(formal_position >= 0 && formal_position < WN_kid_count(wn_call),
00323 ("Execution_Cost_Value: Unexpected formal position"));
00324 WN* wn_parm = WN_kid(wn_call, formal_position);
00325 FmtAssert(WN_operator(wn_parm) == OPR_PARM,
00326 ("Execution_Cost_Value: Expecting PARM node under CALL"));
00327 WN* wn_arg = WN_kid0(wn_parm);
00328 FmtAssert(OPCODE_has_sym(WN_opcode(wn_arg)),
00329 ("Execution_Cost_Value: Expecting single symbol argument"));
00330 ST_IDX st_idx = WN_st_idx(wn_arg);
00331 ST* st = &St_Table[st_idx];
00332 TYPE_ID mtype = TY_mtype(ST_type(st_idx));
00333 if (ST_class(st) == CLASS_CONST && MTYPE_is_integral(mtype)) {
00334 INT64 const_value = Targ_To_Host(STC_val(st));
00335 float float_value = (float) const_value;
00336 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00337 }
00338 WN* wn_ldid = WN_CreateLdid(OPR_LDID, Promote_Type(mtype), mtype, 0,
00339 st_idx, ST_type(st_idx));
00340 Create_alias(Alias_Mgr, wn_ldid);
00341 LWN_Copy_Def_Use_Node(wn_parm, wn_ldid, Du_Mgr);
00342 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(wn_ldid);
00343 if (def_list == NULL)
00344 Du_Mgr->Add_Def_Use(Current_Func_Node, wn_ldid);
00345 OPCODE op_float = OPCODE_make_op(OPR_CVT, MTYPE_F8, WN_rtype(wn_ldid));
00346 WN* wn_fldid = LWN_CreateExp1(op_float, wn_ldid);
00347 return wn_fldid;
00348 } else if (svv->Is_global()) {
00349 ST_IDX st_idx = svv->Get_global_st_idx();
00350 ST* st = &St_Table[st_idx];
00351 TYPE_ID mtype = TY_mtype(ST_type(st_idx));
00352 if (ST_class(st) == CLASS_CONST && MTYPE_is_integral(mtype)) {
00353 INT64 const_value = Targ_To_Host(STC_val(st));
00354 float float_value = (float) const_value;
00355 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00356 }
00357 WN* wn_ldid = WN_CreateLdid(OPR_LDID, Promote_Type(mtype), mtype, 0,
00358 st_idx, ST_type(st_idx));
00359 Create_alias(Alias_Mgr, wn_ldid);
00360 Make_Def_List_For_Global(wn_call, wn_ldid);
00361 OPCODE op_float = OPCODE_make_op(OPR_CVT, MTYPE_F8, WN_rtype(wn_ldid));
00362 WN* wn_fldid = LWN_CreateExp1(op_float, wn_ldid);
00363 return wn_fldid;
00364 } else {
00365 FmtAssert(FALSE, ("Execution_Cost_Value: Unexpected SUMMARY_VALUE type"));
00366 return NULL;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 static WN* Execution_Cost_Expr(IPA_LNO_READ_FILE* IPA_LNO_File,
00379 WN* wn_call,
00380 DYN_ARRAY<SUMMARY_EXPR>* sx,
00381 DYN_ARRAY<SUMMARY_VALUE>* sv,
00382 INT sx_index)
00383 {
00384 SUMMARY_EXPR* sxx = &(*sx)[sx_index];
00385 WN* wn_one = NULL;
00386 WN* wn_two = NULL;
00387 TYPE_ID mtype = MTYPE_UNKNOWN;
00388 if (sxx->Has_const_operand()) {
00389 WN* wn_non_const = NULL;
00390 if (sxx->Is_expr_value(0)) {
00391 INT value_index = sxx->Get_node_index(0);
00392 wn_one = Execution_Cost_Value(wn_call, sv, value_index);
00393 } else if (sxx->Is_expr_expr(0)) {
00394 INT expr_index = sxx->Get_node_index(0);
00395 wn_one = Execution_Cost_Expr(IPA_LNO_File, wn_call, sx, sv, expr_index);
00396 }
00397 FmtAssert(wn_one != NULL, ("Execution_Cost_Expr: NULL expression"));
00398 INT64 const_value = sxx->Get_const_value();
00399 float float_value = (float) const_value;
00400 wn_two = Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00401 } else {
00402 if (sxx->Is_expr_value(0)) {
00403 INT value_index = sxx->Get_node_index(0);
00404 wn_one = Execution_Cost_Value(wn_call, sv, value_index);
00405 } else if (sxx->Is_expr_expr(0)) {
00406 INT expr_index = sxx->Get_node_index(0);
00407 wn_one = Execution_Cost_Expr(IPA_LNO_File, wn_call, sx, sv, expr_index);
00408 }
00409 FmtAssert(wn_one != NULL, ("Execution_Cost_Expr: NULL expression"));
00410 if (sxx->Is_expr_value(1)) {
00411 INT value_index = sxx->Get_node_index(1);
00412 wn_two = Execution_Cost_Value(wn_call, sv, value_index);
00413 } else if (sxx->Is_expr_expr(1)) {
00414 INT expr_index = sxx->Get_node_index(1);
00415 wn_two = Execution_Cost_Expr(IPA_LNO_File, wn_call, sx, sv, expr_index);
00416 }
00417 FmtAssert(wn_two != NULL, ("Execution_Cost_Expr: NULL expression"));
00418 }
00419 mtype = Cast_Float_Operands(&wn_one, &wn_two);
00420 OPERATOR opr = OPCODE_operator(sxx->Get_opcode());
00421 OPCODE opc = OPCODE_make_op(opr, mtype, MTYPE_V);
00422 return LWN_CreateExp2(opc, wn_one, wn_two);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 extern WN* Execution_Cost(IPA_LNO_READ_FILE* IPA_LNO_File,
00433 WN* wn_call,
00434 TYPE_ID wtype)
00435 {
00436 if (!Can_Evaluate_Cost(wn_call)) {
00437 INT64 const_value = Simple_Execution_Cost(wn_call);
00438 float float_value = (float) const_value;
00439 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00440 }
00441 CALL_INFO* call_info = (CALL_INFO *) WN_MAP_Get(LNO_Info_Map, wn_call);
00442 DYN_ARRAY<SUMMARY_VALUE>* sv = call_info->Value();
00443 DYN_ARRAY<SUMMARY_EXPR>* sx = call_info->Expr();
00444 if (sx->Lastidx() == -1)
00445 return Execution_Cost_Value(wn_call, sv, sv->Lastidx());
00446 WN* wn_expr = Execution_Cost_Expr(IPA_LNO_File, wn_call, sx, sv,
00447 sx->Lastidx());
00448 INT node_count = Node_Count(wn_expr, MAX_CALL_EXPR_COUNT, FALSE);
00449 if (node_count <= MAX_CALL_EXPR_COUNT)
00450 return wn_expr;
00451 LWN_Delete_Tree(wn_expr);
00452 INT64 const_value = Simple_Execution_Cost(wn_call);
00453 float float_value = (float) const_value;
00454 return Make_Const(Host_To_Targ_Float(MTYPE_F8, float_value));
00455 }