00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifdef USE_PCH
00038 #include "be_com_pch.h"
00039 #endif
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
00056
00057
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
00076
00077
00078
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
00101
00102
00103
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
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
00153
00154
00155
00156 lopc = WN_opcode(l);
00157 lopr = OPCODE_operator(lopc);
00158
00159
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
00175
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
00191
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)
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
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;
00223 }
00224
00225
00226
00227
00228
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
00275
00276
00277
00278
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
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