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 #ifdef USE_PCH
00037 #include "lno_pch.h"
00038 #endif // USE_PCH
00039 #pragma hdrstop
00040
00041 #ifdef _KEEP_RCS_ID
00042
00043 static char *rcs_id = "$Source$ $Revision$";
00044 #endif
00045
00046 #include <sys/types.h>
00047 #include <ctype.h>
00048 #include <limits.h>
00049 #include <alloca.h>
00050
00051 #include "pu_info.h"
00052 #include "lnoutils.h"
00053 #include "lnopt_main.h"
00054 #include "stab.h"
00055 #include "targ_const.h"
00056 #include "wn_simp.h"
00057 #include "stdlib.h"
00058 #include "lwn_util.h"
00059 #include "strtab.h"
00060 #include "config.h"
00061 #include "optimizer.h"
00062 #include "opt_du.h"
00063 #include "name.h"
00064 #include "wintrinsic.h"
00065 #include "lno_bv.h"
00066 #include "dep_graph.h"
00067 #include "debug.h"
00068 #include "cxx_memory.h"
00069 #include "lego_pragma.h"
00070 #include "lego_util.h"
00071 #include "lego_skew.h"
00072 #include "tlog.h"
00073
00074
00075
00076
00077
00078
00079
00080 static BOOL Lego_Reshaped_Array(WN* wn_array)
00081 {
00082 if (WN_operator(wn_array) != OPR_ARRAY)
00083 return FALSE;
00084 ST* st_array;
00085 WN *array_base = WN_array_base(wn_array);
00086
00087 st_array = (WN_has_sym(array_base) ? WN_st(array_base) : NULL);
00088 DISTR_ARRAY* dact = Lookup_DACT(st_array);
00089 if (dact == NULL || !dact->Dinfo()->IsReshaped())
00090 return FALSE;
00091 return TRUE;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 static BOOL Lego_Skew_Canonical(WN* wn_loop,
00104 ACCESS_VECTOR* av)
00105 {
00106 if (av->Too_Messy)
00107 return FALSE;
00108 if (av->Contains_Non_Lin_Symb())
00109 return FALSE;
00110 if (!av->Has_Loop_Coeff())
00111 return FALSE;
00112 INT loop_depth = Do_Depth(wn_loop);
00113 INT loop_coeff = av->Loop_Coeff(loop_depth);
00114 if (loop_coeff != 1 && loop_coeff != -1)
00115 return FALSE;
00116 for (INT i = 0; i < av->Nest_Depth(); i++)
00117 if (i != loop_depth && av->Loop_Coeff(i) != 0)
00118 return FALSE;
00119 if (!av->Contains_Lin_Symb())
00120 return FALSE;
00121 return TRUE;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131 static BOOL Lego_Skew_Equivalent(WN* wn_loop,
00132 ACCESS_VECTOR* av1,
00133 ACCESS_VECTOR* av2)
00134 {
00135 if (av1->Loop_Coeff(Do_Depth(wn_loop)) != av2->Loop_Coeff(Do_Depth(wn_loop)))
00136 return FALSE;
00137 INTSYMB_LIST* isl = NULL;
00138 isl = Subtract(av1->Lin_Symb, av2->Lin_Symb, &LNO_local_pool);
00139 if (isl != NULL)
00140 return FALSE;
00141 return TRUE;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151 static void Lego_Update_Skew_Count(WN* wn_loop,
00152 WN* wn_array,
00153 STACK<LEGO_SKEW*>* st_skew)
00154 {
00155 DISTR_ARRAY* dact = Lookup_DACT(WN_has_sym(WN_array_base(wn_array)) ?
00156 WN_st(WN_array_base(wn_array)) :
00157 NULL);
00158 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn_array);
00159 if (aa == NULL || aa->Too_Messy)
00160 return;
00161 for (INT i = 0; i < aa->Num_Vec(); i++) {
00162 ACCESS_VECTOR* av = aa->Dim(i);
00163 if (Lego_Skew_Canonical(wn_loop, av)) {
00164 INT j;
00165 for (j = 0; j < st_skew->Elements(); j++) {
00166 LEGO_SKEW* lsk = st_skew->Bottom_nth(j);
00167 ST* st_old = (WN_has_sym(WN_array_base(lsk->Array())) ?
00168 WN_st(WN_array_base(lsk->Array())) :
00169 NULL);
00170 DISTR_ARRAY* dact_old = Lookup_DACT(st_old);
00171 if (dact->DACT_Equiv(dact_old, i, lsk->Dim())
00172 && Lego_Skew_Equivalent(wn_loop, av, lsk->Av())) {
00173 lsk->Increment();
00174 break;
00175 }
00176 }
00177 if (j == st_skew->Elements()) {
00178 LEGO_SKEW* lsk_new = CXX_NEW(LEGO_SKEW(av, wn_array, i, 1),
00179 &LNO_default_pool);
00180 st_skew->Push(lsk_new);
00181 }
00182 }
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 static WN* Lego_Skew_Offset(LEGO_SKEW* lsk,
00193 BOOL negative_stride,
00194 DU_MANAGER* du)
00195 {
00196 WN* wn_skew = NULL;
00197 INTSYMB_CONST_ITER iter(lsk->Av()->Lin_Symb);
00198 const INTSYMB_NODE *first = iter.First();
00199 for (const INTSYMB_NODE *node=first; !iter.Is_Empty(); node = iter.Next()) {
00200 WN* wn_variable = Find_Node(node->Symbol, lsk->Array());
00201 WN* wn_constant = LWN_Make_Icon(WN_rtype(wn_variable), node->Coeff);
00202 WN* wn_varcopy = LWN_Copy_Tree(wn_variable);
00203 LWN_Copy_Def_Use(wn_variable, wn_varcopy, du);
00204 OPCODE op_mpy = OPCODE_make_op(OPR_MPY, WN_rtype(wn_variable), MTYPE_V);
00205 WN* wn_prod = LWN_CreateExp2(op_mpy, wn_constant, wn_varcopy);
00206 if (wn_skew == NULL) {
00207 wn_skew = wn_prod;
00208 } else {
00209 TYPE_ID type_add = Max_Wtype(WN_rtype(wn_skew), WN_rtype(wn_prod));
00210 OPCODE op_add = OPCODE_make_op(OPR_ADD, type_add, MTYPE_V);
00211 wn_skew = LWN_CreateExp2(op_add, wn_skew, wn_prod);
00212 }
00213 }
00214 if (negative_stride) {
00215 WN* wn_minusone = LWN_Make_Icon(WN_rtype(wn_skew), -1);
00216 OPCODE op_mpy = OPCODE_make_op(OPR_MPY, WN_rtype(wn_skew), MTYPE_V);
00217 wn_skew = LWN_CreateExp2(op_mpy, wn_minusone, wn_skew);
00218 }
00219 return wn_skew;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static BOOL Lego_Loop_Want_Skew(WN* wn_loop,
00231 WN** wn_lego_skew_addr,
00232 DU_MANAGER* du)
00233 {
00234 *wn_lego_skew_addr = NULL;
00235 WN* wn_step = Loop_Step(wn_loop);
00236 if (WN_operator(wn_step) != OPR_INTCONST)
00237 return FALSE;
00238 if (WN_const_val(wn_step) != 1)
00239 return FALSE;
00240 if (!Upper_Bound_Standardize(WN_end(wn_loop), TRUE))
00241 return FALSE;
00242 STACK<LEGO_SKEW*> st_skew(&LNO_local_pool);
00243 LWN_ITER* itr = LWN_WALK_TreeIter(WN_do_body(wn_loop));
00244 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00245 WN* wn = itr->wn;
00246 if (Lego_Reshaped_Array(wn))
00247 Lego_Update_Skew_Count(wn_loop, wn, &st_skew);
00248 }
00249 if (st_skew.Elements() == 0)
00250 return FALSE;
00251 LEGO_SKEW* lsk_best = st_skew.Bottom_nth(0);
00252 for (INT i = 1; i < st_skew.Elements(); i++) {
00253 LEGO_SKEW* lsk = st_skew.Bottom_nth(i);
00254 if (lsk->Count() > lsk_best->Count())
00255 lsk_best = lsk;
00256 }
00257 BOOL negative_stride = lsk_best->Av()->Loop_Coeff(Do_Depth(wn_loop)) < 0;
00258 *wn_lego_skew_addr = Lego_Skew_Offset(lsk_best, negative_stride, du);
00259 return TRUE;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 static WN* Lego_Parent_Array(WN* wn_node)
00269 {
00270 for (WN* wn = wn_node; wn != NULL; wn = LWN_Get_Parent(wn))
00271 if (WN_operator(wn) == OPR_ARRAY)
00272 return wn;
00273 return NULL;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283 static WN* Lego_Skew_Index(WN* wn_loop,
00284 WN* wn_lego_skew_offset,
00285 DU_MANAGER* du)
00286 {
00287 TYPE_ID type = Promote_Type(Do_Wtype(wn_loop));
00288 WN* wn_index = UBvar(WN_end(wn_loop));
00289 WN* wn_index_copy = LWN_Copy_Tree(wn_index);
00290 LWN_Copy_Def_Use(wn_index, wn_index_copy, du);
00291 WN* wn_ldid = LWN_Copy_Tree(wn_lego_skew_offset);
00292 LWN_Copy_Def_Use(wn_lego_skew_offset, wn_ldid, du);
00293 OPCODE op = OPCODE_make_op(OPR_SUB, type, MTYPE_V);
00294 WN* wn_skew = LWN_CreateExp2(op, wn_index_copy, wn_ldid);
00295 return wn_skew;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 static BOOL Lego_Contains_Non_Index_Ldid(WN* wn_loop,
00306 WN* wn_index)
00307 {
00308 LWN_ITER* itr = LWN_WALK_TreeIter(wn_index);
00309 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00310 WN* wn = itr->wn;
00311 if (WN_operator(wn) == OPR_LDID
00312 && SYMBOL(wn) != SYMBOL(WN_index(wn_loop)))
00313 return TRUE;
00314 }
00315 return FALSE;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325 static WN* Lego_Index_From_Access_Vector(ACCESS_VECTOR* av,
00326 WN* wn_index,
00327 DU_MANAGER* du)
00328 {
00329 WN* wn_new_index = NULL;
00330 for (INT i = 0; i < av->Nest_Depth(); i++) {
00331 if (av->Loop_Coeff(i) == 0)
00332 continue;
00333 WN* wn = 0;
00334 for (wn = wn_index; wn != NULL; wn = LWN_Get_Parent(wn))
00335 if (WN_opcode(wn) == OPC_DO_LOOP && Do_Depth(wn) == i)
00336 break;
00337 FmtAssert(wn != NULL, ("Could not find do loop with given depth"));
00338 OPCODE op_ldid = Matching_Load_Opcode(WN_opcode(WN_start(wn)));
00339 WN* wn_ldid = LWN_CreateLdid(op_ldid, WN_start(wn));
00340 du->Add_Def_Use(WN_start(wn), wn_ldid);
00341 du->Add_Def_Use(WN_step(wn), wn_ldid);
00342 du->Ud_Get_Def(wn_ldid)->Set_loop_stmt(wn);
00343 WN* wn_constant = LWN_Make_Icon(WN_rtype(wn_ldid), av->Loop_Coeff(i));
00344 OPCODE op_mpy = OPCODE_make_op(OPR_MPY, WN_rtype(wn_ldid), MTYPE_V);
00345 WN* wn_prod = LWN_CreateExp2(op_mpy, wn_constant, wn_ldid);
00346 if (wn_new_index == NULL) {
00347 wn_new_index = wn_prod;
00348 } else {
00349 TYPE_ID type_add = Max_Wtype(WN_rtype(wn_ldid), WN_rtype(wn_new_index));
00350 OPCODE op_add = OPCODE_make_op(OPR_ADD, type_add, MTYPE_V);
00351 wn_new_index = LWN_CreateExp2(op_add, wn_new_index, wn_prod);
00352 }
00353 }
00354 if (av->Const_Offset != 0) {
00355 if (wn_new_index == 0) {
00356 wn_new_index = LWN_Make_Icon(av->Const_Offset, WN_rtype(wn_index));
00357 } else {
00358 WN* wn_offset = LWN_Make_Icon(WN_rtype(wn_new_index), av->Const_Offset);
00359 OPCODE op_add = OPCODE_make_op(OPR_ADD, WN_rtype(wn_new_index), MTYPE_V);
00360 wn_new_index = LWN_CreateExp2(op_add, wn_new_index, wn_offset);
00361 }
00362 }
00363 return wn_new_index;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 static void Lego_Simplify(WN* wn_loop,
00375 WN* wn_array,
00376 DU_MANAGER* du)
00377 {
00378 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn_array);
00379 if (aa == NULL || aa->Too_Messy)
00380 return;
00381 INT loop_depth = Do_Depth(wn_loop);
00382 INT i;
00383 for (i = 0; i < aa->Num_Vec(); i++)
00384 if (aa->Dim(i)->Delinearized_Symbol != NULL)
00385 return;
00386 for (i = 0; i < aa->Num_Vec(); i++) {
00387 ACCESS_VECTOR* av = aa->Dim(i);
00388 if (av->Too_Messy)
00389 continue;
00390 INT loop_coeff = av->Loop_Coeff(loop_depth);
00391 if (av->Loop_Coeff(loop_depth)== 0 || av->Contains_Non_Lin_Symb())
00392 continue;
00393 if (av->Contains_Lin_Symb())
00394 continue;
00395 WN* wn_index = WN_array_index(wn_array, i);
00396 if (!Lego_Contains_Non_Index_Ldid(wn_loop, wn_index))
00397 continue;
00398 WN* wn_new_index = Lego_Index_From_Access_Vector(av, wn_index, du);
00399 Replace_Wnexp_With_Exp_Copy(wn_index, wn_new_index, du);
00400 LWN_Delete_Tree(wn_new_index);
00401 }
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 static void Lego_Simplify_Loop(WN* wn_loop,
00411 DU_MANAGER* du)
00412 {
00413 LWN_ITER* itr = LWN_WALK_TreeIter(WN_do_body(wn_loop));
00414 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00415 WN* wn = itr->wn;
00416 if (WN_operator(wn) == OPR_ARRAY)
00417 Lego_Simplify(wn_loop, wn, du);
00418 }
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 static void Lego_Skew_Loop(WN* wn_loop,
00429 WN* wn_lego_skew_offset,
00430 DU_MANAGER* du)
00431 {
00432 if (LNO_Verbose) {
00433 fprintf(stdout, "Lego skewing loop %s on line %d\n",
00434 WB_Whirl_Symbol(wn_loop), (INT) WN_linenum(wn_loop));
00435 fprintf(TFile, "Lego skewing loop %s on line %d\n",
00436 WB_Whirl_Symbol(wn_loop), (INT) WN_linenum(wn_loop));
00437 if (LNO_Tlog)
00438 Generate_Tlog("LNO", "lego_skewing", Srcpos_To_Line(WN_linenum(wn_loop)),
00439 (char *) WB_Whirl_Symbol(wn_loop), "", "", "");
00440 }
00441 if (Index_Variable_Live_At_Exit(wn_loop))
00442 Finalize_Index_Variable(wn_loop, TRUE, TRUE);
00443 TYPE_ID type = Promote_Type(Do_Wtype(wn_loop));
00444 OPCODE op_skew = OPCODE_make_op(OPR_ADD, type, MTYPE_V);
00445 LWN_ITER* itr = LWN_WALK_TreeIter(WN_do_body(wn_loop));
00446 STACK<WN*> index_stack(&LNO_local_pool);
00447 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00448 WN* wn = itr->wn;
00449 if (WN_operator(wn) == OPR_LDID
00450 && SYMBOL(wn) == SYMBOL(WN_index(wn_loop)))
00451 index_stack.Push(wn);
00452 }
00453 INT i;
00454 for (i = 0; i < index_stack.Elements(); i++) {
00455 WN* wn = index_stack.Bottom_nth(i);
00456 WN* wn_array = Lego_Parent_Array(wn);
00457 WN* wn_new_index = Lego_Skew_Index(wn_loop, wn_lego_skew_offset, du);
00458 Replace_Wnexp_With_Exp_Copy(wn, wn_new_index, du);
00459 if (wn_array != NULL)
00460 LWN_Simplify_Tree(wn_array);
00461 LWN_Delete_Tree(wn_new_index);
00462 }
00463 WN* wn_start = WN_kid0(WN_start(wn_loop));
00464 WN* wn_stop = UBexp(WN_end(wn_loop));
00465 for (i = 0; i < WN_kid_count(WN_end(wn_loop)); i++)
00466 if (WN_kid(WN_end(wn_loop), i) == wn_stop)
00467 break;
00468 INT stop_index = i;
00469 WN* wn_skew = LWN_Copy_Tree(wn_lego_skew_offset);
00470 LWN_Copy_Def_Use(wn_lego_skew_offset, wn_skew, du);
00471 WN* wn_new_start = LWN_CreateExp2(op_skew, wn_start, wn_skew);
00472 wn_skew = LWN_Copy_Tree(wn_lego_skew_offset);
00473 LWN_Copy_Def_Use(wn_lego_skew_offset, wn_skew, du);
00474 WN* wn_new_stop = LWN_CreateExp2(op_skew, wn_stop, wn_skew);
00475 WN_kid0(WN_start(wn_loop)) = wn_new_start;
00476 LWN_Set_Parent(wn_new_start, WN_start(wn_loop));
00477 WN_kid(WN_end(wn_loop), stop_index) = wn_new_stop;
00478 LWN_Set_Parent(wn_new_stop, WN_end(wn_loop));
00479 LWN_Delete_Tree(wn_lego_skew_offset);
00480 DOLOOP_STACK shortstack(&LNO_local_pool);
00481 Build_Doloop_Stack(LWN_Get_Parent(wn_loop), &shortstack);
00482 LNO_Build_Access(wn_loop, &shortstack, &LNO_default_pool, 0, TRUE);
00483 Lego_Simplify_Loop(wn_loop, du);
00484 }
00485
00486
00487
00488
00489
00490
00491
00492 static void Lego_Skew_Traverse(WN* wn_tree,
00493 DU_MANAGER* du)
00494 {
00495 if (WN_opcode(wn_tree) == OPC_DO_LOOP) {
00496 WN* wn_lego_skew_offset = NULL;
00497 if (Lego_Loop_Want_Skew(wn_tree, &wn_lego_skew_offset, du))
00498 Lego_Skew_Loop(wn_tree, wn_lego_skew_offset, du);
00499 }
00500 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00501 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00502 Lego_Skew_Traverse(wn, du);
00503 } else {
00504 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00505 Lego_Skew_Traverse(WN_kid(wn_tree, i), du);
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 extern void Lego_Skew_Indices(WN* wn_tree)
00516 {
00517 DU_MANAGER* du = Du_Mgr;
00518 Lego_Skew_Traverse(wn_tree, du);
00519 }
00520