Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
reshape.cxx
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines