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
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #ifdef USE_PCH
00062 #include "lno_pch.h"
00063 #endif // USE_PCH
00064 #pragma hdrstop
00065
00066 static const char *source_file = __FILE__;
00067
00068 #ifdef _KEEP_RCS_ID
00069 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.al_loop.cxx $ $Revision: 1.5 $";
00070 #endif
00071
00072 #include <sys/types.h>
00073 #include <ctype.h>
00074 #include <limits.h>
00075 #include <alloca.h>
00076
00077 #include "pu_info.h"
00078 #include "lnopt_main.h"
00079 #include "lnoutils.h"
00080 #include "lwn_util.h"
00081 #include "snl_utils.h"
00082 #include "lego_pragma.h"
00083 #include "lego_util.h"
00084 #include "array_lower.h"
00085 #include "al_loop.h"
00086 #include "errors.h"
00087 #include "erbe.h"
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static void Find_Array_Expr(WN *curr_nd);
00098 static mBOOL Is_Reshaped_Array_Expr(const WN *curr_nd, DISTR_ARRAY **dact);
00099 static mBOOL Is_Reshaped_Array_Param(const WN *curr_nd, DISTR_ARRAY **dact);
00100 static void Check_Invalid_Accesses(const WN *curr_nd);
00101
00102 static ST *Get_Reshaped_Array_St(const WN *array_expr, mBOOL *valid);
00103 static mBOOL Is_Allowed_Invalid_Access(const WN *curr_nd);
00104 static mBOOL Is_Array_Base(const WN *curr_nd);
00105 static mBOOL Is_Array_Param(const WN *curr_nd);
00106 static WN *Get_Memop_Parent(const WN *curr_nd);
00107 static mBOOL Has_Reshaped_Type(ST *array_st);
00108 static DISTR_ARRAY *Lookup_Array_Distr(ST *array_st);
00109
00110
00111
00112
00113
00114 ARRAY_LOWER_LOOP::~ARRAY_LOWER_LOOP()
00115 {
00116 while (_children.Elements()) CXX_DELETE (_children.Pop(), LEGO_pool);
00117 while (_array_refs.Elements()) CXX_DELETE (_array_refs.Pop(), LEGO_pool);
00118 }
00119
00120
00121
00122
00123
00124 ARRAY_LOWER_LOOP *ARRAY_LOWER_LOOP::Get_Ancestor(INT n)
00125 {
00126 ARRAY_LOWER_LOOP *curr_loop = this;
00127 INT curr_num = 0;
00128
00129 while (curr_loop && (curr_num < n)) {
00130 curr_loop = curr_loop->Parent();
00131 curr_num++;
00132 }
00133
00134 return curr_loop;
00135 }
00136
00137
00138 LEGO_INFO *ARRAY_LOWER_LOOP::Get_Lego_Info()
00139 {
00140 Is_True(Doloop() && (WN_operator(Doloop()) == OPR_DO_LOOP),
00141 ("ARRAY_LOWER_LOOP::Get_Lego_Info: called with bad do loop\n"));
00142
00143 DO_LOOP_INFO *loop_info = Get_Do_Loop_Info(Doloop());
00144 LEGO_INFO *lego_info = loop_info->Lego_Info;
00145
00146 return (lego_info);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 void ARRAY_LOWER_LOOP::Build_Loop(WN *curr_nd)
00156 {
00157 WN *kid;
00158
00159 if (!curr_nd) return;
00160
00161 if (WN_opcode(curr_nd) == OPC_BLOCK) {
00162 kid = WN_first(curr_nd);
00163 while (kid) {
00164
00165 if (WN_opcode(kid) == OPC_DO_LOOP) {
00166 ARRAY_LOWER_LOOP *child_node =
00167 CXX_NEW(ARRAY_LOWER_LOOP(this, kid, Depth()+1), LEGO_pool);
00168 _children.Push(child_node);
00169 child_node->Build_Loop(kid);
00170 } else {
00171 Build_Loop(kid);
00172 }
00173
00174 kid = WN_next(kid);
00175 }
00176 return;
00177 }
00178
00179 for (INT kidno = 0; kidno < WN_kid_count(curr_nd); kidno++) {
00180 kid = WN_kid(curr_nd, kidno);
00181
00182 if (WN_opcode(kid) == OPC_DO_LOOP) {
00183 ARRAY_LOWER_LOOP *child_node =
00184 CXX_NEW(ARRAY_LOWER_LOOP(this, kid, Depth()+1), LEGO_pool);
00185 _children.Push(child_node);
00186 child_node->Build_Loop(kid);
00187 } else {
00188 Build_Loop(kid);
00189 }
00190 }
00191
00192 Build_Refs(curr_nd);
00193 }
00194
00195
00196
00197
00198
00199 void ARRAY_LOWER_LOOP::Build_Refs(WN *curr_nd)
00200 {
00201 DISTR_ARRAY *dact = NULL;
00202
00203 if (Is_Reshaped_Array_Expr(curr_nd, &dact)) {
00204 ARRAY_LOWER_REF *ref =
00205 CXX_NEW(ARRAY_LOWER_REF(curr_nd, dact, this, FALSE), LEGO_pool);
00206 Add_Ref(ref);
00207
00208 } else if (Is_Reshaped_Array_Param(curr_nd, &dact)) {
00209 ARRAY_LOWER_REF *ref =
00210 CXX_NEW(ARRAY_LOWER_REF(curr_nd, dact, this, TRUE), LEGO_pool);
00211 Add_Ref(ref);
00212
00213 } else {
00214 Check_Invalid_Accesses(curr_nd);
00215 }
00216 }
00217
00218
00219 void ARRAY_LOWER_LOOP::Process_Loop(void)
00220 {
00221 INT i;
00222
00223 for (i = 0; i < _children.Elements(); i++) {
00224 _children.Bottom_nth(i)->Process_Loop();
00225 }
00226
00227 Process_Refs();
00228 }
00229
00230
00231 void ARRAY_LOWER_LOOP::Process_Refs(void)
00232 {
00233 INT i;
00234
00235 for (i = 0; i < _array_refs.Elements(); i++) {
00236 _array_refs.Bottom_nth(i)->Lower_Ref();
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 mBOOL
00250 Is_Reshaped_Array_Expr(const WN *curr_nd,
00251 DISTR_ARRAY **dact)
00252 {
00253 *dact = NULL;
00254 ST *array_st = NULL;
00255
00256
00257
00258
00259 if (WN_operator(curr_nd) == OPR_ARRAY) {
00260 mBOOL valid = TRUE;
00261 array_st = Get_Reshaped_Array_St(curr_nd, &valid);
00262
00263 if (array_st) {
00264 *dact = Lookup_Array_Distr(array_st);
00265
00266 if (*dact) {
00267 DISTR_INFO *dinfo = (*dact)->Dinfo();
00268
00269 if (!valid) {
00270 ErrMsgSrcpos (EC_LNO_Generic2String, LWN_Get_Linenum(curr_nd),
00271 "Suspicious reference to reshaped array, lowering anyway",
00272 ST_name(array_st));
00273 return TRUE;
00274 } else if (dinfo->Num_Dim() != WN_num_dim(curr_nd)) {
00275 ErrMsgSrcpos (EC_LNO_Generic2String, LWN_Get_Linenum(curr_nd),
00276 "Bad reference to reshaped array (mismatch in number of dimensions)",
00277 ST_name(array_st));
00278 } else {
00279 return TRUE;
00280 }
00281 }
00282 }
00283 }
00284
00285 return FALSE;
00286 }
00287
00288
00289
00290
00291
00292 mBOOL
00293 Is_Reshaped_Array_Param(const WN *curr_nd,
00294 DISTR_ARRAY **dact)
00295 {
00296 *dact = NULL;
00297
00298 if (Is_Array_Param(curr_nd)) {
00299
00300 ST *array_st = WN_st(curr_nd);
00301
00302 if (array_st) {
00303 *dact = Lookup_Array_Distr(array_st);
00304 if (*dact) return TRUE;
00305 }
00306 }
00307
00308 return FALSE;
00309 }
00310
00311
00312
00313
00314
00315 void Check_Invalid_Accesses(const WN *curr_nd)
00316 {
00317 if (!OPCODE_is_not_executable(WN_opcode(curr_nd)) &&
00318 OPCODE_has_sym(WN_opcode(curr_nd)) &&
00319 !Is_Allowed_Invalid_Access(curr_nd) &&
00320 !Is_Array_Base(curr_nd) &&
00321 !Is_Array_Param(curr_nd) &&
00322 !WN_opcode(curr_nd) == OPC_IDNAME) {
00323
00324 ST *array_st = WN_st(curr_nd);
00325
00326 if (array_st && Lookup_Array_Distr(array_st)) {
00327 ErrMsgSrcpos (EC_LNO_Generic2String, LWN_Get_Linenum(curr_nd),
00328 "Bad reference to reshaped array ", ST_name(array_st));
00329 }
00330 }
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 ST *
00346 Get_Reshaped_Array_St(const WN *array_expr,
00347 mBOOL *valid)
00348 {
00349 Is_True(WN_operator(array_expr) == OPR_ARRAY,
00350 ("Get_Reshaped_Array_St: called with non-array node (got opcode=%d)\n",
00351 WN_opcode(array_expr)));
00352
00353 ST *array_st = NULL;
00354 WN *array_base = WN_array_base(array_expr);
00355
00356 *valid = TRUE;
00357
00358
00359
00360
00361 if (OPCODE_has_sym(WN_opcode(array_base))) {
00362 array_st = WN_st(array_base);
00363 } else {
00364 return NULL;
00365 }
00366
00367
00368
00369 WN *mem_wn = Get_Memop_Parent(array_expr);
00370 Is_True(mem_wn, ("Get_Reshaped_Array_St: No ancestor found for array\n"));
00371
00372
00373
00374
00375
00376
00377 #if 0
00378 if (WN_operator(mem_wn) != OPR_PARM) {
00379
00380
00381 if ((WN_offset(mem_wn) != 0) &&
00382 (WN_operator(mem_wn) != OPR_PREFETCH) &&
00383 (WN_operator(mem_wn) != OPR_PREFETCHX))
00384 {
00385 *valid = FALSE;
00386 return array_st;
00387 }
00388 }
00389 #endif
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 if ((WN_operator(mem_wn) != OPR_ILOAD) &&
00402 (WN_operator(mem_wn) != OPR_ISTORE) &&
00403 (WN_operator(mem_wn) != OPR_PREFETCH) &&
00404 (WN_operator(mem_wn) != OPR_PREFETCHX) &&
00405 (WN_operator(mem_wn) != OPR_PARM) &&
00406 (WN_io_item(mem_wn) != IOL_VAR)) {
00407
00408 *valid = FALSE;
00409 return array_st;
00410 }
00411
00412
00413
00414
00415 if (WN_operator(array_base) == OPR_LDID) {
00416 if (WN_offset(array_base) != 0) {
00417 *valid = FALSE;
00418 return array_st;
00419 }
00420 } else if (WN_operator(array_base) != OPR_LDA) {
00421 *valid = FALSE;
00422 return array_st;
00423 }
00424
00425 return array_st;
00426 }
00427
00428
00429
00430
00431
00432
00433 WN *
00434 Get_Memop_Parent(const WN *curr_nd)
00435 {
00436 WN* parent = LWN_Get_Parent(curr_nd);
00437
00438 while (parent) {
00439 if ((WN_operator(parent) != OPR_CVT) &&
00440 (WN_operator(parent) != OPR_CVTL)) {
00441
00442 return parent;
00443
00444 } else {
00445 parent = LWN_Get_Parent(parent);
00446 }
00447 }
00448
00449 return NULL;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458 mBOOL
00459 Is_Allowed_Invalid_Access(const WN *curr_nd)
00460 {
00461 if (WN_operator(curr_nd) == OPR_STID) {
00462 WN *kid = WN_kid0(curr_nd);
00463
00464 if (WN_operator(kid) == OPR_LDID) {
00465 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(kid);
00466 if (defs && defs->Len() == 1) {
00467 WN *def_wn = defs->Head()->Wn();
00468 if (WN_operator(def_wn) == OPR_PARM) {
00469 def_wn = LWN_Get_Parent(def_wn);
00470 }
00471 if (WN_operator(def_wn) == OPR_CALL &&
00472 WN_st(def_wn) == distr_st_entries[Alloc_Reshape]) return TRUE;
00473 }
00474 }
00475 }
00476
00477 return FALSE;
00478 }
00479
00480
00481
00482
00483
00484 mBOOL
00485 Is_Array_Base(const WN *curr_nd)
00486 {
00487 WN *parent = LWN_Get_Parent(curr_nd);
00488 if (!parent) return FALSE;
00489
00490 mBOOL result = ((WN_operator(parent) == OPR_ARRAY) &&
00491 (WN_array_base(parent) == curr_nd));
00492 return result;
00493 }
00494
00495
00496
00497
00498
00499 mBOOL
00500 Is_Array_Param(const WN *curr_nd)
00501 {
00502 Is_True (LNO_Use_Parm,
00503 ("LNO_Use_Parm should be always on\n"));
00504 if ((WN_operator(curr_nd) == OPR_LDA) ||
00505 (WN_operator(curr_nd) == OPR_LDID)) {
00506
00507 WN *parent = LWN_Get_Parent(curr_nd);
00508 if ((WN_operator(parent) == OPR_PARM) &&
00509 (OPCODE_is_call(WN_opcode(LWN_Get_Parent(parent))) ||
00510 WN_operator(LWN_Get_Parent(parent)) == OPR_INTRINSIC_OP
00511 #ifdef KEY
00512 || WN_operator(LWN_Get_Parent(parent)) == OPR_PURE_CALL_OP
00513 #endif
00514 ))
00515 return TRUE;
00516 }
00517
00518 return FALSE;
00519 }
00520
00521
00522
00523
00524
00525 DISTR_ARRAY*
00526 Lookup_Array_Distr(ST *array_st)
00527 {
00528 if (Has_Reshaped_Type(array_st)) {
00529 DISTR_ARRAY *dact = Lookup_DACT(array_st);
00530 if (dact && dact->Dinfo()->IsReshaped()) return dact;
00531 }
00532
00533 return NULL;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542 mBOOL
00543 Has_Reshaped_Type(ST *array_st)
00544 {
00545 if (ST_class(array_st) != CLASS_VAR) return FALSE;
00546
00547 TY_IDX array_ty = ST_type(array_st);
00548 return ((TY_kind(array_ty) == KIND_POINTER) &&
00549 (TY_kind(TY_pointed(array_ty)) == KIND_POINTER));
00550 }