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 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