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 // Revision history: 00041 // 24-AUG-95 dahl - Original Version 00042 // 00043 // Description: 00044 // Regions Around Inner Loops (RAIL) 00045 // Find inner loops, insert regions around them. 00046 // 00047 // This code is linked in with lno.so 00048 // 00049 //============================================================================ 00050 00051 #define rail_CXX "rail.cxx" 00052 #ifdef _KEEP_RCS_ID 00053 #endif /* _KEEP_RCS_ID */ 00054 00055 #include "wn.h" /* WN type */ 00056 #include "wn_util.h" /* wn accessors */ 00057 #include "rail.h" /* RAIL class */ 00058 #include "ir_reader.h" /* for fdump_tree */ 00059 #include "region_util.h" /* RID structure */ 00060 #include "tracing.h" /* TFile */ 00061 00062 RAIL::RAIL(void) 00063 { 00064 _trace_flag = Get_Trace(TP_REGION,TT_REGION_RAIL_DEBUG,); 00065 } 00066 00067 // max number of nested blocks 00068 #define BLOCK_STACK_SIZE 20 00069 00070 void 00071 RAIL::Process_func_entry(WN *wn) 00072 { 00073 // loop through all func_entries in this WHIRL tree 00074 Set_fe(wn); // set pointer to first PU 00075 do { 00076 FmtAssert(WN_opcode(Get_fe()) == OPC_FUNC_ENTRY, 00077 ("RAIL::Process_func_entry, could not find function entry")); 00078 if (Trace()) 00079 fprintf(TFile,"===== RAIL::Process_func_entry: %s\n", 00080 ST_name(WN_st(Get_fe()))); 00081 Process_block(WN_func_body(Get_fe()),1); // level 0 is PU 00082 RID *rid = REGION_get_rid(Get_fe()); 00083 RID_level(rid) = RL_RAIL; // processed by RAIL 00084 RID_bounds_exist(rid) = REGION_BOUND_UNKNOWN; // no boundary info yet 00085 RID_has_return(rid) = REGION_NO_RETURN; // not known yet 00086 Next_fe(); // go to next PU 00087 } while (Get_fe()); // while there are no more PUs 00088 } 00089 00090 // returns TRUE if found a loop, FALSE otherwise 00091 BOOL 00092 RAIL::Process_block(WN *wn_block, INT32 nest_level) 00093 { 00094 WN *wn_after_loop = NULL; 00095 BOOL found_loop = FALSE; 00096 00097 FmtAssert(WN_opcode(wn_block) == OPC_BLOCK, 00098 ("RAIL::Process_block, could not find block")); 00099 00100 // go through all statements in block 00101 for (WN *wtmp=WN_first(wn_block); wtmp!=NULL; wtmp=WN_next(wtmp)) { 00102 const OPCODE opc = WN_opcode(wtmp); 00103 const OPERATOR opr = OPCODE_operator(opc); 00104 00105 // look for loop beginning 00106 if (opr == OPR_DO_LOOP || opr == OPR_WHILE_DO || opr == OPR_DO_WHILE) { 00107 found_loop = TRUE; // there is a loop in this block 00108 if (WN_next(wtmp)) 00109 wn_after_loop = WN_next(wtmp); 00110 00111 // follow block recursively 00112 WN *wn_body = (opr == OPR_DO_LOOP) ? WN_do_body(wtmp) : 00113 WN_while_body(wtmp); 00114 if (!Process_block(wn_body,nest_level+1)) { 00115 if (Trace()) 00116 fprintf(TFile, 00117 "===== RAIL::Process_block, %s begin, level %d, inner loop\n", 00118 OPCODE_name(opc),nest_level); 00119 // pull loop out of block 00120 wtmp = WN_EXTRACT_FromBlock(wn_block,wtmp); 00121 // add region around the loop, create RID, connect to RID tree 00122 WN *wnew = Add_region_around_loop(wtmp,nest_level); 00123 // add gotos for exits and label for fall-through 00124 wn_after_loop = REGION_add_exit(wn_block,wn_after_loop,wnew); 00125 // patch result back into block 00126 WN_INSERT_BlockBefore(wn_block,wn_after_loop,wnew); 00127 // point wtmp to inserted region and continue scanning from there 00128 wtmp = wnew; 00129 } else { 00130 if (Trace()) 00131 fprintf(TFile,"===== RAIL::Process_block, %s begin, level %d\n", 00132 OPCODE_name(opc),nest_level); 00133 } 00134 } 00135 00136 // handle SCF (Structured Control Flow) nodes, loops handled above 00137 switch (opc) { 00138 case OPC_BLOCK: 00139 found_loop |= Process_block(wtmp,nest_level); 00140 break; 00141 case OPC_REGION: 00142 found_loop |= Process_block(WN_region_body(wtmp),nest_level); 00143 break; 00144 case OPC_IF: 00145 found_loop |= Process_block(WN_then(wtmp),nest_level); 00146 found_loop |= Process_block(WN_else(wtmp),nest_level); 00147 break; 00148 default: 00149 break; 00150 } 00151 00152 } // end for loop 00153 00154 return found_loop; 00155 } 00156 00157 // TODO: need to search through PU and find all exits and build goto table 00158 WN * 00159 RAIL::Add_region_around_loop(WN *wn_loop, INT32 nest_level) 00160 { 00161 // create a new region for this inner loop 00162 WN *wnew = WN_CreateRegion(REGION_KIND_PRAGMA, wn_loop,NULL,NULL, 00163 RID_CREATE_NEW_ID,NULL); 00164 00165 // create RID for the new region and add to map 00166 RID *rid = RID_Create(WN_region_id(wnew), nest_level, wnew); // sets depth 00167 RID_level(rid) = RL_RAIL; 00168 RID_bounds_exist(rid) = REGION_BOUND_UNKNOWN; // no boundary info yet 00169 RID_has_return(rid) = REGION_NO_RETURN; // not known yet 00170 RID_num_exits(rid) = 1; 00171 RID_TYPE_loop_Set(rid); // this RID is strictly a loop 00172 WN_MAP_Set(RID_map,wnew,(void *)rid); 00173 if (Trace()) 00174 fprintf(TFile,"===== RAIL::Add_regions_around_loop, New RID: %d\n", 00175 RID_id(rid)); 00176 00177 // link new RID into RID tree, the PU has the root RID 00178 RID *root_rid = REGION_get_rid(Get_fe()); 00179 FmtAssert(root_rid != NULL, 00180 ("RAIL::Add_region_around_loop, can't find root RID")); 00181 RID_Add_kid(rid,root_rid); 00182 00183 return wnew; 00184 } 00185 00186 extern "C" /* so lnodriver.c can call this entry point */ 00187 void 00188 Rail(WN *itree) 00189 { 00190 RAIL rtmp; 00191 00192 if (!PU_has_region (Get_Current_PU ())) 00193 return; 00194 00195 FmtAssert(WN_opcode(itree) == OPC_FUNC_ENTRY, 00196 ("Rail must be called on a PU")); 00197 00198 // go through all statements looking for inner loops 00199 rtmp.Process_func_entry(itree); 00200 00201 if (rtmp.Trace()) { 00202 fprintf(TFile,"===== RAIL finished\n"); 00203 RID_WN_Tree_Print(TFile,itree); 00204 } 00205 }