/* -*- c++ -*- */ #ifndef _SNIPPET_H_ #define _SNIPPET_H_ #include #include "Bridge.h" #define BOGUS(s) \ do { \ cerr << "Internal error! " << (s) << \ " should not be invoked on this: " << to_string() << endl; \ return 0; \ } while (0) typedef pair snippetguts; class TouchSet; class TreeNode; extern string & nameOfLoop(TreeNode *f); class snippet : public gc { public: snippet() : used(false) {} bool used; virtual snippetguts guts() = 0; bool equals(snippet *x) { return guts() == x->guts(); } virtual TouchSet *reads(bool ignore_junk_method = false) = 0; virtual TouchSet *writes(bool ignore_junk_method = false) = 0; bool can_swap(class snippet *y, bool check_arrays = true); virtual string to_string() const = 0; virtual TreeNode *asLoop() const { BOGUS("asLoop"); } virtual bool isParallel() const { BOGUS("isParallel"); } virtual bool isLoop() const { return false; } // true for Loop and LoopOnly virtual bool isLoopOnly() const { return false; } // true for LoopOnly virtual bool isLoopIntro() const { return false; } // true for LoopIntro virtual bool isBridge() const { return false; } // true for Bridge virtual bool matchingLoopPair(class snippet const *x) const { return false; } virtual class snippet *loopIntro() const { BOGUS("loopIntro()"); } virtual class snippet *loopOnly() const { BOGUS("loopOnly()"); } /* Add to s statement nodes that cover everything in the snippet (not necessarily a tight cover). */ virtual void add_statements(set &s) = 0; virtual void add_decls(treeSet &s) {} virtual int iteration_space_arity() const { BOGUS("iteration_space_arity()"); } virtual llist *untiled() { return cons(this); } virtual void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l) = 0; }; class snippetBridge : public snippet { public: snippetBridge(Bridge *a) : b(a) {} inline TouchSet *reads(bool ignore_junk_method = false) { return b->reads(ignore_junk_method); } inline TouchSet *writes(bool ignore_junk_method = false) { return b->writes(ignore_junk_method); } inline bool isBridge() const { return true; } inline string to_string() const { return 'B' + b->to_string(); } inline snippetguts guts() { return snippetguts(0, (void *) b); } inline void add_statements(set &s) { b->add_statements(s); } inline void add_decls(treeSet &s) { b->add_decls(s); } void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l); private: Bridge *b; }; class snippetTiledAndUntiled : public snippet { public: snippetTiledAndUntiled(llist *z) : l(z), r0(NULL), w0(NULL), r1(NULL), w1(NULL) {} TouchSet *reads(bool ignore_junk_method = false); TouchSet *writes(bool ignore_junk_method = false); string to_string() const; snippetguts guts() { return snippetguts(-1, (void *) l); } const llist *asList() const { return l; } llist *untiled() { return l->copy(); } void add_statements(set &s) { for (llist *k = l; k != NULL; k = k->tail()) k->front()->add_statements(s); } void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l); private: llist *l; TouchSet *r0, *w0, *r1, *w1; // what is read and written }; class snippetLoopIntro : public snippet { public: snippetLoopIntro(TreeNode *a) : t(a), r0(NULL), w0(NULL), r1(NULL), w1(NULL), c(NULL), d(NULL) {} TouchSet *reads(bool ignore_junk_method = false); TouchSet *writes(bool ignore_junk_method = false); string to_string() const { return 'I' + nameOfLoop(t); } TreeNode *asLoop() const { return t; } bool isParallel() const { return static_cast(t)->getParallel(); } bool isLoopIntro() const { return true; } virtual bool matchingLoopPair(class snippet const *x) const { return x->isLoopOnly() && x->asLoop() == asLoop(); } llist *code(); llist *decls(); llist *code_and_decls(); snippetguts guts() { return snippetguts(2, (void *) t); } void add_statements(set &s) { assert(isForEachStmtNode(t)); StatementNode *z = dynamic_cast (static_cast(t)->cannotBeEmpty()); s.insert(z == NULL ? static_cast(t) : z); } void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l); private: TreeNode *t; // the loop TouchSet *r0, *w0, *r1, *w1; // what is read and written // c is everything between the "if (!D.isNull()) {" and "foreach+ (...) " llist *c; // code llist *d; // decls }; class snippetLoopOnly : public snippet { public: snippetLoopOnly(TreeNode *a) : t(a), r0(NULL), w0(NULL), r1(NULL), w1(NULL) {} TouchSet *reads(bool ignore_junk_method = false); TouchSet *writes(bool ignore_junk_method = false); string to_string() const { return 'X' + nameOfLoop(t); } bool isLoop() const { return true; } bool isLoopOnly() const { return true; } TreeNode *asLoop() const { return t; } bool isParallel() const { return static_cast(t)->getParallel(); } int iteration_space_arity() const { return static_cast(t)->tiArity(); } snippetguts guts() { return snippetguts(3, (void *) t); } void add_statements(set &s) { assert(t->isStatementNode()); s.insert(static_cast(t)); } void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l); private: TreeNode *t; TouchSet *r0, *w0, *r1, *w1; // llist *c; }; class snippetLoop : public snippet { public: snippetLoop(TreeNode *a) : t(a), r0(NULL), w0(NULL), r1(NULL), w1(NULL) {} TouchSet *reads(bool ignore_junk_method = false); TouchSet *writes(bool ignore_junk_method = false); string to_string() const { return nameOfLoop(t); } bool isLoop() const { return true; } TreeNode *asLoop() const { return t; } bool isParallel() const { return static_cast(t)->getParallel(); } int iteration_space_arity() const { return static_cast(t)->tiArity(); } snippetguts guts() { return snippetguts(1, (void *) t); } void add_statements(set &s) { assert(t->isStatementNode()); s.insert(static_cast(t)); } snippet *loopIntro() const { return new snippetLoopIntro(t); } snippet *loopOnly() const { return new snippetLoopOnly(t); } void rewrite(TreeNode *tc, TreeNode *can_megatile, TreeNode *else_part, llist *& l); private: TreeNode *t; TouchSet *r0, *w0, *r1, *w1; }; #endif