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 #include <sys/types.h> 00037 #include "tracing.h" 00038 #include "ipa_section.h" 00039 #include "reshape.h" 00040 00041 //----------------------------------------------------------------------- 00042 // NAME: RESHAPE::RESHAPE 00043 // FUNCTION: Save a list of PROJECTED_REGIONs for reshaping analysis. 00044 //----------------------------------------------------------------------- 00045 00046 RESHAPE::RESHAPE(PROJECTED_REGION* caller_shape_proj_region, 00047 PROJECTED_REGION* callee_shape_proj_region, 00048 PROJECTED_REGION* callee_proj_region, 00049 PROJECTED_REGION* callsite_region, 00050 MEM_POOL* m, 00051 BOOL trace) : 00052 _caller_shape_proj_region (caller_shape_proj_region), 00053 _callee_shape_proj_region (callee_shape_proj_region), 00054 _callee_proj_region (callee_proj_region), 00055 _callsite_region (callsite_region), 00056 _callee_proj_reshaped_region (NULL), 00057 _m (m) 00058 { 00059 #ifdef Is_True_On 00060 if (trace) { 00061 fprintf(TFile, "\nRESHAPE::RESHAPE\n"); 00062 fprintf(TFile, " caller_shape: "); 00063 if (_caller_shape_proj_region) { 00064 _caller_shape_proj_region->Print(TFile); 00065 } else { 00066 fprintf(TFile, "NULL\n"); 00067 } 00068 fprintf(TFile, " callee_shape: "); 00069 if (_callee_shape_proj_region) { 00070 _callee_shape_proj_region->Print(TFile); 00071 } else { 00072 fprintf(TFile, "NULL\n"); 00073 } 00074 fprintf(TFile, " callee_proj_region: "); 00075 if (_callee_proj_region) { 00076 _callee_proj_region->Print(TFile); 00077 } else { 00078 fprintf(TFile, "NULL\n"); 00079 } 00080 fprintf(TFile, " callsite_region: "); 00081 if (_callsite_region) { 00082 _callsite_region->Print(TFile); 00083 } else { 00084 fprintf(TFile, "NULL\n"); 00085 } 00086 } 00087 #endif // Is_True_On 00088 } 00089 00090 //----------------------------------------------------------------------- 00091 // NAME: RESHAPE::Constant_Type_Reshape 00092 // FUNCTION: Return TRUE if this reshaping is "constant". Return FALSE 00093 // otherwise. 00094 // NOTE: By "constant" we mean: 00095 // (1) Caller and callee shapes have all constant dimensions, with 00096 // the possible exception of the first dimension. 00097 // (2) The region in the callee has all constant dimensions. 00098 //----------------------------------------------------------------------- 00099 00100 BOOL RESHAPE::Constant_Type_Reshape() 00101 { 00102 return _caller_shape_proj_region->Constant_bounds(1) 00103 && _callee_shape_proj_region->Constant_bounds(1) 00104 && _callee_proj_region->Constant_bounds(0); 00105 } 00106 00107 //----------------------------------------------------------------------- 00108 // NAME: RESHAPE::Reshape_Callee_To_Caller 00109 // FUNCTION: Reshape the callee to the caller. (This does not include 00110 // handling any passed section). We return the PROJECTED_REGION re- 00111 // shaped to the caller, if the reshaping is successful, and NULL 00112 // otherwise. 00113 //----------------------------------------------------------------------- 00114 00115 PROJECTED_REGION* RESHAPE::Reshape_Callee_To_Caller(BOOL trace) 00116 { 00117 00118 #ifdef Is_True_On 00119 if (trace) { 00120 fprintf(TFile, "RESHAPE::Perform_Reshape\n"); 00121 } 00122 #endif 00123 00124 Is_True(_callee_proj_region != NULL && _caller_shape_proj_region != NULL, 00125 ("Reshape_Callee_To_Caller: NULL projected region\n")); 00126 00127 UINT depth = _caller_shape_proj_region->Get_depth(); 00128 UINT num_dims = _caller_shape_proj_region->Get_num_dims(); 00129 00130 // Screen out cases where: 00131 // - callee region is messy, or 00132 // - the actual passed is messy, or 00133 // - we have non-constant region reshaping 00134 if (_callee_proj_region->Is_messy_region() || 00135 _callee_proj_region->Has_Messy_Bounds() || 00136 _caller_shape_proj_region->Is_messy_region() || 00137 _caller_shape_proj_region->Has_Important_Messy_Bounds() || 00138 (_callsite_region && (_callsite_region->Is_messy_region() || 00139 _callsite_region->Has_Messy_Bounds())) || 00140 ! Constant_Type_Reshape()) { 00141 _callee_proj_reshaped_region = 00142 CXX_NEW (PROJECTED_REGION (MESSY_REGION, depth, num_dims, _m), _m); 00143 } else { 00144 // Handle the case where is the section is a constant 00145 // and the caller shape bounds for all except the last 00146 // is also a constant. The number of dimensions being reshaped 00147 // to and from should not matter 00148 _callee_proj_reshaped_region = Reshape_Constant_Shape(); 00149 } 00150 00151 #ifdef Is_True_On 00152 if (trace) { 00153 fprintf(TFile, " callee_proj_reshaped_region: "); 00154 _callee_proj_reshaped_region->Print(TFile); 00155 } 00156 #endif 00157 00158 Is_True(_callee_proj_reshaped_region->Get_num_dims() == num_dims, 00159 ("Reshape_Callee_To_Caller: Dims reshaped callee (%d) != caller shape (%d)", 00160 num_dims, _callee_proj_reshaped_region->Get_num_dims())); 00161 00162 return _callee_proj_reshaped_region; 00163 } 00164 00165 //----------------------------------------------------------------------- 00166 // NAME: Linearize_Shape 00167 // FUNCTION: Return values for 'lin_lower', 'lin_upper', and 'lin_stride', 00168 // the linearized dimensions of the 'pr_callee' currently shaped as 00169 // 'pr_callee_shape'. 00170 //----------------------------------------------------------------------- 00171 00172 static void Linearize_Shape(PROJECTED_REGION* pr_callee, 00173 PROJECTED_REGION* pr_callee_shape, 00174 INT* lin_lower, 00175 INT* lin_upper, 00176 INT* lin_stride) 00177 { 00178 // compute the upper bound on region size from the _callee_proj_region 00179 *lin_upper = 0; 00180 *lin_lower = 0; 00181 INT dim_size = 1; 00182 INT last_callee_dim = pr_callee->Get_num_dims() - 1; 00183 for (INT i = last_callee_dim; i >= 0; i--) { 00184 PROJECTED_NODE* region_node = pr_callee->Get_projected_node(i); 00185 LINEX* stride = region_node->Get_step_linex(); 00186 LINEX* ub = region_node->Get_upper_linex(); 00187 LINEX* lb = region_node->Get_lower_linex(); 00188 if (i == last_callee_dim) { 00189 Is_True(stride->Num_terms() == 0 00190 && stride->Get_term(0)->Get_type() == LTKIND_CONST, 00191 ("Linearize_Shape: Dim %d ub for callee is NOT constant", i)); 00192 *lin_stride = stride->Get_constant_term(); 00193 } 00194 Is_True(ub->Num_terms() == 0 00195 && ub->Get_term(0)->Get_type() == LTKIND_CONST, 00196 ("Linearize_Shape: Dim %d ub for callee is NOT constant", i)); 00197 Is_True(lb->Num_terms() == 0 00198 && lb->Get_term(0)->Get_type() == LTKIND_CONST, 00199 ("Linearize_Shape: Dim %d lb for callee is NOT constant", i)); 00200 *lin_upper += ub->Get_constant_term() * dim_size; 00201 *lin_lower += lb->Get_constant_term() * dim_size; 00202 // Get the dimension sizes from the callee shape 00203 if (i != 0) { 00204 PROJECTED_NODE* node = pr_callee_shape->Get_projected_node(i); 00205 LINEX* upper = node->Get_upper_linex(); 00206 LINEX* lower = node->Get_lower_linex(); 00207 Is_True(upper->Num_terms() == 0 00208 && upper->Get_term(0)->Get_type() == LTKIND_CONST, 00209 ("Linearize_Shape: Dim %d ub for callee shape is NOT constant", i)); 00210 Is_True(lower->Num_terms() == 0 00211 && lower->Get_term(0)->Get_type() == LTKIND_CONST, 00212 ("Linearize_Shape: Dim %d lb for callee shape is NOT constant", i)); 00213 dim_size *= abs(upper->Get_constant_term() 00214 - lower->Get_constant_term() + 1); 00215 } 00216 } 00217 } 00218 00219 //----------------------------------------------------------------------- 00220 // NAME: Dim_Length 00221 // FUNCTION: Return the length of the 'k'th dimension of 'pr_shape'. 00222 //----------------------------------------------------------------------- 00223 00224 static INT Dim_Length(PROJECTED_REGION* pr_shape, 00225 INT k) 00226 { 00227 PROJECTED_NODE* p = pr_shape->Get_projected_node(k); 00228 Is_True(!p->Is_messy_ub(), ("Dim_Length: Messy upper bound")); 00229 Is_True(!p->Is_messy_lb(), ("Dim_Length: Messy lower bound")); 00230 Is_True(!p->Is_messy_step(), ("Dim_Length: Messy step")); 00231 Is_True(p->Get_upper_linex()->Is_const(), 00232 ("Dim_Length: Non-constant upper bound")); 00233 Is_True(p->Get_lower_linex()->Is_const(), 00234 ("Dim_Length: Non-constant lower bound")); 00235 Is_True(p->Get_step_linex()->Is_const(), 00236 ("Dim_Length: Non-constant step")); 00237 INT upper_val = p->Get_upper_linex()->Get_term(0)->Get_coeff(); 00238 INT lower_val = p->Get_lower_linex()->Get_term(0)->Get_coeff(); 00239 INT step_val = p->Get_step_linex()->Get_term(0)->Get_coeff(); 00240 Is_True(lower_val == 0, ("Dim_Length: Expecting shape lower bound of 0")); 00241 Is_True(step_val == 1, ("Dim_Length: Expecting shape step of 1")); 00242 return upper_val + 1; 00243 } 00244 00245 //----------------------------------------------------------------------- 00246 // NAME: Delinearize_Shape 00247 // FUNCTION: Delinearize the 'pr_caller' into 'pr_caller_shape' from the 00248 // linearized section with lower bound 'lin_lower', upper bound 00249 // 'lin_upper' and stride 'lin_stride'. Fill in the 'lb_caller_dim' 00250 // to 'ub_caller_dim - 1' dimensions of 'pr_caller' with the result 00251 // (which has a total of 'total_dims' dimensions). 00252 //----------------------------------------------------------------------- 00253 00254 static void Delinearize_Shape(PROJECTED_REGION* pr_caller, 00255 PROJECTED_REGION* pr_caller_shape, 00256 INT lin_lower, 00257 INT lin_upper, 00258 INT lin_stride, 00259 INT lb_caller_dim, 00260 INT ub_caller_dim, 00261 INT total_dims) 00262 { 00263 INT lb_current = lin_lower; 00264 INT ub_current = lin_upper; 00265 BOOL fill_in_max = FALSE; 00266 for (INT j = lb_caller_dim; j < ub_caller_dim; j++) { 00267 INT dim_size = 1; 00268 for (INT k = j + 1; k < total_dims; k++) 00269 dim_size *= Dim_Length(pr_caller_shape, k); 00270 INT lb_current_dim = -1; 00271 INT ub_current_dim = -1; 00272 if (fill_in_max) { 00273 PROJECTED_NODE* p = pr_caller_shape->Get_projected_node(j); 00274 lb_current_dim = 0; 00275 ub_current_dim = p->Get_upper_linex()->Get_term(0)->Get_coeff(); 00276 } else { 00277 lb_current_dim = lb_current / dim_size; 00278 ub_current_dim = ub_current / dim_size; 00279 } 00280 PROJECTED_NODE* pn_return = pr_caller->Get_projected_node(j); 00281 INT stride = j == total_dims - 1 ? lin_stride : 1; 00282 pn_return->Set_constant_linexs(ub_current_dim, lb_current_dim, 00283 lin_stride, 0, 0); 00284 lb_current -= lb_current_dim * dim_size; 00285 ub_current -= ub_current_dim * dim_size; 00286 if (lb_current_dim < ub_current_dim) 00287 fill_in_max = TRUE; 00288 } 00289 } 00290 00291 //----------------------------------------------------------------------- 00292 // NAME: RESHAPE::Reshape_Constant_Shape 00293 // FUNCTION: Reshape the constant dimensioned callee-based projected 00294 // region into a constant dimensioned caller-based projected region. 00295 //----------------------------------------------------------------------- 00296 00297 PROJECTED_REGION* RESHAPE::Reshape_Constant_Shape(BOOL trace) 00298 { 00299 00300 #ifdef Is_True_On 00301 if (trace) { 00302 fprintf(TFile, "RESHAPE::Reshape_Constant_Shape\n"); 00303 } 00304 #endif 00305 00306 Is_True(Constant_Type_Reshape(), 00307 ("Reshape_Constant_Shape: Expecting constant shapes")); 00308 00309 UINT caller_depth = _caller_shape_proj_region->Get_depth(); 00310 UINT caller_dims = _caller_shape_proj_region->Get_num_dims(); 00311 PROJECTED_REGION* region = 00312 CXX_NEW(PROJECTED_REGION(NON_MESSY_REGION,caller_depth,caller_dims,_m),_m); 00313 00314 // Linearize from the callee. 00315 INT lin_upper = 0; 00316 INT lin_lower = 0; 00317 INT lin_stride = 0; 00318 Linearize_Shape(_callee_proj_region, _callee_shape_proj_region, 00319 &lin_lower, &lin_upper, &lin_stride); 00320 00321 #ifdef Is_True_On 00322 if (trace) { 00323 fprintf(TFile, " Linearized callee_projected_region: [%d:%d:1]\n", 00324 lin_lower, lin_upper); 00325 } 00326 #endif 00327 00328 Is_True(lin_upper >= lin_lower, 00329 ("Reshape_Constant_Shape: After linearization lb (%d) > ub (%d)\n", 00330 lin_lower, lin_upper)); 00331 00332 // Determine if we are working with two-strided segments 00333 INT segment_length = -1; 00334 INT segment_stride = -1; 00335 PROJECTED_NODE* pr_node = _callee_proj_region->Get_projected_node(0); 00336 if (pr_node->Get_segment_length_linex() != NULL 00337 && pr_node->Get_segment_length_linex()->Is_const() 00338 && pr_node->Get_segment_length_linex()->Is_const()) { 00339 segment_length = pr_node->Get_segment_length_linex()->Get_constant_term(); 00340 segment_stride = pr_node->Get_segment_stride_linex()->Get_constant_term(); 00341 } 00342 00343 // Delinearize into the caller. 00344 if (segment_stride == -1) { 00345 Delinearize_Shape(region, _caller_shape_proj_region, lin_lower, 00346 lin_upper, lin_stride, 0, caller_dims, caller_dims); 00347 } else { 00348 INT stride_dims = 0; 00349 INT local_stride = 1; 00350 for (INT i = caller_dims - 1; i >= 0; i--) { 00351 stride_dims++; 00352 local_stride *= Dim_Length(_caller_shape_proj_region, i); 00353 if (local_stride >= segment_stride) 00354 break; 00355 } 00356 if (local_stride != segment_stride) { 00357 Delinearize_Shape(region, _caller_shape_proj_region, lin_lower, 00358 lin_upper, lin_stride, 0, caller_dims, caller_dims); 00359 } else { 00360 Delinearize_Shape(region, _caller_shape_proj_region, lin_lower, 00361 lin_upper, 1, 0, caller_dims - stride_dims, caller_dims); 00362 Delinearize_Shape(region, _caller_shape_proj_region, 0, 00363 segment_length - 1, lin_stride, caller_dims - stride_dims, 00364 caller_dims, caller_dims); 00365 } 00366 } 00367 00368 return region; 00369 } 00370 00371 //----------------------------------------------------------------------- 00372 // NAME: RESHAPE::Reshapeable_Passed_Section 00373 // FUNCTION: Return TRUE if the section passed can be added to the caller 00374 // reshape section without violating the constraints of the caller 00375 // shapes bounds. Return FALSE otherwise. 00376 //----------------------------------------------------------------------- 00377 00378 BOOL RESHAPE::Reshapeable_Passed_Section(BOOL trace) 00379 { 00380 00381 #ifdef Is_True_On 00382 if (trace) { 00383 fprintf(TFile, "RESHAPE::Actual_Passed_Reshapable\n"); 00384 } 00385 #endif 00386 00387 Is_True(_callsite_region != NULL, 00388 ("Actual_Passed_Reshapeable: NULL callsite region")); 00389 00390 if (_callsite_region->Is_messy_region()) { 00391 return FALSE; 00392 } 00393 00394 Is_True(_callsite_region->Is_unprojected_region(), 00395 ("Actual_Passed_Reshapeable: Projected callsite region")); 00396 00397 for (INT i = 1; i < _callsite_region->Get_num_dims(); i++) { 00398 PROJECTED_NODE* pn_callsite 00399 = _callsite_region->Get_projected_node(i); 00400 PROJECTED_NODE* pn_caller_shape 00401 = _caller_shape_proj_region->Get_projected_node(i); 00402 PROJECTED_NODE* pn_caller 00403 = _callee_proj_reshaped_region->Get_projected_node(i); 00404 LINEX* lx_callsite = pn_callsite->Get_lower_linex(); 00405 LINEX* lx_caller_lower = pn_caller->Get_lower_linex(); 00406 LINEX* lx_caller_upper = pn_caller->Get_upper_linex(); 00407 LINEX* lx_caller_shape_lower = pn_caller_shape->Get_lower_linex(); 00408 LINEX* lx_caller_shape_upper = pn_caller_shape->Get_upper_linex(); 00409 LINEX* lx_caller_diff = lx_caller_upper->Subtract(lx_caller_lower); 00410 lx_caller_diff->Simplify(); 00411 00412 #ifdef Is_True_On 00413 if (trace) { 00414 fprintf(TFile, " dim[%d] - ", i); 00415 fprintf(TFile, "callsite: "); 00416 pn_callsite->Print(TFile); 00417 fprintf(TFile, " caller_shape: "); 00418 pn_caller_shape->Print(TFile); 00419 } 00420 #endif 00421 00422 if (!lx_caller_diff->Is_const() 00423 || lx_caller_diff->Get_constant_term() != 0) { 00424 LINEX* lx_high = lx_caller_upper->Merge(lx_callsite); 00425 LINEX* lx_over = lx_high->Subtract(lx_caller_shape_upper); 00426 if (!lx_over->Is_const() || lx_over->Get_constant_term() > 0) 00427 return FALSE; 00428 LINEX* lx_low = lx_caller_lower->Merge(lx_callsite); 00429 LINEX* lx_under = lx_low->Subtract(lx_caller_shape_lower); 00430 if (!lx_under->Is_const() || lx_under->Get_constant_term() > 0) 00431 return FALSE; 00432 } 00433 } 00434 00435 return TRUE; 00436 } 00437 00438 //----------------------------------------------------------------------- 00439 // NAME: RESHAPE::Reshape_Passed_Section 00440 // FUNCTION: Add the callsite to the 'callee_reshaped' section to get 00441 // the final reshaped result. 00442 //----------------------------------------------------------------------- 00443 00444 void RESHAPE::Reshape_Passed_Section(PROJECTED_REGION* callee_reshaped, 00445 BOOL trace) 00446 { 00447 00448 #ifdef Is_True_On 00449 if (trace) { 00450 fprintf(TFile, "RESHAPE::Reshape_Passed_Section\n"); 00451 } 00452 #endif 00453 00454 INT num_dims = callee_reshaped->Get_num_dims(); 00455 for (INT dim_idx = 0; dim_idx < num_dims; dim_idx++) { 00456 PROJECTED_NODE* pn_callsite = _callsite_region->Get_projected_node(dim_idx); 00457 LINEX* lx_callsite = pn_callsite->Get_lower_linex(); 00458 PROJECTED_NODE* pn_reshaped = callee_reshaped->Get_projected_node(dim_idx); 00459 LINEX* lx_lower = lx_callsite->Merge(pn_reshaped->Get_lower_linex()); 00460 LINEX* lx_upper = lx_callsite->Merge(pn_reshaped->Get_upper_linex()); 00461 pn_reshaped->Get_lower_linex()->Free_terms(); 00462 pn_reshaped->Set_lower_linex(lx_lower); 00463 00464 INT i; 00465 00466 for (i = 0; i <= pn_reshaped->Get_lower_linex()->Num_terms(); i++) { 00467 TERM* tm = pn_reshaped->Get_lower_linex()->Get_term(i); 00468 switch (tm->Get_type()) { 00469 case LTKIND_LINDEX: 00470 case LTKIND_SUBSCR: 00471 pn_reshaped->Set_messy_lb(); 00472 break; 00473 } 00474 } 00475 00476 pn_reshaped->Get_upper_linex()->Free_terms(); 00477 pn_reshaped->Set_upper_linex(lx_upper); 00478 00479 for (i = 0; i <= pn_reshaped->Get_upper_linex()->Num_terms(); i++) { 00480 00481 TERM* tm = pn_reshaped->Get_upper_linex()->Get_term(i); 00482 switch (tm->Get_type()) { 00483 case LTKIND_LINDEX: 00484 case LTKIND_SUBSCR: 00485 pn_reshaped->Set_messy_ub(); 00486 break; 00487 } 00488 } 00489 } 00490 00491 00492 #ifdef Is_True_On 00493 if (trace) { 00494 fprintf(TFile, "New reshaped section\n"); 00495 callee_reshaped->Print(TFile); 00496 } 00497 #endif 00498 00499 }