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 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 00038 #include "wn_tree_util.h" 00039 #include "anl_common.h" 00040 #include "anl_diagnostics.h" // For warnings and errors 00041 #include "anl_file_mngr.h" // For managing files 00042 #include "w2cf_translator.h" // For translating WHIRL into high-level-language 00043 #include "anl_varlist.h" // For emitting attributes of symbol references 00044 #include "anl_pragma_attribute.h" // For <dir> entries 00045 #include "anl_func_entry.h" 00046 #include "anl_loop_construct.h" 00047 00048 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx 00049 00050 00051 // =============== Static Helper Functions =============== 00052 // ======================================================= 00053 00054 #define WN_current_loop_nest(wn) WN_pragma_arg1(wn) 00055 #define WN_max_loop_nest(wn) WN_pragma_arg2(wn) 00056 00057 00058 // ================ Static Member Functions =============== 00059 // ======================================================== 00060 00061 BOOL 00062 ANL_LOOP_CONSTRUCT::Is_Valid_Dir(ANL_PRAGMA_ATTRIBUTE *dir, 00063 INT32 construct_level) 00064 { 00065 return dir->Is_Loop_Construct_Attribute(construct_level); 00066 } 00067 00068 BOOL 00069 ANL_LOOP_CONSTRUCT::Is_End_Of_Loop_Comment(WN *end_stmt) 00070 { 00071 return (WN_operator(end_stmt) == OPR_COMMENT && 00072 strcmp(Index_To_Str(WN_GetComment(end_stmt)), "ENDLOOP") == 0); 00073 } 00074 00075 void 00076 ANL_LOOP_CONSTRUCT::Remove_Stmt_In_Block(WN *stmt) 00077 { 00078 WN *block = LWN_Get_Parent(stmt); 00079 00080 while (block != NULL && WN_operator(block) != OPR_BLOCK) 00081 block = LWN_Get_Parent(block); 00082 00083 if (WN_operator(block) == OPR_BLOCK) 00084 { 00085 WN_DELETE_FromBlock(block, stmt); 00086 } 00087 } 00088 00089 00090 // =============== Private Member Functions =============== 00091 // ======================================================== 00092 00093 WN * 00094 ANL_LOOP_CONSTRUCT::_First_Loop_Stmt() 00095 { 00096 WN *base = (_Is_Parallel_Loop()? _loop_region : _loop); 00097 ANL_SRCPOS basepos(base); 00098 00099 while (WN_prev(base) != NULL && ANL_SRCPOS(WN_prev(base)) >= basepos) 00100 base = WN_prev(base); 00101 return base; 00102 } // ANL_LOOP_CONSTRUCT::_First_Loop_Stmt 00103 00104 00105 WN * 00106 ANL_LOOP_CONSTRUCT::_Last_Loop_Stmt() 00107 { 00108 WN *base = (_Is_Parallel_Loop()? _loop_region : _loop); 00109 ANL_SRCPOS basepos(base); 00110 00111 while (WN_next(base) != NULL && ANL_SRCPOS(WN_next(base)) <= basepos) 00112 base = WN_next(base); 00113 return base; 00114 } //ANL_LOOP_CONSTRUCT::_Last_Loop_Stmt 00115 00116 00117 void 00118 ANL_LOOP_CONSTRUCT::_Loop_Srcpos_Range(ANL_SRCPOS *min, ANL_SRCPOS *max) 00119 { 00120 // Get the source-position range for the loop, including associated 00121 // pragmas and loop initialization statements (which may have been moved 00122 // in front of the loop by the compiler front-end). 00123 // 00124 WN *end_stmt = NULL; 00125 WN *end_comment = NULL; 00126 WN *base = (_Is_Parallel_Loop()? _loop_region : _loop); 00127 WN *first_stmt = _First_Loop_Stmt(); 00128 WN *last_stmt = _Last_Loop_Stmt(); 00129 ANL_SRCPOS minpos(first_stmt); 00130 ANL_SRCPOS maxpos(last_stmt); 00131 00132 // Start out with the top-level stmts (at same nesting level as the 00133 // region or loop) as a first approximation, looking only at the stmts 00134 // within the loopor region. 00135 // 00136 for (WN *stmt = first_stmt; 00137 stmt != NULL && WN_prev(stmt) != last_stmt; 00138 stmt = WN_next(stmt)) 00139 { 00140 Adjust_Srcpos_Range(stmt, &minpos, &maxpos); 00141 } 00142 00143 // See if the maxpos we got from the above analysis is accurate, 00144 // or whether we should adjust it to extend up to the statement 00145 // following this construct. 00146 // 00147 if (_Is_Parallel_Loop()) 00148 { 00149 // Look for special pragma to end the loop. 00150 // 00151 for (end_stmt = WN_first(WN_region_pragmas(_loop_region)); 00152 (end_stmt != NULL && 00153 WN_pragma(end_stmt) != WN_PRAGMA_PDO_END && 00154 WN_pragma(end_stmt) != WN_PRAGMA_END_MARKER && 00155 (WN_pragma(end_stmt) != WN_PRAGMA_NOWAIT || 00156 _func_entry->Pu_Translator()->Language_is_C())); 00157 end_stmt = WN_next(end_stmt)); 00158 } 00159 00160 // Look for special comment to end the loop. We always need to do this 00161 // such that we can remove it from WHIRL. 00162 // 00163 if (_Is_Parallel_Loop()) 00164 { 00165 // Get to the do-loop 00166 // 00167 for (end_comment = WN_first(WN_region_body(_loop_region)); 00168 (end_comment != NULL && WN_operator(end_comment) != OPR_DO_LOOP); 00169 end_comment = WN_next(end_comment)); 00170 00171 // Look for the special loop terminating comment within the body of 00172 // the loop. 00173 // 00174 if (end_comment != NULL) 00175 for (end_comment = WN_first(WN_do_body(end_comment)); 00176 (end_comment != NULL && !Is_End_Of_Loop_Comment(end_comment)); 00177 end_comment = WN_next(end_comment)); 00178 } 00179 else 00180 { 00181 WN *const body = (_loop_kind == ANL_DO_LOOP? 00182 WN_do_body(_loop) : WN_while_body(_loop)); 00183 00184 // Look for a special loop terminating comment in the body of 00185 // the loop. 00186 // 00187 for (end_comment = WN_first(body); 00188 (end_comment != NULL && !Is_End_Of_Loop_Comment(end_comment)); 00189 end_comment = WN_next(end_comment)); 00190 } 00191 if (end_comment != NULL) 00192 { 00193 if (end_stmt == NULL) 00194 end_stmt = end_comment; 00195 Remove_Stmt_In_Block(end_comment); 00196 } 00197 00198 // Adjust the max position, when there is no true indication of 00199 // the end of the construct. 00200 // 00201 if (end_stmt == NULL && WN_next(last_stmt) != NULL) 00202 { 00203 // Assume the end is just before the next statement. 00204 // 00205 ANL_SRCPOS next_min(WN_next(last_stmt)); 00206 ANL_SRCPOS next_max(WN_next(last_stmt)); 00207 00208 Adjust_Srcpos_Range(WN_next(last_stmt), &next_min, &next_max); 00209 if (next_min > maxpos) // FALSE when the file-numbers are different! 00210 { 00211 next_min -= 1; 00212 maxpos = next_min; 00213 } 00214 } 00215 00216 Is_True(end_stmt == NULL || maxpos == ANL_SRCPOS(end_stmt), 00217 ("Unexpected maxpos (maxpos=[%d,%d,%d],end_stmt_pos=[%d,%d,%d]) in " 00218 "ANL_LOOP_CONSTRUCT::_Loop_Srcpos_Range", 00219 maxpos.Filenum(), maxpos.Linenum(), maxpos.Column(), 00220 ANL_SRCPOS(end_stmt).Filenum(), 00221 ANL_SRCPOS(end_stmt).Linenum(), 00222 ANL_SRCPOS(end_stmt).Column())); 00223 00224 *min = minpos; 00225 *max = maxpos; 00226 } // ANL_LOOP_CONSTRUCT::_Loop_Srcpos_Range 00227 00228 00229 void 00230 ANL_LOOP_CONSTRUCT::_Write_Loop_Header(ANL_CBUF *cbuf) 00231 { 00232 ANL_SRCPOS min_srcpos; 00233 ANL_SRCPOS max_srcpos; 00234 00235 _Loop_Srcpos_Range(&min_srcpos, &max_srcpos); 00236 switch (_loop_kind) 00237 { 00238 case ANL_WHILE_LOOP: 00239 cbuf->Write_String("owhile "); 00240 cbuf->Write_Int(_id); 00241 if (_func_entry->Pu_Translator()->Language_is_C()) 00242 cbuf->Write_String(" \"while "); 00243 else 00244 cbuf->Write_String(" \"do while "); 00245 _func_entry->Pu_Translator()->Expr_To_String(cbuf, WN_while_test(_loop)); 00246 break; 00247 00248 case ANL_WHILE_AS_DO_LOOP: 00249 cbuf->Write_String("oloop "); 00250 cbuf->Write_Int(_id); 00251 if (_func_entry->Pu_Translator()->Language_is_C()) 00252 cbuf->Write_String(" \"for "); 00253 else 00254 cbuf->Write_String(" \"do "); 00255 _func_entry->Pu_Translator()-> 00256 Original_Symname_To_String(cbuf, WN_st(WN_prev(_loop))); 00257 break; 00258 00259 case ANL_DO_LOOP: 00260 case ANL_DOACROSS_LOOP: 00261 case ANL_PARALLELDO_LOOP: 00262 case ANL_PDO_LOOP: 00263 cbuf->Write_String("oloop "); 00264 cbuf->Write_Int(_id); 00265 if (_func_entry->Pu_Translator()->Language_is_C()) 00266 cbuf->Write_String(" \"for "); 00267 else 00268 cbuf->Write_String(" \"do "); 00269 _func_entry->Pu_Translator()-> 00270 Original_Symname_To_String(cbuf, WN_st(WN_index(_loop))); 00271 break; 00272 00273 default: 00274 break; 00275 } 00276 cbuf->Write_String("\" range "); 00277 min_srcpos.Write(cbuf); 00278 cbuf->Write_Char('-'); 00279 max_srcpos.Write(cbuf); 00280 cbuf->Write_Char('\n'); 00281 } // ANL_LOOP_CONSTRUCT::_Write_Loop_Header 00282 00283 00284 void 00285 ANL_LOOP_CONSTRUCT::_Write_Loop_Directive(ANL_CBUF *cbuf) 00286 { 00287 BOOL omp_pragma; 00288 WN *nowait = NULL; 00289 WN *end_pdo = NULL; 00290 WN *region_pragma = WN_first(WN_region_pragmas(_loop_region)); 00291 WN *next_clause = WN_next(region_pragma); 00292 ANL_SRCPOS startpos; 00293 ANL_SRCPOS endpos; 00294 00295 // Some preliminiaries. 00296 // 00297 _func_entry->Get_Pragma_Srcpos_Range(region_pragma, &startpos, &endpos); 00298 00299 // The idir clause. 00300 // 00301 cbuf->Write_String("idir "); 00302 cbuf->Write_Int(_id); 00303 cbuf->Write_Char(' '); 00304 startpos.Write(cbuf); 00305 cbuf->Write_Char('-'); 00306 endpos.Write(cbuf); 00307 00308 omp_pragma = WN_pragma_omp(region_pragma); 00309 cbuf->Append_Pragma_Preamble(omp_pragma,FALSE); 00310 00311 switch (_loop_kind) 00312 { 00313 case ANL_DOACROSS_LOOP: 00314 cbuf->Write_String("DOACROSS "); 00315 break; 00316 case ANL_PARALLELDO_LOOP: 00317 cbuf->Write_String("PARALLEL DO "); 00318 break; 00319 case ANL_PDO_LOOP: 00320 if (omp_pragma) 00321 cbuf->Write_String("DO "); 00322 else if (_func_entry->Pu_Translator()->Language_is_C()) 00323 cbuf->Write_String("PFOR "); 00324 else 00325 cbuf->Write_String("PDO "); 00326 break; 00327 default: 00328 cbuf->Write_String("<WHATLOOP??> "); 00329 break; 00330 } 00331 00332 // Emit the "nest" clause if relevant 00333 // 00334 if (WN_max_loop_nest(region_pragma) > 1) 00335 { 00336 _func_entry->Pu_Translator()-> 00337 Nest_Clauses_To_String(cbuf, 00338 _loop_region, 00339 WN_max_loop_nest(region_pragma)); 00340 if ( _func_entry->Pu_Translator()->Is_A_Pragma_Clause(next_clause)) 00341 cbuf->Write_String(", "); 00342 } 00343 00344 // The list of clauses on an idir. 00345 // 00346 _func_entry->Pu_Translator()->ClauseList_To_String(cbuf, &next_clause); 00347 cbuf->Write_String("\n"); 00348 00349 // The edir clause. 00350 // 00351 if (next_clause != NULL && 00352 !_func_entry->Pu_Translator()->Language_is_C()) 00353 { 00354 // We never emit an edir for language C (sections of code are delimited 00355 // by a nested scope, not by BEGIN/END pragmas). 00356 // 00357 if (WN_pragma(next_clause) == WN_PRAGMA_PDO_END && 00358 !WN_pragma_compiler_generated(next_clause)) 00359 end_pdo = next_clause; 00360 else if (WN_pragma(next_clause) == WN_PRAGMA_NOWAIT && 00361 !WN_pragma_compiler_generated(next_clause)) 00362 nowait = next_clause; 00363 } 00364 if (nowait != NULL || end_pdo != NULL) 00365 { 00366 if (end_pdo != NULL) 00367 startpos = ANL_SRCPOS(end_pdo); 00368 else 00369 startpos = ANL_SRCPOS(nowait); 00370 cbuf->Write_String("edir "); 00371 cbuf->Write_Int(_id); 00372 cbuf->Write_String(" "); 00373 startpos.Write(cbuf); 00374 00375 cbuf->Append_Pragma_Preamble(omp_pragma,FALSE); 00376 if (WN_pragma_omp(next_clause)) 00377 cbuf->Write_String("END DO"); 00378 else 00379 cbuf->Write_String("END PDO"); 00380 if (nowait) 00381 cbuf->Write_String(" nowait\n"); 00382 else 00383 cbuf->Write_Char('\n'); 00384 } 00385 } // ANL_LOOP_CONSTRUCT::_Write_Loop_Directive 00386 00387 00388 // =============== Public Member Functions ================ 00389 // ======================================================== 00390 00391 00392 ANL_LOOP_CONSTRUCT::ANL_LOOP_CONSTRUCT(WN *loop, 00393 INT32 construct_level, 00394 ANL_FUNC_ENTRY *func_entry, 00395 MEM_POOL *pool): 00396 _loop_region(NULL), 00397 _loop(loop), 00398 _construct_level(construct_level), 00399 _func_entry(func_entry), 00400 _pool(pool) 00401 { 00402 WN *parent_region = NULL; 00403 BOOL in_region = FALSE; 00404 00405 // Set tentative loop kind (we may later change an ANL_DO_LOOP if its 00406 // context shows it to be a parallel loop). 00407 // 00408 if (WN_operator(loop) == OPR_WHILE_DO || 00409 WN_operator(loop) == OPR_DO_WHILE) 00410 { 00411 if (_func_entry->Pu_Translator()->Whileloop_Looks_Like_Forloop(loop)) 00412 _loop_kind = ANL_WHILE_AS_DO_LOOP; 00413 else 00414 _loop_kind = ANL_WHILE_LOOP; 00415 } 00416 else // An OPR_DO_LOOP 00417 { 00418 _loop_kind = ANL_DO_LOOP; 00419 parent_region = LWN_Get_Parent(LWN_Get_Parent(loop)); 00420 in_region = (WN_operator(parent_region) == OPR_REGION); 00421 } 00422 00423 // Set the ID for this loop. 00424 // 00425 _id = _func_entry->Next_Construct_Id()->Post_Incr(); 00426 func_entry->Set_Construct_Id(loop, _id); 00427 00428 // See if it is a special parallel loop 00429 // 00430 if (in_region) 00431 { 00432 WN *pragma = WN_first(WN_region_pragmas(parent_region)); 00433 00434 if (pragma != NULL) 00435 { 00436 if (WN_pragma(pragma) == WN_PRAGMA_DOACROSS && 00437 WN_current_loop_nest(pragma) == 0) 00438 { 00439 _loop_kind = ANL_DOACROSS_LOOP; 00440 _loop_region = parent_region; 00441 func_entry->Set_Construct_Id(parent_region, _id); 00442 } 00443 else if (WN_pragma(pragma) == WN_PRAGMA_PARALLEL_DO && 00444 WN_current_loop_nest(pragma) == 0) 00445 { 00446 _loop_kind = ANL_PARALLELDO_LOOP; 00447 _loop_region = parent_region; 00448 func_entry->Set_Construct_Id(parent_region, _id); 00449 } 00450 else if (WN_pragma(pragma) == WN_PRAGMA_PDO_BEGIN && 00451 WN_current_loop_nest(pragma) == 0) 00452 { 00453 _loop_kind = ANL_PDO_LOOP; 00454 _loop_region = parent_region; 00455 func_entry->Set_Construct_Id(parent_region, _id); 00456 } 00457 } // if region pragma 00458 } // if in region 00459 } // ANL_LOOP_CONSTRUCT::ANL_LOOP_CONSTRUCT 00460 00461 00462 WN * 00463 ANL_LOOP_CONSTRUCT::Next_Stmt() 00464 { 00465 // The next statement must be in the same scope as the _loop, since 00466 // that is expected from ANL_FUNC_ENTRY::Emit_Nested_Original_Constructs(). 00467 // 00468 return WN_next(_loop); 00469 } // ANL_LOOP_CONSTRUCT::Next_Stmt 00470 00471 00472 void 00473 ANL_LOOP_CONSTRUCT::Write(ANL_CBUF *cbuf) 00474 { 00475 ANL_CBUF varlist_cbuf(_pool); 00476 ANL_CBUF nested_cbuf(_pool); 00477 ANL_SRCPOS min_srcpos; 00478 ANL_SRCPOS max_srcpos; 00479 ANL_VARLIST varlist(_pool, _func_entry); 00480 WN *first_stmt = _First_Loop_Stmt(); 00481 WN *last_stmt = _Last_Loop_Stmt(); 00482 WN *body = ((_loop_kind == ANL_WHILE_AS_DO_LOOP || 00483 _loop_kind == ANL_WHILE_LOOP)? 00484 WN_while_body(_loop) : 00485 WN_do_body(_loop)); 00486 00487 // Write out the loop header 00488 // 00489 _Write_Loop_Header(cbuf); 00490 00491 // Write out the index variable. 00492 // 00493 if (_loop_kind != ANL_WHILE_LOOP) 00494 { 00495 ST *const st = (_loop_kind == ANL_WHILE_AS_DO_LOOP? 00496 WN_st(WN_prev(_loop)) : WN_st(WN_index(_loop))); 00497 00498 cbuf->Write_String("index \""); 00499 _func_entry->Pu_Translator()-> Original_Symname_To_String(cbuf, st); 00500 cbuf->Write_String("\"\n"); 00501 } 00502 00503 // Write out the loop related directives 00504 // 00505 if (_loop_kind == ANL_DOACROSS_LOOP || 00506 _loop_kind == ANL_PARALLELDO_LOOP || 00507 _loop_kind == ANL_PDO_LOOP) 00508 { 00509 _Write_Loop_Directive(cbuf); 00510 } 00511 00512 // Determine variable references within the statements belonging to the 00513 // loop, and write them to a temporary buffer. 00514 // 00515 for (WN *stmt = first_stmt; 00516 stmt != NULL && WN_prev(stmt) != last_stmt; 00517 stmt = WN_next(stmt)) 00518 { 00519 varlist.Insert_Var_Refs(stmt); 00520 } 00521 varlist.Write(&varlist_cbuf, _id); 00522 varlist_cbuf.Write_Char('\n'); 00523 00524 // Write nested constructs to a temporary buffer 00525 // 00526 _func_entry->Emit_Nested_Original_Constructs(&nested_cbuf, 00527 WN_first(body), WN_last(body)); 00528 00529 // Write out any applicable <dir> entries (i.e. those that were 00530 // not attributed to nested constructs). 00531 // 00532 _func_entry-> 00533 Emit_Dir_Entries(cbuf, _id, _construct_level, 00534 &ANL_LOOP_CONSTRUCT::Is_Valid_Dir); 00535 00536 // Write the varlist and nested constructs. 00537 // 00538 if (varlist_cbuf.Size() > 0) 00539 cbuf->Write_String(varlist_cbuf.Chars()); 00540 if (nested_cbuf.Size() > 0) 00541 cbuf->Write_String(nested_cbuf.Chars()); 00542 00543 // Finish writing the function descriptor. 00544 // 00545 if (_loop_kind == ANL_WHILE_LOOP) 00546 cbuf->Write_String("end_owhile "); 00547 else 00548 cbuf->Write_String("end_oloop "); 00549 cbuf->Write_Int(_id); 00550 cbuf->Write_String("\n"); // Start next construct on a new line 00551 } // ANL_LOOP_CONSTRUCT::Write