#ifndef _INCLUDE_STORAGE_ANNOTATIONS_H_ #define _INCLUDE_STORAGE_ANNOTATIONS_H_ #include "using-std.h" #include "pseudocode.h" #include "ArrayAccessSet.h" #include "code-util.h" #include "code-MIVE.h" #include "stoptifu/stoptifu.h" /* from stoptifu.cc */ extern int array_arity(const ArrayAccessNode *t); /* A value of 0 means "I don't know" and is unequal to all value numbers. */ typedef int value_number; class ArrayAccess { public: ArrayAccess() {} ArrayAccess(bool r, value_number v, Relation z, ArrayAccessNode *x) : is_read(r), a(v), r(z), t(x) {} /* true=read, false=write */ bool is_read; /* the array (0 means "I don't know") */ value_number a; /* Relation: (iter point -> array index) */ Relation r; /* May be NULL if a is 0. */ ArrayAccessNode *t; inline int arity() const { return array_arity(t); } inline TreeNode *array() const { return (t == NULL ? NULL : t->array()); } inline string array_name() const { return pseudocode(array()); } inline TypeNode *array_type() const { return array()->type(); } inline bool is_grid_access() const { return array_type()-> isTitaniumArrayType(); } inline TreeNode *array_decl_source() const { return arrayVarDecl(array()); } inline bool equals(const ArrayAccess &x) const { return memcmp(this, &x, sizeof(ArrayAccess)) == 0; } inline bool every_iter() const { return (t != NULL && (isSRArrayAccessNode(t) || isOSRArrayAccessNode(t)) && t->appearsOnEveryIter()); } string to_string() const { if (t == NULL) return string("<") + (is_read ? 'r' : 'w') + ' ' + pseudocode(t) + ", V=" + int2string((int) a) + ", " "MIVE=?, ?>"; const MIVE *z = NULL; if (isSRArrayAccessNode(t) || isOSRArrayAccessNode(t)) z = t->index()->getMIVE(t->WRTloop()); return string("<") + (is_read ? 'r' : 'w') + ' ' + pseudocode(t) + ", V=" + int2string((int) a) + ", " "MIVE=" + stringify(z) + ", " + (const char *) (((Relation) r).print_formula_to_string()) + ">"; } }; static inline bool operator<(const ArrayAccess &x, const ArrayAccess &y) { return (x.t < y.t || (x.t == y.t && x.to_string() < y.to_string())); } static inline void set_type_of_access(int access, TreeNode *t) { extern map override_typemap; // in ACtrans.cc if (t != NULL) { TypeNode *type = t->type(); string mangled_type = type->mangle(); type_of_access(access) = new Ty(mangled_type); override_typemap[mangled_type] = type; } } class StorageAnnotations { public: StorageAnnotations() : sm(NULL), wm(NULL) {}; ~StorageAnnotations() { free_all(wm); free_all(sm); }; static int a2i(const ArrayAccess &a); static const ArrayAccess &i2a(int i); static map *mia; static map *mai; static int count; static void reset() { delete mia; delete mai; mia = NULL; mai = NULL; } smap &optimizable_reads_and_writes() { return s; } rwmap &reads_and_writes() { return w; } smap_element *insert_optimizable(Foreach *f, const ArrayAccess &a, bool can_prefetch, bool avail_at_end) { smap_element *e = new smap_element(a2i(a), can_prefetch, avail_at_end, a.a, a.r); set_type_of_access(e->access, a.t); push(sm, e); push(s[f], e); return e; } rwmap_element *insert_write(Foreach *f, const ArrayAccess &a) { rwmap_element *e = new rwmap_element(a2i(a), a.a, false, a.r, a.every_iter()); set_type_of_access(e->access, a.t); push(wm, e); push(w[f], e); return e; } rwmap_element *insert_read(Foreach *f, const ArrayAccess &a) { rwmap_element *e = new rwmap_element(a2i(a), a.a, true, a.r, a.every_iter()); set_type_of_access(e->access, a.t); push(wm, e); push(w[f], e); return e; } private: smap s; // optimizable accesses rwmap w; // all reads and writes, including those in s // Lists of stuff to be freed when this is deleted. llist *sm; llist *wm; }; StorageAnnotations *computeStorageAnnotations(llist *m); #endif