#include #include "AST.h" #include "StorageAnnotations.h" #include "dominator.h" extern bool debug_stoptifu; #define DEBUG_STOR debug_stoptifu // #define DEBUG_STOR 1 /* Macros for debugging output */ #undef DPRINT #undef DPRINTLN #undef DBG #define DPRINT(x) do { if (DEBUG_STOR) cout << (x); } while (0) #define DPRINTLN(x) DPRINT(string(x) + '\n') #define DBG(x) do { if (DEBUG_STOR) { x; } } while (0) #undef XBG #undef XPRINTLN #undef XPRINT #define XPRINT(x) do { if (1) cout << (x); } while (0) #define XPRINTLN(x) XPRINT(string(x) + '\n') #define XBG(x) do { if (1) { x; } } while (0) extern TreeNode *& ACtoIF(AC *r); extern llist * array_accesses(TreeNode *l); extern bool may_overlap(ArrayAccess &x, ArrayAccess &y); extern bool arrays_same_or_assumed_to_be_same(ArrayAccess &x, ArrayAccess &y); /* True if any element of l (except perhaps x itself) could write to an array elt that x touches. */ static bool other_writes_can_conflict(ArrayAccess &x, llist *l) { while (l != NULL) { ArrayAccess &y = l->front(); if (!y.is_read && !x.equals(y)) { DBG(cout << "Check conflict:\n " << x.to_string() << "\n " << y.to_string() << '\n'); bool same = arrays_same_or_assumed_to_be_same(x, y); if (same && exists_range_overlap(x.r, y.r) || !same && may_overlap(x, y)) return true; } l = l->tail(); } DBG(cout << "No conflicts with\n " << x.to_string() << '\n'); return false; } /* Construct smap_elements and rwmap_elements for f and add them to r. */ static void annotate(Foreach *f, StorageAnnotations *r) { DBG({ cout << "annotate():" << endl; f->print(cout, 2); }); llist *a, *i; a = array_accesses(ACtoIF(f)); for (i = a; i != NULL; i = i->tail()) { ArrayAccess &acc = i->front(); DPRINTLN("acc: " + acc.to_string()); if (acc.is_read) { rwmap_element *e = r->insert_read(f, acc); DPRINTLN("Found rwmap " + e->to_string()); } else { rwmap_element *e = r->insert_write(f, acc); DPRINTLN("Found rwmap " + e->to_string()); } if (acc.t != NULL && (isSRArrayAccessNode(acc.t) || isOSRArrayAccessNode(acc.t))) if (!acc.t->appearsOnEveryIter()) DPRINTLN("Not necessarily occuring on every iter"); else if (other_writes_can_conflict(acc, a)) DPRINTLN("Other writes may conflict with acc"); else { smap_element *e = r->insert_optimizable(f, acc, acc.is_read, acc.is_read); DPRINTLN("Found smap " + e->to_string()); } } } StorageAnnotations *computeStorageAnnotations(llist *m) { StorageAnnotations *r = new StorageAnnotations(); while (m != NULL) { Megatile *x = m->front(); m = m->tail(); foreach (p, llist, *(x->loop_list())) annotate(*p, r); } return r; } map *StorageAnnotations::mia = NULL; map *StorageAnnotations::mai = NULL; int StorageAnnotations::count; /* a2i(x) and a2i(y) return the same integer iff x and y are the same. */ int StorageAnnotations::a2i(const ArrayAccess &a) { if (mia == NULL) { mia = new map; mai = new map; count = 0; } if (mai->find(a) == mai->end()) { (*mai)[a] = count; (*mia)[count] = a; return count++; } return (*mai)[a]; } /* i2a(a2i(x)) returns x. Do not call i2a(i) unless i was the return value of some call to a2i(). */ const ArrayAccess &StorageAnnotations::i2a(int i) { return (*mia)[i]; }