1 /* file "normalize.cc" */
3 /* Copyright (c) 1994 Stanford University
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
12 #define _MODULE_ "libdependence.a"
18 #include "dependence.h"
23 // Normalize the access vectors for all array references and loop
24 // definitoins so that the loop increment is always 1
26 // for i = a to b by c (where a and b may be funcs of other induc vars)
28 // has it's access vectors transformed to
29 // for i = 0 to (b-a)div c by 1
31 // (unless c is 1 in which case no normalization is done)
32 // Two sets of routines:
33 // ref routines change i->xci+xa for all references (including more deeply
34 // nested loop definintions)
35 // loop definition routines change lb<-0, ub<- (b-a)divc, step<-1
36 // to work correctly, all references must be changed before enclosing defs
37 // and the references in a loop definition must be changed before
38 // statements inside the loop,
43 // Also routine to normalize access vectors and test so test is <=
45 // must change for j = a' b' c' ref first (to take into account changes in i)
46 // then change ref [i,j] and finally change loop definitions (a'<-0, etc)
50 // nomalize the reference in an array_info
51 void array_info::normalize_step_ref()
53 array_info
*temp_info
= new array_info
;
55 array_info_iter
iter1(this);
56 while (!iter1
.is_empty()) { // normalize each dimension
57 access_vector
*temp_vector
= iter1
.step();
58 temp_vector
->normalize_step_ref();
59 temp_info
->append(temp_vector
);
63 // copy normalized versions back onto this array_info
64 array_info_iter
iter2(temp_info
);
65 while (!iter2
.is_empty()) {
66 access_vector
*temp_vector
= iter2
.step();
68 temp_info
->remove(iter2
.cur_elem());
74 // normalize an acess_vector for a reference
75 // ie ai+bj+... b => a*step1*i+a*lb1 + b*step2*j+b*lb2 + ...
76 void access_vector::normalize_step_ref()
78 if (too_messy
) return; // cannot undo a mess
80 access_list_iter
ai(&elts
);
81 while(!ai
.is_empty()) { // for each induction variable referenced
82 normalize_step_ref(ai
.step());
83 if (too_messy
) return; // cannot undo a mess
88 // normalize one variable of an access variable referenced
89 // ie a*i => a*step*i + a*lb
90 void access_vector::normalize_step_ref(access_list_e
*induct
)
92 tree_node
* tn
= (tree_node
*)induct
->var();
93 dep_for_annote
* ann
=
94 (dep_for_annote
*) tn
->peek_annote(k_dep_for_annote
);
95 array_info
*low
= ann
->lb
;
96 access_vector
*step
= ann
->stp
;
98 if (step
->too_messy
|| !step
->elts
.is_empty()) {
102 if (step
->con
== 1) return; // already normalized
104 /* keep only the first lower bound */
105 if (low
->count() > 1) {
106 array_info
*ai
= new array_info();
107 ai
->append(new access_vector(low
->first()));
111 assert(low
->count() == 1);
112 access_vector
*lb
= low
->first();
115 if (lb
->too_messy
|| (step
->con
== 0)) {
121 int a
= induct
->info
;
122 induct
->info
= a
*step
->con
; // a*i => a*step*i
124 // now add a*lb to access vector
125 access_list_iter
ai(&lb
->elts
);
126 while (!ai
.is_empty()) {
127 access_list_e
*lb_element
= ai
.step();
128 access_list_e
*this_element
= elts
.search(lb_element
->var());
130 this_element
->info
= this_element
->val() + a
*(lb_element
->val());
132 add((tree_node
*) lb_element
->var(),a
*lb_element
->val());
137 // now add it to conregs and conpaths and memregs
138 ai
.reset(&lb
->conregs
);
139 while (!ai
.is_empty()) {
140 access_list_e
*lb_element
= ai
.step();
141 access_list_e
*this_element
= conregs
.search(lb_element
->var());
143 this_element
->info
= (this_element
->val() + a
*(lb_element
->val()));
145 add((var_sym
*) lb_element
->var(),0,a
*lb_element
->val());
148 ai
.reset(&lb
->memregs
);
149 while (!ai
.is_empty()) {
150 access_list_e
*lb_element
= ai
.step();
151 access_list_e
*this_element
= memregs
.search(lb_element
->var());
153 this_element
->info
= (this_element
->val() +
154 a
*(lb_element
->val()));
156 add((var_sym
*) lb_element
->var(),1,a
*lb_element
->val());
164 // normalize the access vectors for the bounds and steps of a loop
165 void normalize_step_loops(array_info
*low
, array_info
*up
,
166 access_vector
*step
, tree_for_test test
)
168 if (step
->too_messy
) return;
169 if (step
->is_const() &&
170 step
->con
== 1) return; // loop already step_normalized
172 /* keep only the first lower/upper bound */
173 access_vector
*lb
=low
->pop();
174 while (low
->count()) delete low
->pop();
176 assert(low
->count() == 1);
178 access_vector
*ub
=up
->pop();
179 while (up
->count()) delete up
->pop();
181 assert(up
->count() == 1);
183 if (!step
->is_const()) { // non constant step, give up
189 if (step
->con
== 0) { // perverse case, die
195 if (lb
->too_messy
) { // can't normalize so give up
202 if (step
->con
< 0) { // reverse sign of test
203 if (test
== FOR_SLT
) {
205 } else if (test
== FOR_ULT
) {
207 } else if (test
== FOR_SLTE
) {
209 } else if (test
== FOR_ULTE
) {
211 } else if (test
== FOR_SGT
) {
213 } else if (test
== FOR_UGT
) {
215 } else if (test
== FOR_SGTE
) {
217 } else if (test
== FOR_UGTE
) {
227 if (ub
->too_messy
) { // can normalize, but ub stays messy
230 access_list_iter
ai(&lb
->elts
);
231 while(!ai
.is_empty()) { // subtract off each lower bound component
232 access_list_e
*lb_element
= ai
.step();
233 access_list_e
*ub_element
= ub
->elts
.search(lb_element
->var());
235 ub_element
->info
= ub_element
->val() -
236 lb
->val((tree_node
*) lb_element
->var());
238 ub
->add((tree_node
*) lb_element
->key
,
239 -lb
->val((tree_node
*) lb_element
->var()));
243 ai
.reset(&lb
->conregs
);
244 while(!ai
.is_empty()) { // subtract off each lower bound component
245 access_list_e
*lb_element
= ai
.step();
246 access_list_e
*ub_element
= ub
->conregs
.search(lb_element
->var());
248 ub_element
->info
= (ub_element
->val() -
249 lb
->val((var_sym
*)lb_element
->var(),0));
251 ub
->add((var_sym
*) lb_element
->key
,0,
252 -lb
->val((var_sym
*)lb_element
->var(),0));
255 ai
.reset(&lb
->memregs
);
256 while(!ai
.is_empty()) { // subtract off each lower bound component
257 access_list_e
*lb_element
= ai
.step();
258 access_list_e
*ub_element
= ub
->memregs
.search(lb_element
->var());
260 ub_element
->info
= (ub_element
->val() -
261 lb
->val((var_sym
*)lb_element
->var(),1));
263 ub
->add((var_sym
*) lb_element
->key
,1,
264 -lb
->val((var_sym
*)lb_element
->var(),1));
270 while(!ai
.is_empty()) {
271 access_list_e
*ub_element
= ai
.step();
272 if ((ub_element
->val() % step
->con
) != 0) {
281 while(!lb
->elts
.is_empty())
282 lb
->elts
.pop();// erase lb vars
283 while (!lb
->conregs
.is_empty())
285 while (!lb
->memregs
.is_empty())
291 (ub
->val((tree_node
*)ub_element
->key
) / step
->con
);
294 if ((ub
->con
% step
->con
) != 0) {
297 while(!lb
->elts
.is_empty()) lb
->elts
.pop();// erase lb vars
298 while (!lb
->conregs
.is_empty()) lb
->conregs
.pop();
299 while (!lb
->memregs
.is_empty()) lb
->memregs
.pop();
303 ub
->con
/= step
->con
;
304 ub
->con
+= ub_offset
;
306 ai
.reset(&ub
->conregs
);
307 while(!ai
.is_empty()) {
308 access_list_e
*ub_element
= ai
.step();
309 if ((ub_element
->val() % step
->con
) != 0) {
312 while(!lb
->elts
.is_empty())
313 lb
->elts
.pop();// erase lb vars
314 while (!lb
->conregs
.is_empty())
316 while (!lb
->memregs
.is_empty())
328 (ub
->val((var_sym
*)ub_element
->key
,0) / step
->con
);
331 ai
.reset(&ub
->memregs
);
332 while(!ai
.is_empty()) {
333 access_list_e
*ub_element
= ai
.step();
334 if ((ub_element
->val() % step
->con
) != 0) {
342 while(!lb
->elts
.is_empty())
343 lb
->elts
.pop();// erase lb vars
344 while (!lb
->conregs
.is_empty())
346 while (!lb
->memregs
.is_empty())
352 (ub
->val((var_sym
*)ub_element
->key
,1) / step
->con
);
358 while (!lb
->elts
.is_empty()) lb
->elts
.pop(); // erase lb vars
359 while (!lb
->conregs
.is_empty()) lb
->conregs
.pop();
360 while (!lb
->memregs
.is_empty()) lb
->memregs
.pop();
365 void normalize_test(array_info
*low
,array_info
*up
,
366 access_vector
*step
, tree_for_test test
)
368 array_info_iter
ai(up
);
369 while (!ai
.is_empty()) {
370 access_vector
*ub
= ai
.step();
372 if (test
== FOR_SLT
) {
374 if (ub
->min
) (*ub
->min
) --;
375 } else if (test
== FOR_ULT
) {
377 if (ub
->min
) (*ub
->min
) --;
378 } else if ((test
== FOR_SLTE
) || (test
== FOR_ULTE
)) {
384 array_info_iter
ai2(low
);
385 while (!ai2
.is_empty()) {
386 access_vector
*lb
= ai2
.step();
388 if (test
== FOR_SLT
) {
389 } else if (test
== FOR_ULT
) {
390 } else if ((test
== FOR_SLTE
) || (test
== FOR_ULTE
)) {