Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
standardize.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 
00037 #ifdef USE_PCH
00038 #include "be_com_pch.h"
00039 #endif /* USE_PCH */
00040 #pragma hdrstop
00041 #include "defs.h"
00042 #include "stab.h"
00043 #include "wn.h"
00044 #include "config_targ.h"
00045 #include "wn_simp.h"
00046 #include "wio.h"
00047 #include "targ_const.h"
00048 #include "const.h"
00049 #include "strtab.h"
00050 #include "config.h"
00051 #include "wn_util.h"
00052 #include "fb_whirl.h"
00053 
00054 /*-----------------------------------------------------------------------
00055 // NAME: WN_Symbol_Count 
00056 // FUNCTION: For the tree rooted at 'wn', return the number of nodes with 
00057 //   the given 'symbol' and 'offset'.  
00058 //---------------------------------------------------------------------*/
00059 
00060 static INT WN_Symbol_Count(WN *wn,              
00061                            ST_IDX symbol, 
00062                            WN_OFFSET offset)
00063 {
00064   INT k = 0; 
00065   INT rval = 0; 
00066   rval = (WN_operator(wn) == OPR_LDID &&
00067           symbol == WN_st_idx(wn) && offset == WN_offset(wn)) 
00068     ? 1 : 0;
00069   for (k = 0; k < WN_kid_count(wn); k++)
00070     rval += WN_Symbol_Count(WN_kid(wn,k), symbol, offset);
00071   return rval;
00072 }
00073 
00074 /*-----------------------------------------------------------------------
00075 // NAME: WN_Flip_Le_And_Ge 
00076 // FUNCTION: Flip the left and right hand sides of an expression with 
00077 //   OPR_GE, OPR_LE, OPR_GT, or OPR_LT as the operator of the expression 
00078 //   root 'wn'.  
00079 //---------------------------------------------------------------------*/
00080 
00081 static void WN_Flip_Le_And_Ge(WN *wn)
00082 {
00083   OPCODE    opc;
00084   OPERATOR  opr; 
00085 
00086   opc = WN_opcode(wn);
00087   opr = OPCODE_operator(opc);
00088   switch (opr) {
00089    case OPR_GE: opr = OPR_LE; break;
00090    case OPR_LE: opr = OPR_GE; break;
00091    case OPR_GT: opr = OPR_LT; break;
00092    case OPR_LT: opr = OPR_GT; break;
00093    default: FmtAssert(0, ("Bad call to Flip_Le_And_Ge")); break;
00094   }
00095 
00096   WN_set_opcode(wn, OPCODE_make_op(opr, OPCODE_rtype(opc), OPCODE_desc(opc)));
00097 }
00098 
00099 /*-----------------------------------------------------------------------
00100 // NAME: WN_Solve_For 
00101 // FUNCTION: For the expression 'wn_top', solve this in terms of the 
00102 //   variable given by 'symbol' and 'offset'.  Return TRUE if we knew 
00103 //   how to solve, FALSE otherwise. 
00104 //---------------------------------------------------------------------*/
00105 
00106 static BOOL WN_Solve_For(WN *wn_top, 
00107                          ST_IDX symbol,
00108                          WN_OFFSET offset)
00109 {
00110   BOOL ok = FALSE;
00111   BOOL use_ceil = FALSE;
00112   INT lcount = 0; 
00113   INT rcount = 0;
00114   INT v = 0; 
00115   INTRINSIC intrnceil = INTRINSIC_NONE;
00116   INTRINSIC intrnfloor = INTRINSIC_NONE;
00117   WN *l = NULL; 
00118   WN *r = NULL; 
00119   WN *wn0 = NULL; 
00120   WN *ll = NULL;  
00121   WN *lr = NULL;  
00122   OPCODE lopc; 
00123   OPCODE negop;
00124   OPCODE newopc; 
00125   OPCODE lropc;
00126   OPERATOR lopr; 
00127   TYPE_ID  type;
00128   OPERATOR opr_base; 
00129    
00130   opr_base = WN_operator(wn_top);
00131   FmtAssert(opr_base == OPR_GT || opr_base == OPR_LT || opr_base == OPR_LE
00132     || opr_base == OPR_GE, ("Solve_For() called with bad RELOP"));
00133  
00134   lcount = WN_Symbol_Count(WN_kid0(wn_top), symbol, offset);
00135   rcount = WN_Symbol_Count(WN_kid1(wn_top), symbol, offset);
00136   if (!(lcount == 1 && rcount == 0) && !(lcount == 0 && rcount == 1)) {
00137     return FALSE;
00138   }
00139 
00140   /* put variable on lhs for the moment */
00141   if (rcount) {
00142     WN_Flip_Le_And_Ge(wn_top);
00143     wn0 = WN_kid0(wn_top);
00144     WN_kid0(wn_top) = WN_kid1(wn_top);
00145     WN_kid1(wn_top) = wn0;
00146   }
00147 
00148   l = WN_kid0(wn_top);
00149   r = WN_kid1(wn_top);
00150   while (1) {
00151     /* 
00152      * invariant at this location: the index is somewhere on the left (l))
00153      * invariant at this location: l and r will be wn_top's kids
00154      */
00155   
00156     lopc = WN_opcode(l);
00157     lopr = OPCODE_operator(lopc);
00158 
00159     /* have we successfully solved for the index variable? */
00160     if (OPCODE_is_load(lopc)) {
00161       ok = TRUE;
00162       break;
00163     }
00164 
00165     if (lopr == OPR_NEG) {
00166       WN_Flip_Le_And_Ge(wn_top);
00167       type = WN_rtype(r);
00168       negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
00169       r = WN_CreateExp1(negop, r);
00170       l = WN_kid0(l);
00171       continue;
00172     }
00173 
00174     /* A CVT of an expression containing the index varible
00175      * or any other single kid node is bad news at this point.
00176      */
00177     if (lopr == OPR_CVT || WN_kid_count(l) == 1)
00178       return FALSE;
00179 
00180     lcount = WN_Symbol_Count(WN_kid0(l), symbol, offset);
00181     rcount = WN_Symbol_Count(WN_kid1(l), symbol, offset);
00182 
00183     Is_True((lcount == 1 && rcount == 0) ||
00184             (lcount == 0 && rcount == 1),
00185             ("Impossible: Counts messed up %d %d", lcount, rcount));
00186 
00187     if (rcount) {
00188       if (lopr == OPR_SUB) {
00189         /* 
00190          * in order to commute below, must change sign and mul right size
00191          * through by -1.
00192          */ 
00193         WN_Flip_Le_And_Ge(wn_top);
00194         type = WN_rtype(r);
00195         negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
00196         r = WN_CreateExp1(negop, r);
00197       }
00198       else if (lopr != OPR_ADD && lopr != OPR_MPY) /* commutative */
00199         break;
00200       wn0 = WN_kid0(l);
00201       WN_kid0(l) = WN_kid1(l);
00202       WN_kid1(l) = wn0;
00203     }
00204 
00205     ll = WN_kid0(l);
00206     lr = WN_kid1(l);
00207 
00208     if (lopr == OPR_MPY) {
00209       type = OPCODE_rtype(lopc);
00210 
00211       /* the intrinsics */ 
00212       switch (type) {
00213        case MTYPE_I4:
00214         intrnceil = INTRN_I4DIVCEIL; intrnfloor = INTRN_I4DIVFLOOR; break;
00215        case MTYPE_I8:
00216         intrnceil = INTRN_I8DIVCEIL; intrnfloor = INTRN_I8DIVFLOOR; break;
00217        case MTYPE_U4:
00218         intrnceil = INTRN_U4DIVCEIL; intrnfloor = INTRN_U4DIVFLOOR; break;
00219        case MTYPE_U8:
00220         intrnceil = INTRN_U8DIVCEIL; intrnfloor = INTRN_U8DIVFLOOR; break;
00221        default:
00222         goto out;        /* escape before we change any code. */
00223       }
00224 
00225       /* 
00226        * rhs of mul must be a const so we know if we are dividing
00227        * through by a positive or negative.  Besides, it fits the
00228        * expected normalized pattern.
00229        */ 
00230 
00231       lropc = WN_opcode(lr);
00232       if (OPCODE_operator(lropc) != OPR_INTCONST)
00233         break;
00234 
00235       v = WN_const_val(lr);
00236       if (v < 0) {
00237         WN_Flip_Le_And_Ge(wn_top);
00238         WN_const_val(lr) = -v;
00239         negop = OPCODE_make_op(OPR_NEG, OPCODE_rtype(lropc), MTYPE_V);
00240         r = WN_CreateExp1(negop, r);
00241       }
00242 
00243       use_ceil = WN_operator(wn_top) == OPR_GE 
00244         || WN_operator(wn_top) == OPR_LT;
00245       newopc = OPCODE_make_op(OPR_INTRINSIC_OP, type, MTYPE_V);
00246 
00247       r = WN_CreateExp2(newopc, r, lr);
00248       WN_intrinsic(r) = use_ceil ? intrnceil : intrnfloor;
00249       WN_Delete(l);
00250       l = ll;
00251     }
00252     else if (lopr == OPR_ADD || lopr == OPR_SUB) {
00253       WN_kid0(l) = r;
00254       WN_kid1(l) = lr;
00255       r = l;
00256       l = ll;
00257       WN_set_opcode(r, OPCODE_make_op(lopr == OPR_ADD ? OPR_SUB : OPR_ADD,
00258                                       OPCODE_rtype(lopc), OPCODE_desc(lopc)));
00259     }
00260     else
00261       return FALSE;
00262   }
00263 
00264  out:
00265 
00266   WN_kid0(wn_top) = l;
00267   WN_kid1(wn_top) = r;
00268 
00269   return ok;
00270 }
00271 
00272 
00273 /*-----------------------------------------------------------------------
00274 // NAME: WN_Upper_Bound_Standardize 
00275 // FUNCTION: For the do loop 'doloop' with upper bound 'ub', put that 
00276 //   bound in standard form, if possible.  If 'ok_to_fail', return 
00277 //   FALSE if we can't standardize the upper bound, otherwise assert. 
00278 //   Return TRUE if we can standardize. 
00279 //---------------------------------------------------------------------*/
00280 
00281 extern "C" BOOL
00282 WN_Upper_Bound_Standardize(WN   *doloop, 
00283                            WN   *ub, 
00284                            BOOL  ok_to_fail)
00285 {
00286   OPCODE opc; 
00287   OPERATOR opr; 
00288   TYPE_ID desc; 
00289   OPCODE subop; 
00290   OPCODE intconst_opc; 
00291   WN *ub1 = NULL; 
00292   WN *wn_const = NULL;
00293   BOOL ok = FALSE; 
00294   WN *wn_tmp = NULL;  
00295 
00296   FmtAssert(WN_opcode(doloop) == OPC_DO_LOOP, ("Bad ub passed"));
00297   if (WN_operator(WN_end(doloop)) == OPR_GT) {
00298     WN_Flip_Le_And_Ge(ub); 
00299     wn_tmp = WN_kid0(ub); 
00300     WN_kid0(ub) = WN_kid1(ub); 
00301     WN_kid1(ub) = wn_tmp; 
00302   }
00303   if (WN_operator(WN_end(doloop)) == OPR_LT) {
00304     /* change i < b to i <= b-1 */
00305     desc = WN_desc(WN_end(doloop));
00306     WN_set_opcode(ub, OPCODE_make_op(OPR_LE, 
00307       WN_rtype(WN_end(doloop)), desc));
00308     subop = OPCODE_make_op(OPR_SUB, desc, MTYPE_V);
00309     intconst_opc = OPCODE_make_op(OPR_INTCONST, desc, MTYPE_V);
00310     wn_const = WN_CreateIntconst(intconst_opc, 1);
00311     ub1 = WN_CreateExp2(subop, WN_kid1(ub), wn_const); 
00312     ub1 = WN_Simplify_Tree(ub1); 
00313     WN_kid1(ub) = ub1;
00314   }
00315   WN_kid1(WN_end(doloop)) = WN_Simplify_Tree(WN_kid1(WN_end(doloop))); 
00316   ok = WN_Solve_For(WN_end(doloop), WN_st_idx(WN_index(doloop)),
00317     WN_offset(WN_index(doloop)));
00318   opc = WN_opcode(ub = WN_end(doloop));
00319   opr = OPCODE_operator(opc);
00320   FmtAssert(opr == OPR_LT || opr == OPR_LE,
00321             ("surprise operator %s returned from WN_Solve_For()",
00322              OPCODE_name(opc)));
00323   if (ok == FALSE) {
00324     FmtAssert(ok_to_fail, 
00325       ("Upper_Bound_Standardize() could not solve for induction variable")); 
00326     return FALSE;
00327   }
00328   WN_kid1(WN_end(doloop)) = WN_Simplify_Tree(WN_kid1(WN_end(doloop))); 
00329   return ok;
00330 }
00331 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines