Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 //-*-c++-*- 00037 // ==================================================================== 00038 // ==================================================================== 00039 // 00040 // 00041 // Description: 00042 // 00043 // During instrumentation, certain events associated with program 00044 // control flow (such as the number of times a particular branch is 00045 // taken, or not taken) are counted. During subsequent compilations, 00046 // this data may be retrieved and used to guide optimization decisions. 00047 // 00048 // fb_info.h defines data structs used to store this feedback data for 00049 // various types of whirl nodes. These structures are used by the 00050 // FEEDBACK class (defined in fb_whirl.h) and by the instrumentation runtime 00051 // 00052 // ==================================================================== 00053 // ==================================================================== 00054 00055 #ifndef fb_info_INCLUDED 00056 #define fb_info_INCLUDED 00057 00058 #include "fb_freq.h" 00059 00060 #include <vector> 00061 00062 using namespace std; 00063 00064 #ifdef MONGOOSE_BE 00065 00066 #ifndef mempool_allocator_INCLUDED 00067 #include "mempool_allocator.h" 00068 #endif 00069 00070 #ifndef wn_INCLUDED 00071 #include "wn.h" 00072 #endif 00073 00074 #endif // MONGOOSE_BE 00075 00076 00077 // data structures shared by both the instrumentation runtime and the back 00078 // end. 00079 00080 struct FB_Info_Invoke { 00081 00082 FB_FREQ freq_invoke; // number of times statement invoked 00083 00084 FB_Info_Invoke( FB_FREQ invoke) 00085 : freq_invoke( invoke ) {} 00086 00087 FB_Info_Invoke() : 00088 00089 /* Solaris workaround 00090 * compiler encountered error because there's no definition of 00091 * FB_FREQ(const FB_FREQ) constructor, see fb_freq.h -- 00092 * seems like it should call the constructor - FB_FREQ( 00093 * FB_FREQ_TYPE_UNINIT) instead. 00094 */ 00095 freq_invoke( FB_FREQ_TYPE_UNINIT ) { } 00096 00097 void Print( FILE *fp ) const { 00098 fprintf( fp, "FB---> invoke = " ); 00099 freq_invoke.Print( fp ); 00100 } 00101 }; 00102 00103 struct FB_Info_Branch { 00104 00105 FB_FREQ freq_taken; // number of times branch taken 00106 // (then clause for IF, Kid0 for CSELECT) 00107 FB_FREQ freq_not_taken; // number of times branch not taken 00108 // (else clause for IF, Kid1 for CSELECT) 00109 00110 FB_Info_Branch( FB_FREQ taken, FB_FREQ not_taken ) 00111 : freq_taken( taken ), 00112 freq_not_taken( not_taken ) {} 00113 00114 #ifdef MONGOOSE_BE 00115 FB_Info_Branch( FB_FREQ taken, FB_FREQ not_taken, OPERATOR opr ) 00116 : freq_taken( opr != OPR_FALSEBR ? taken : not_taken ), 00117 freq_not_taken( opr != OPR_FALSEBR ? not_taken : taken ) { 00118 // if opr == OPR_FALSEBR, then reverse taken and not_taken 00119 Is_True( opr == OPR_TRUEBR || opr == OPR_FALSEBR 00120 || opr == OPR_IF || opr == OPR_CSELECT, 00121 ( "FB_Info_Branch found unexpected operator" ) ); 00122 } 00123 #endif // MONGOOSE_BE 00124 00125 00126 /* 00127 * Same change, see before 00128 */ 00129 FB_Info_Branch() 00130 : freq_taken( FB_FREQ_TYPE_UNINIT ), 00131 freq_not_taken( FB_FREQ_TYPE_UNINIT ) {} 00132 00133 void Print( FILE *fp ) const { 00134 fprintf( fp, "FB---> taken = " ); 00135 freq_taken.Print( fp ); 00136 fprintf( fp, ", not_taken = " ); 00137 freq_not_taken.Print( fp ); 00138 } 00139 00140 FB_FREQ Total() const { 00141 return ( freq_taken + freq_not_taken ); 00142 } 00143 }; 00144 00145 // ==================================================================== 00146 00147 // Feedback info for a loop node 00148 // ___|__ 00149 // | test | 00150 // |______| 00151 // / \ 00152 // zero/N Y\positive 00153 // / \ ____ 00154 // | _\__/_ \ 00155 // | | body | | 00156 // | |______| | exit = zero + out 00157 // | | test | | iterate = positive + back 00158 // | |______| | 00159 // | / \ / In a DO_WHILE loop, zero = 0. 00160 // | out/N Y\__/ 00161 // \ / back 00162 // _\__/_ 00163 // | | 00164 00165 00166 struct FB_Info_Loop { 00167 00168 FB_FREQ freq_zero; 00169 FB_FREQ freq_positive; 00170 FB_FREQ freq_out; 00171 FB_FREQ freq_back; 00172 FB_FREQ freq_exit; 00173 FB_FREQ freq_iterate; 00174 00175 FB_Info_Loop( FB_FREQ zero, FB_FREQ positive, FB_FREQ out, FB_FREQ back, 00176 FB_FREQ exit, FB_FREQ iterate ) 00177 : freq_zero( zero ), 00178 freq_positive( positive ), 00179 freq_out( out ), 00180 freq_back( back ), 00181 freq_exit( exit ), 00182 freq_iterate( iterate ) {} 00183 00184 FB_Info_Loop( FB_FREQ zero, FB_FREQ positive, FB_FREQ out, FB_FREQ back ) 00185 : freq_zero( zero ), 00186 freq_positive( positive ), 00187 freq_out( out ), 00188 freq_back( back ), 00189 freq_exit( zero + out ), 00190 freq_iterate( positive + back ) {} 00191 00192 FB_Info_Loop( FB_FREQ exit, FB_FREQ iterate ) 00193 : freq_zero( FB_FREQ_UNKNOWN ), 00194 freq_positive( FB_FREQ_UNKNOWN ), 00195 freq_out( FB_FREQ_UNKNOWN ), 00196 freq_back( FB_FREQ_UNKNOWN ), 00197 freq_exit( exit ), 00198 freq_iterate( iterate ) {} 00199 00200 /* 00201 * Same change, see before 00202 */ 00203 FB_Info_Loop() 00204 : freq_zero( FB_FREQ_TYPE_UNINIT ), 00205 freq_positive( FB_FREQ_TYPE_UNINIT ), 00206 freq_out( FB_FREQ_TYPE_UNINIT ), 00207 freq_back( FB_FREQ_TYPE_UNINIT ), 00208 freq_exit( FB_FREQ_TYPE_UNINIT ), 00209 freq_iterate( FB_FREQ_TYPE_UNINIT ) {} 00210 00211 00212 00213 void Print( FILE *fp ) const { 00214 fprintf( fp, "FB---> zero = " ); 00215 freq_zero.Print( fp ); 00216 fprintf( fp, ", positive = " ); 00217 freq_positive.Print( fp ); 00218 fprintf( fp, ", out = " ); 00219 freq_out.Print( fp ); 00220 fprintf( fp, ", back = " ); 00221 freq_back.Print( fp ); 00222 fprintf( fp, "\n exit = " ); 00223 freq_exit.Print( fp ); 00224 fprintf( fp, ", iterate = " ); 00225 freq_iterate.Print( fp ); 00226 } 00227 00228 FB_FREQ Total() const { 00229 return ( freq_exit + freq_iterate ); 00230 } 00231 00232 float Loop_lower_scale() const { 00233 FB_FREQ freq_scale = ( freq_zero + freq_positive ) / Total(); 00234 if ( freq_scale.Known() ) 00235 return freq_scale.Value(); 00236 else 00237 return 0.1; // This is a wild guess!! 00238 } 00239 }; 00240 00241 struct FB_Info_Circuit { 00242 00243 FB_FREQ freq_left; // "taken" means false for CAND, true for CIOR 00244 FB_FREQ freq_right; 00245 FB_FREQ freq_neither; 00246 00247 FB_Info_Circuit( FB_FREQ left, FB_FREQ right, FB_FREQ neither ) 00248 : freq_left( left ), 00249 freq_right( right ), 00250 freq_neither( neither ) {} 00251 00252 /* 00253 * same change, see before 00254 */ 00255 FB_Info_Circuit() 00256 : freq_left( FB_FREQ_TYPE_UNINIT ), 00257 freq_right( FB_FREQ_TYPE_UNINIT ), 00258 freq_neither( FB_FREQ_TYPE_UNINIT ) {} 00259 00260 00261 void Print( FILE *fp ) const { 00262 fprintf( fp, "FB---> left = " ); 00263 freq_left.Print( fp ); 00264 fprintf( fp, ", right = " ); 00265 freq_right.Print( fp ); 00266 fprintf( fp, ", neither = " ); 00267 freq_neither.Print( fp ); 00268 } 00269 00270 FB_FREQ Total() const { 00271 return ( freq_left + freq_right + freq_neither ); 00272 } 00273 }; 00274 00275 00276 struct FB_Info_Call { 00277 FB_FREQ freq_entry; 00278 FB_FREQ freq_exit; 00279 BOOL in_out_same; // TRUE iff freq_entry and freq_exit must be == 00280 BOOL dummy_buffer; // FB_Info_Call size must be 0 mod 64bits for 00281 // consistent feedback file alignment in IA32/64 00282 00283 FB_Info_Call( FB_FREQ entry, FB_FREQ exit, BOOL same = FALSE ) 00284 : freq_entry( entry ), 00285 freq_exit( exit ), 00286 in_out_same( same ) { 00287 Is_True( freq_entry == freq_exit || ! in_out_same, 00288 ( "FEEDBACK::Annot_call: in_out_same failure" ) ); 00289 } 00290 00291 FB_Info_Call( FB_FREQ entry_and_exit ) 00292 : freq_entry( entry_and_exit ), 00293 freq_exit( entry_and_exit ), 00294 in_out_same( TRUE ) {} 00295 00296 /* 00297 * same change, see before 00298 */ 00299 FB_Info_Call() : 00300 freq_entry(FB_FREQ_TYPE_UNINIT), 00301 freq_exit(FB_FREQ_TYPE_UNINIT), 00302 in_out_same(FALSE) {} 00303 00304 00305 void Print( FILE *fp ) const { 00306 fprintf( fp, "FB---> entry = " ); 00307 freq_entry.Print( fp ); 00308 fprintf( fp, ", exit = " ); 00309 freq_exit.Print( fp ); 00310 fprintf( fp, ", in_out_same = %c", in_out_same ? 'Y' : 'N' ); 00311 } 00312 }; 00313 00314 00315 struct FB_Info_Switch { 00316 00317 vector<FB_FREQ> freq_targets; 00318 00319 FB_Info_Switch() {} 00320 00321 /* 00322 * NOTE: these two lines look strange ??? 00323 */ 00324 FB_Info_Switch( const vector<FB_FREQ>::size_type n ) 00325 : freq_targets( vector<FB_FREQ>( n, FB_FREQ_UNINIT ) ) {} 00326 00327 FB_FREQ& operator[] ( const vector<FB_FREQ>::size_type n ) { 00328 if ( n >= freq_targets.size() ) { 00329 freq_targets.insert( freq_targets.end(), n - freq_targets.size() + 1, 00330 FB_FREQ_UNINIT ); 00331 } 00332 return freq_targets[n]; 00333 } 00334 00335 const FB_FREQ& operator[] ( const vector<FB_FREQ>::size_type n ) const { 00336 return ( n >= freq_targets.size() ? FB_FREQ_UNINIT : freq_targets[n] ); 00337 } 00338 00339 vector<FB_FREQ>::size_type size() const { 00340 return freq_targets.size(); 00341 } 00342 00343 vector<FB_FREQ>::const_reference back() const { 00344 return freq_targets.back(); 00345 } 00346 00347 void pop_back() { 00348 freq_targets.pop_back(); 00349 } 00350 00351 void Print( FILE *fp ) const { 00352 fprintf( fp, "FB---> targets = %d", (INT) freq_targets.size() ); 00353 for ( INT t = 0; t < freq_targets.size(); t++ ) { 00354 fprintf( fp, ", %d: ", t ); 00355 freq_targets[t].Print( fp ); 00356 } 00357 } 00358 00359 FB_FREQ Total() const { 00360 vector<FB_FREQ>::const_iterator iter; 00361 FB_FREQ freq = FB_FREQ_ZERO; 00362 for ( iter = freq_targets.begin(); iter != freq_targets.end(); iter++ ) { 00363 freq += *iter; 00364 } 00365 return freq; 00366 } 00367 }; 00368 00369 00370 // Print the entire FB_Info vector 00371 template <class T> 00372 void 00373 FB_Info_Print (const T& info, const char* name, FILE *fp) 00374 { 00375 size_t size = info.size (); 00376 00377 if (size != 0) 00378 fprintf (fp, "%s Profile:\n", name); 00379 for (size_t i = 0; i < size; i++) { 00380 fprintf(fp, "\t%s id = %d\t", name, i); 00381 info[i].Print (fp); 00382 fputc ('\n', fp); 00383 } 00384 } 00385 00386 00387 // utilities and definitions only used by the back end (and not by the 00388 // instrumentation runtime 00389 #ifdef MONGOOSE_BE 00390 00391 typedef vector<FB_Info_Invoke, mempool_allocator<FB_Info_Invoke> > 00392 FB_Invoke_Vector; 00393 typedef vector<FB_Info_Branch, mempool_allocator<FB_Info_Branch> > 00394 FB_Branch_Vector; 00395 typedef vector<FB_Info_Loop, mempool_allocator<FB_Info_Loop> > 00396 FB_Loop_Vector; 00397 typedef vector<FB_Info_Circuit, mempool_allocator<FB_Info_Circuit> > 00398 FB_Circuit_Vector; 00399 typedef vector<FB_Info_Call, mempool_allocator<FB_Info_Call> > 00400 FB_Call_Vector; 00401 typedef vector<FB_Info_Switch, mempool_allocator<FB_Info_Switch> > 00402 FB_Switch_Vector; 00403 00404 // ==================================================================== 00405 // FB_EDGE_TYPE -- Indicates the source of a node's frequency data 00406 // 00407 // Frequency values are assigned to edges in the control flow graph. 00408 // ==================================================================== 00409 00410 // FB_IO_ESCAPE_EDGES_MAX is the maximum number of labels that can appear 00411 // within the ITEMs pf an IO as branch targets. 00412 00413 #define FB_IO_ESCAPE_EDGES_MAX 3 00414 00415 enum FB_EDGE_TYPE { 00416 FB_EDGE_UNINIT = 0, // NOTE: If any of these are changed, then 00417 FB_EDGE_INCOMING = 1, // the array FB_EDGE_NAMES in fb_info.cxx 00418 FB_EDGE_OUTGOING = 2, // must also be updated! 00419 FB_EDGE_ENTRY_OUTGOING = 3, 00420 FB_EDGE_BRANCH_TAKEN = 4, 00421 FB_EDGE_BRANCH_NOT_TAKEN = 5, 00422 FB_EDGE_LOOP_ZERO = 6, 00423 FB_EDGE_LOOP_POSITIVE = 7, 00424 FB_EDGE_LOOP_OUT = 8, 00425 FB_EDGE_LOOP_BACK = 9, 00426 FB_EDGE_LOOP_EXIT = 10, // EXIT == ZERO + OUT 00427 FB_EDGE_LOOP_ITERATE = 11, // ITERATE == POSITIVE + BACK 00428 FB_EDGE_CIRCUIT_LEFT = 12, 00429 FB_EDGE_CIRCUIT_RIGHT = 13, 00430 FB_EDGE_CIRCUIT_NEITHER = 14, 00431 FB_EDGE_CALL_INCOMING = 15, 00432 FB_EDGE_CALL_OUTGOING = 16, 00433 FB_EDGE_CALL_INOUTSAME = 17, 00434 FB_EDGE_IO_OUTGOING = 18, 00435 FB_EDGE_IO_ESCAPE_BASE = 19, 00436 FB_EDGE_SWITCH_DEFAULT = 22, // 19 + FB_IO_ESCAPE_EDGES_MAX 00437 FB_EDGE_SWITCH_BASE = 23 // must be last 00438 }; 00439 00440 // IO branch br is BASE + br; 0 <= br < FB_IO_ESCAPE_EDGES_MAX 00441 // SWITCH branch br is BASE + br; 0 <= br 00442 00443 #define FB_EDGE_IO_ESCAPE(br) ( FB_EDGE_TYPE( FB_EDGE_IO_ESCAPE_BASE + (br) ) ) 00444 00445 #define FB_EDGE_SWITCH(br) ( FB_EDGE_TYPE( FB_EDGE_SWITCH_BASE + (br) ) ) 00446 #define FB_EDGE_SWITCH_INDEX(typ) ( INT32( (typ) - FB_EDGE_SWITCH_BASE + 1 ) ) 00447 00448 #define FB_EDGE_TYPE_NAME_LENGTH 20 // buffer length required for 00449 // FB_EDGE_TYPE_sprintf 00450 00451 extern const char *FB_EDGE_NAMES[]; 00452 00453 void FB_EDGE_TYPE_fprintf( FILE *fp, const FB_EDGE_TYPE fb_type ); 00454 INT FB_EDGE_TYPE_sprintf( char *buffer, const FB_EDGE_TYPE fb_type ); 00455 00456 00457 // ==================================================================== 00458 // The following structures hold feedback info for the incoming and 00459 // outgoing edges of various kinds of whirl nodes. 00460 // ==================================================================== 00461 00462 // Minimal feedback info for label, goto, entry and return nodes, and 00463 // the WN_PRAGMA_PREAMBLE_END PRAGMA node 00464 00465 #define fb_opr_cases_invoke \ 00466 case OPR_LABEL: \ 00467 case OPR_GOTO: \ 00468 case OPR_MSTORE: \ 00469 case OPR_FUNC_ENTRY: \ 00470 case OPR_ALTENTRY: \ 00471 case OPR_RETURN: \ 00472 case OPR_RETURN_VAL 00473 // Note that OPR_PRAGMA is not included in fb_opr_cases_invoke 00474 00475 inline bool FB_valid_opr_invoke(const WN *wn) { 00476 OPERATOR opr = WN_operator( wn ); 00477 switch ( opr ) { 00478 fb_opr_cases_invoke: 00479 return true; 00480 case OPR_PRAGMA: 00481 return ( WN_pragma( wn ) == WN_PRAGMA_PREAMBLE_END ); 00482 default: 00483 return false; 00484 } 00485 } 00486 00487 00488 // ==================================================================== 00489 00490 // Feedback info for a branch node 00491 // IDEA: Within a loop test expression, distinguish for CSELECT between 00492 // first and later trips 00493 00494 #define fb_opr_cases_branch \ 00495 case OPR_TRUEBR: \ 00496 case OPR_FALSEBR: \ 00497 case OPR_IF: \ 00498 case OPR_CSELECT 00499 00500 inline bool FB_valid_opr_branch(const WN *wn) { 00501 OPERATOR opr = WN_operator( wn ); 00502 switch ( opr ) { 00503 fb_opr_cases_branch: 00504 return true; 00505 default: 00506 return false; 00507 } 00508 } 00509 00510 00511 // ==================================================================== 00512 00513 #define fb_opr_cases_loop \ 00514 case OPR_DO_LOOP: \ 00515 case OPR_WHILE_DO: \ 00516 case OPR_DO_WHILE 00517 00518 inline bool FB_valid_opr_loop(const WN *wn) { 00519 OPERATOR opr = WN_operator( wn ); 00520 switch ( opr ) { 00521 fb_opr_cases_loop: 00522 return true; 00523 default: 00524 return false; 00525 } 00526 } 00527 00528 // ==================================================================== 00529 00530 // Feedback info for OPR_CAND and/or OPR_CIOR 00531 // IDEA: Within a loop test expression, distinguish between first and later 00532 // trips 00533 00534 #define fb_opr_cases_circuit \ 00535 case OPR_CAND: \ 00536 case OPR_CIOR 00537 00538 inline bool FB_valid_opr_circuit(const WN *wn) { 00539 OPERATOR opr = WN_operator( wn ); 00540 switch ( opr ) { 00541 fb_opr_cases_circuit: 00542 return true; 00543 default: 00544 return false; 00545 } 00546 } 00547 00548 00549 // ==================================================================== 00550 // Feedback info for a call 00551 00552 #define fb_opr_cases_call \ 00553 case OPR_PICCALL: \ 00554 case OPR_CALL: \ 00555 case OPR_ICALL: \ 00556 case OPR_INTRINSIC_CALL: \ 00557 case OPR_IO 00558 // case OPR_REGION: 00559 00560 inline bool FB_valid_opr_call(const WN *wn) { 00561 OPERATOR opr = WN_operator( wn ); 00562 switch ( opr ) { 00563 fb_opr_cases_call: 00564 return true; 00565 default: 00566 return false; 00567 } 00568 } 00569 00570 00571 // ==================================================================== 00572 00573 // Feedback info for a OPR_SWITCH or OPR_XGOTO or OPR_SWITCH 00574 // A frequency count is given for each possible jump target 00575 00576 #define fb_opr_cases_switch \ 00577 case OPR_SWITCH: \ 00578 case OPR_COMPGOTO: \ 00579 case OPR_XGOTO 00580 00581 inline bool FB_valid_opr_switch (const WN *wn) { 00582 OPERATOR opr = WN_operator( wn ); 00583 switch ( opr ) { 00584 fb_opr_cases_switch: 00585 return true; 00586 default: 00587 return false; 00588 } 00589 } 00590 00591 #endif // MONGOOSE_BE 00592 // ==================================================================== 00593 00594 #endif 00595 00596 00597 00598 00599 00600 00601 00602