diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-17 03:22:53 +0000 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-17 03:22:53 +0000 |
commit | 75ff98e4d65862ff5b36b533b4f6e3ea71ede1d5 (patch) | |
tree | 498ac06b4cf78568b807fafd2619856afff69c28 /loop.cc | |
parent | 29efa7b1a0d089e02a70f73f348f11878955287c (diff) | |
download | chill-75ff98e4d65862ff5b36b533b4f6e3ea71ede1d5.tar.gz chill-75ff98e4d65862ff5b36b533b4f6e3ea71ede1d5.tar.bz2 chill-75ff98e4d65862ff5b36b533b4f6e3ea71ede1d5.zip |
cmake build
Diffstat (limited to 'loop.cc')
-rw-r--r-- | loop.cc | 1870 |
1 files changed, 0 insertions, 1870 deletions
diff --git a/loop.cc b/loop.cc deleted file mode 100644 index 0a82f7a..0000000 --- a/loop.cc +++ /dev/null @@ -1,1870 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - Core loop transformation functionality. - - Notes: - "level" (starting from 1) means loop level and it corresponds to "dim" - (starting from 0) in transformed iteration space [c_1,l_1,c_2,l_2,...., - c_n,l_n,c_(n+1)], e.g., l_2 is loop level 2 in generated code, dim 3 - in transformed iteration space, and variable 4 in Omega relation. - All c's are constant numbers only and they will not show up as actual loops. - Formula: - dim = 2*level - 1 - var = dim + 1 - - History: - 10/2005 Created by Chun Chen. - 09/2009 Expand tile functionality, -chun - 10/2009 Initialize unfusible loop nest without bailing out, -chun -*****************************************************************************/ - -#include <limits.h> -#include <math.h> -#include <codegen.h> -#include <code_gen/CG_utils.h> -#include <iostream> -#include <algorithm> -#include <map> -#include "loop.hh" -#include "omegatools.hh" -#include "irtools.hh" -#include "chill_error.hh" -#include <string.h> -#include <list> -using namespace omega; - -const std::string Loop::tmp_loop_var_name_prefix = std::string("chill_t"); // Manu:: In fortran, first character of a variable name must be a letter, so this change -const std::string Loop::overflow_var_name_prefix = std::string("over"); - -//----------------------------------------------------------------------------- -// Class Loop -//----------------------------------------------------------------------------- -// --begin Anand: Added from CHiLL 0.2 - -bool Loop::isInitialized() const { - return stmt.size() != 0 && !stmt[0].xform.is_null(); -} - -//--end Anand: added from CHiLL 0.2 - -bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, - std::vector<ir_tree_node *> &ir_stmt) { - - ir_stmt = extract_ir_stmts(ir_tree); - stmt_nesting_level_.resize(ir_stmt.size()); - std::vector<int> stmt_nesting_level(ir_stmt.size()); - for (int i = 0; i < ir_stmt.size(); i++) { - ir_stmt[i]->payload = i; - int t = 0; - ir_tree_node *itn = ir_stmt[i]; - while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - t++; - } - stmt_nesting_level_[i] = t; - stmt_nesting_level[i] = t; - } - - stmt = std::vector<Statement>(ir_stmt.size()); - int n_dim = -1; - int max_loc; - //std::vector<std::string> index; - for (int i = 0; i < ir_stmt.size(); i++) { - int max_nesting_level = -1; - int loc; - for (int j = 0; j < ir_stmt.size(); j++) - if (stmt_nesting_level[j] > max_nesting_level) { - max_nesting_level = stmt_nesting_level[j]; - loc = j; - } - - // most deeply nested statement acting as a reference point - if (n_dim == -1) { - n_dim = max_nesting_level; - max_loc = loc; - - index = std::vector<std::string>(n_dim); - - ir_tree_node *itn = ir_stmt[loc]; - int cur_dim = n_dim - 1; - while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) { - index[cur_dim] = - static_cast<IR_Loop *>(itn->content)->index()->name(); - itn->payload = cur_dim--; - } - } - } - - // align loops by names, temporary solution - ir_tree_node *itn = ir_stmt[loc]; - int depth = stmt_nesting_level_[loc] - 1; - /* while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP && itn->payload == -1) { - std::string name = static_cast<IR_Loop *>(itn->content)->index()->name(); - for (int j = 0; j < n_dim; j++) - if (index[j] == name) { - itn->payload = j; - break; - } - if (itn->payload == -1) - throw loop_error("no complex alignment yet"); - } - } - */ - for (int t = depth; t >= 0; t--) { - int y = t; - ir_tree_node *itn = ir_stmt[loc]; - - while ((itn->parent != NULL) && (y >= 0)) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - y--; - } - - if (itn->content->type() == IR_CONTROL_LOOP && itn->payload == -1) { - CG_outputBuilder *ocg = ir->builder(); - - itn->payload = depth - t; - - CG_outputRepr *code = - static_cast<IR_Block *>(ir_stmt[loc]->content)->extract(); - - std::vector<CG_outputRepr *> index_expr; - std::vector<std::string> old_index; - CG_outputRepr *repl = ocg->CreateIdent(index[itn->payload]); - index_expr.push_back(repl); - old_index.push_back( - static_cast<IR_Loop *>(itn->content)->index()->name()); - code = ocg->CreateSubstitutedStmt(0, code, old_index, - index_expr); - - replace.insert(std::pair<int, CG_outputRepr*>(loc, code)); - //stmt[loc].code = code; - - } - } - - // set relation variable names - Relation r(n_dim); - F_And *f_root = r.add_and(); - itn = ir_stmt[loc]; - int temp_depth = depth; - while (itn->parent != NULL) { - - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) { - r.name_set_var(itn->payload + 1, index[temp_depth]); - - temp_depth--; - } - //static_cast<IR_Loop *>(itn->content)->index()->name()); - } - - /*while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP) - r.name_set_var(itn->payload+1, static_cast<IR_Loop *>(itn->content)->index()->name()); - }*/ - - // extract information from loop/if structures - std::vector<bool> processed(n_dim, false); - std::vector<std::string> vars_to_be_reversed; - itn = ir_stmt[loc]; - while (itn->parent != NULL) { - itn = itn->parent; - - switch (itn->content->type()) { - case IR_CONTROL_LOOP: { - IR_Loop *lp = static_cast<IR_Loop *>(itn->content); - Variable_ID v = r.set_var(itn->payload + 1); - int c; - - try { - c = lp->step_size(); - if (c > 0) { - CG_outputRepr *lb = lp->lower_bound(); - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true); - CG_outputRepr *ub = lp->upper_bound(); - IR_CONDITION_TYPE cond = lp->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - cond, true); - else - throw ir_error("loop condition not supported"); - - } else if (c < 0) { - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *lb = lp->lower_bound(); - lb = ocg->CreateMinus(NULL, lb); - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true); - CG_outputRepr *ub = lp->upper_bound(); - ub = ocg->CreateMinus(NULL, ub); - IR_CONDITION_TYPE cond = lp->stop_cond(); - if (cond == IR_COND_GE) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LE, true); - else if (cond == IR_COND_GT) - exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LT, true); - else - throw ir_error("loop condition not supported"); - - vars_to_be_reversed.push_back(lp->index()->name()); - } else - throw ir_error("loop step size zero"); - } catch (const ir_error &e) { - for (int i = 0; i < itn->children.size(); i++) - delete itn->children[i]; - itn->children = std::vector<ir_tree_node *>(); - itn->content = itn->content->convert(); - return false; - } - - if (abs(c) != 1) { - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e = f_exists->declare(); - F_And *f_and = f_exists->add_and(); - Stride_Handle h = f_and->add_stride(abs(c)); - if (c > 0) - h.update_coef(e, 1); - else - h.update_coef(e, -1); - h.update_coef(v, -1); - CG_outputRepr *lb = lp->lower_bound(); - exp2formula(ir, r, f_and, freevar, lb, e, 's', IR_COND_EQ, - true); - } - - processed[itn->payload] = true; - break; - } - case IR_CONTROL_IF: { - CG_outputRepr *cond = - static_cast<IR_If *>(itn->content)->condition(); - try { - if (itn->payload % 2 == 1) - exp2constraint(ir, r, f_root, freevar, cond, true); - else { - F_Not *f_not = f_root->add_not(); - F_And *f_and = f_not->add_and(); - exp2constraint(ir, r, f_and, freevar, cond, true); - } - } catch (const ir_error &e) { - std::vector<ir_tree_node *> *t; - if (itn->parent == NULL) - t = &ir_tree; - else - t = &(itn->parent->children); - int id = itn->payload; - int i = t->size() - 1; - while (i >= 0) { - if ((*t)[i] == itn) { - for (int j = 0; j < itn->children.size(); j++) - delete itn->children[j]; - itn->children = std::vector<ir_tree_node *>(); - itn->content = itn->content->convert(); - } else if ((*t)[i]->payload >> 1 == id >> 1) { - delete (*t)[i]; - t->erase(t->begin() + i); - } - i--; - } - return false; - } - - break; - } - default: - for (int i = 0; i < itn->children.size(); i++) - delete itn->children[i]; - itn->children = std::vector<ir_tree_node *>(); - itn->content = itn->content->convert(); - return false; - } - } - - // add information for missing loops - for (int j = 0; j < n_dim; j++) - if (!processed[j]) { - ir_tree_node *itn = ir_stmt[max_loc]; - while (itn->parent != NULL) { - itn = itn->parent; - if (itn->content->type() == IR_CONTROL_LOOP - && itn->payload == j) - break; - } - - Variable_ID v = r.set_var(j + 1); - if (loc < max_loc) { - - CG_outputBuilder *ocg = ir->builder(); - - CG_outputRepr *lb = - static_cast<IR_Loop *>(itn->content)->lower_bound(); - - exp2formula(ir, r, f_root, freevar, lb, v, 's', IR_COND_EQ, - false); - - /* if (ir->QueryExpOperation( - static_cast<IR_Loop *>(itn->content)->lower_bound()) - == IR_OP_VARIABLE) { - IR_ScalarRef *ref = - static_cast<IR_ScalarRef *>(ir->Repr2Ref( - static_cast<IR_Loop *>(itn->content)->lower_bound())); - std::string name_ = ref->name(); - - for (int i = 0; i < index.size(); i++) - if (index[i] == name_) { - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, false); - - CG_outputRepr *ub = - static_cast<IR_Loop *>(itn->content)->upper_bound(); - IR_CONDITION_TYPE cond = - static_cast<IR_Loop *>(itn->content)->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, - 's', cond, false); - - - - } - - } - */ - - } else { // loc > max_loc - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *ub = - static_cast<IR_Loop *>(itn->content)->upper_bound(); - - exp2formula(ir, r, f_root, freevar, ub, v, 's', IR_COND_EQ, - false); - /*if (ir->QueryExpOperation( - static_cast<IR_Loop *>(itn->content)->upper_bound()) - == IR_OP_VARIABLE) { - IR_ScalarRef *ref = - static_cast<IR_ScalarRef *>(ir->Repr2Ref( - static_cast<IR_Loop *>(itn->content)->upper_bound())); - std::string name_ = ref->name(); - - for (int i = 0; i < index.size(); i++) - if (index[i] == name_) { - - CG_outputRepr *lb = - static_cast<IR_Loop *>(itn->content)->lower_bound(); - - exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, false); - - CG_outputRepr *ub = - static_cast<IR_Loop *>(itn->content)->upper_bound(); - IR_CONDITION_TYPE cond = - static_cast<IR_Loop *>(itn->content)->stop_cond(); - if (cond == IR_COND_LT || cond == IR_COND_LE) - exp2formula(ir, r, f_root, freevar, ub, v, - 's', cond, false); - - - } - } - */ - } - } - - r.setup_names(); - r.simplify(); - - // insert the statement - CG_outputBuilder *ocg = ir->builder(); - std::vector<CG_outputRepr *> reverse_expr; - for (int j = 1; j <= vars_to_be_reversed.size(); j++) { - CG_outputRepr *repl = ocg->CreateIdent(vars_to_be_reversed[j]); - repl = ocg->CreateMinus(NULL, repl); - reverse_expr.push_back(repl); - } - CG_outputRepr *code = - static_cast<IR_Block *>(ir_stmt[loc]->content)->extract(); - code = ocg->CreateSubstitutedStmt(0, code, vars_to_be_reversed, - reverse_expr); - stmt[loc].code = code; - stmt[loc].IS = r; - stmt[loc].loop_level = std::vector<LoopLevel>(n_dim); - stmt[loc].ir_stmt_node = ir_stmt[loc]; - for (int i = 0; i < n_dim; i++) { - stmt[loc].loop_level[i].type = LoopLevelOriginal; - stmt[loc].loop_level[i].payload = i; - stmt[loc].loop_level[i].parallel_level = 0; - } - - stmt_nesting_level[loc] = -1; - } - - return true; -} - -Loop::Loop(const IR_Control *control) { - - last_compute_cgr_ = NULL; - last_compute_cg_ = NULL; - - ir = const_cast<IR_Code *>(control->ir_); - init_code = NULL; - cleanup_code = NULL; - tmp_loop_var_name_counter = 1; - overflow_var_name_counter = 1; - known = Relation::True(0); - - ir_tree = build_ir_tree(control->clone(), NULL); - // std::vector<ir_tree_node *> ir_stmt; - - while (!init_loop(ir_tree, ir_stmt)) { - } - - - - for (int i = 0; i < stmt.size(); i++) { - std::map<int, CG_outputRepr*>::iterator it = replace.find(i); - - if (it != replace.end()) - stmt[i].code = it->second; - else - stmt[i].code = stmt[i].code; - } - - if (stmt.size() != 0) - dep = DependenceGraph(stmt[0].IS.n_set()); - else - dep = DependenceGraph(0); - // init the dependence graph - for (int i = 0; i < stmt.size(); i++) - dep.insert(); - - for (int i = 0; i < stmt.size(); i++) - for (int j = i; j < stmt.size(); j++) { - std::pair<std::vector<DependenceVector>, - std::vector<DependenceVector> > dv = test_data_dependences( - ir, stmt[i].code, stmt[i].IS, stmt[j].code, stmt[j].IS, - freevar, index, stmt_nesting_level_[i], - stmt_nesting_level_[j]); - - for (int k = 0; k < dv.first.size(); k++) { - if (is_dependence_valid(ir_stmt[i], ir_stmt[j], dv.first[k], - true)) - dep.connect(i, j, dv.first[k]); - else { - dep.connect(j, i, dv.first[k].reverse()); - } - - } - for (int k = 0; k < dv.second.size(); k++) - if (is_dependence_valid(ir_stmt[j], ir_stmt[i], dv.second[k], - false)) - dep.connect(j, i, dv.second[k]); - else { - dep.connect(i, j, dv.second[k].reverse()); - } - // std::pair<std::vector<DependenceVector>, - // std::vector<DependenceVector> > dv_ = test_data_dependences( - - } - - - - // init dumb transformation relations e.g. [i, j] -> [ 0, i, 0, j, 0] - for (int i = 0; i < stmt.size(); i++) { - int n = stmt[i].IS.n_set(); - stmt[i].xform = Relation(n, 2 * n + 1); - F_And *f_root = stmt[i].xform.add_and(); - - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(stmt[i].xform.output_var(2 * j), 1); - h.update_coef(stmt[i].xform.input_var(j), -1); - } - - for (int j = 1; j <= 2 * n + 1; j += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(stmt[i].xform.output_var(j), 1); - } - stmt[i].xform.simplify(); - } - - if (stmt.size() != 0) - num_dep_dim = stmt[0].IS.n_set(); - else - num_dep_dim = 0; - // debug - /*for (int i = 0; i < stmt.size(); i++) { - std::cout << i << ": "; - //stmt[i].xform.print(); - stmt[i].IS.print(); - std::cout << std::endl; - - }*/ - //end debug -} - -Loop::~Loop() { - - delete last_compute_cgr_; - delete last_compute_cg_; - - for (int i = 0; i < stmt.size(); i++) - if (stmt[i].code != NULL) { - stmt[i].code->clear(); - delete stmt[i].code; - } - - for (int i = 0; i < ir_tree.size(); i++) - delete ir_tree[i]; - - if (init_code != NULL) { - init_code->clear(); - delete init_code; - } - if (cleanup_code != NULL) { - cleanup_code->clear(); - delete cleanup_code; - } -} - -int Loop::get_dep_dim_of(int stmt_num, int level) const { - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - - if (level < 1 || level > stmt[stmt_num].loop_level.size()) - return -1; - - int trip_count = 0; - while (true) { - switch (stmt[stmt_num].loop_level[level - 1].type) { - case LoopLevelOriginal: - return stmt[stmt_num].loop_level[level - 1].payload; - case LoopLevelTile: - level = stmt[stmt_num].loop_level[level - 1].payload; - if (level < 1) - return -1; - if (level > stmt[stmt_num].loop_level.size()) - throw loop_error( - "incorrect loop level information for statement " - + to_string(stmt_num)); - break; - default: - throw loop_error( - "unknown loop level information for statement " - + to_string(stmt_num)); - } - trip_count++; - if (trip_count >= stmt[stmt_num].loop_level.size()) - throw loop_error( - "incorrect loop level information for statement " - + to_string(stmt_num)); - } -} - -int Loop::get_last_dep_dim_before(int stmt_num, int level) const { - if (stmt_num < 0 || stmt_num >= stmt.size()) - throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - - if (level < 1) - return -1; - if (level > stmt[stmt_num].loop_level.size()) - level = stmt[stmt_num].loop_level.size() + 1; - - for (int i = level - 1; i >= 1; i--) - if (stmt[stmt_num].loop_level[i - 1].type == LoopLevelOriginal) - return stmt[stmt_num].loop_level[i - 1].payload; - - return -1; -} - -void Loop::print_internal_loop_structure() const { - for (int i = 0; i < stmt.size(); i++) { - std::vector<int> lex = getLexicalOrder(i); - std::cout << "s" << i + 1 << ": "; - for (int j = 0; j < stmt[i].loop_level.size(); j++) { - if (2 * j < lex.size()) - std::cout << lex[2 * j]; - switch (stmt[i].loop_level[j].type) { - case LoopLevelOriginal: - std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; - break; - case LoopLevelTile: - std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; - break; - default: - std::cout << "(unknown)"; - } - std::cout << ' '; - } - for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { - std::cout << lex[j]; - if (j != lex.size() - 1) - std::cout << ' '; - } - std::cout << std::endl; - } -} - -CG_outputRepr *Loop::getCode(int effort) const { - const int m = stmt.size(); - if (m == 0) - return NULL; - const int n = stmt[0].xform.n_out(); - - if (last_compute_cg_ == NULL) { - std::vector<Relation> IS(m); - std::vector<Relation> xforms(m); - for (int i = 0; i < m; i++) { - IS[i] = stmt[i].IS; - xforms[i] = stmt[i].xform; - } - Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - - last_compute_cg_ = new CodeGen(xforms, IS, known); - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - } - - if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { - delete last_compute_cgr_; - last_compute_cgr_ = last_compute_cg_->buildAST(effort); - last_compute_effort_ = effort; - } - - std::vector<CG_outputRepr *> stmts(m); - for (int i = 0; i < m; i++) - stmts[i] = stmt[i].code; - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *repr = last_compute_cgr_->printRepr(ocg, stmts); - - if (init_code != NULL) - repr = ocg->StmtListAppend(init_code->clone(), repr); - if (cleanup_code != NULL) - repr = ocg->StmtListAppend(repr, cleanup_code->clone()); - - return repr; -} - -void Loop::printCode(int effort) const { - const int m = stmt.size(); - if (m == 0) - return; - const int n = stmt[0].xform.n_out(); - - if (last_compute_cg_ == NULL) { - std::vector<Relation> IS(m); - std::vector<Relation> xforms(m); - for (int i = 0; i < m; i++) { - IS[i] = stmt[i].IS; - xforms[i] = stmt[i].xform; - } - Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - - last_compute_cg_ = new CodeGen(xforms, IS, known); - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - } - - if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { - delete last_compute_cgr_; - last_compute_cgr_ = last_compute_cg_->buildAST(effort); - last_compute_effort_ = effort; - } - - std::string repr = last_compute_cgr_->printString(); - std::cout << repr << std::endl; -} - -void Loop::printIterationSpace() const { - for (int i = 0; i < stmt.size(); i++) { - std::cout << "s" << i << ": "; - Relation r = getNewIS(i); - for (int j = 1; j <= r.n_inp(); j++) - r.name_input_var(j, CodeGen::loop_var_name_prefix + to_string(j)); - r.setup_names(); - r.print(); - } -} - -void Loop::printDependenceGraph() const { - if (dep.edgeCount() == 0) - std::cout << "no dependence exists" << std::endl; - else { - std::cout << "dependence graph:" << std::endl; - std::cout << dep; - } -} - -Relation Loop::getNewIS(int stmt_num) const { - Relation result; - - if (stmt[stmt_num].xform.is_null()) { - Relation known = Extend_Set(copy(this->known), - stmt[stmt_num].IS.n_set() - this->known.n_set()); - result = Intersection(copy(stmt[stmt_num].IS), known); - } else { - Relation known = Extend_Set(copy(this->known), - stmt[stmt_num].xform.n_out() - this->known.n_set()); - result = Intersection( - Range( - Restrict_Domain(copy(stmt[stmt_num].xform), - copy(stmt[stmt_num].IS))), known); - } - - result.simplify(2, 4); - - return result; -} - -std::vector<Relation> Loop::getNewIS() const { - const int m = stmt.size(); - - std::vector<Relation> new_IS(m); - for (int i = 0; i < m; i++) - new_IS[i] = getNewIS(i); - - return new_IS; -} - -void Loop::pragma(int stmt_num, int level, const std::string &pragmaText) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePragmaAttribute(code, level, pragmaText); -} -/* -void Loop::prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePrefetchAttribute(code, level, arrName, indexName, int offset, hint); -} -*/ - -void Loop::prefetch(int stmt_num, int level, const std::string &arrName, int hint) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePrefetchAttribute(code, level, arrName, hint); -} - -std::vector<int> Loop::getLexicalOrder(int stmt_num) const { - assert(stmt_num < stmt.size()); - - const int n = stmt[stmt_num].xform.n_out(); - std::vector<int> lex(n, 0); - - for (int i = 0; i < n; i += 2) - lex[i] = get_const(stmt[stmt_num].xform, i, Output_Var); - - return lex; -} - -// find the sub loop nest specified by stmt_num and level, -// only iteration space satisfiable statements returned. -std::set<int> Loop::getSubLoopNest(int stmt_num, int level) const { - assert(stmt_num >= 0 && stmt_num < stmt.size()); - assert(level > 0 && level <= stmt[stmt_num].loop_level.size()); - - std::set<int> working; - for (int i = 0; i < stmt.size(); i++) - if (const_cast<Loop *>(this)->stmt[i].IS.is_upper_bound_satisfiable() - && stmt[i].loop_level.size() >= level) - working.insert(i); - - for (int i = 1; i <= level; i++) { - int a = getLexicalOrder(stmt_num, i); - for (std::set<int>::iterator j = working.begin(); j != working.end();) { - int b = getLexicalOrder(*j, i); - if (b != a) - working.erase(j++); - else - ++j; - } - } - - return working; -} - -int Loop::getLexicalOrder(int stmt_num, int level) const { - assert(stmt_num >= 0 && stmt_num < stmt.size()); - assert(level > 0 && level <= stmt[stmt_num].loop_level.size()+1); - - Relation &r = const_cast<Loop *>(this)->stmt[stmt_num].xform; - for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) - if (abs((*e).get_coef(r.output_var(2 * level - 1))) == 1) { - bool is_const = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var() != r.output_var(2 * level - 1)) { - is_const = false; - break; - } - if (is_const) { - int t = static_cast<int>((*e).get_const()); - return (*e).get_coef(r.output_var(2 * level - 1)) > 0 ? -t : t; - } - } - - throw loop_error( - "can't find lexical order for statement " + to_string(stmt_num) - + "'s loop level " + to_string(level)); -} - -std::set<int> Loop::getStatements(const std::vector<int> &lex, int dim) const { - const int m = stmt.size(); - - std::set<int> same_loops; - for (int i = 0; i < m; i++) { - if (dim < 0) - same_loops.insert(i); - else { - std::vector<int> a_lex = getLexicalOrder(i); - int j; - for (j = 0; j <= dim; j += 2) - if (lex[j] != a_lex[j]) - break; - if (j > dim) - same_loops.insert(i); - } - - } - - return same_loops; -} - -void Loop::shiftLexicalOrder(const std::vector<int> &lex, int dim, int amount) { - const int m = stmt.size(); - - if (amount == 0) - return; - - for (int i = 0; i < m; i++) { - std::vector<int> lex2 = getLexicalOrder(i); - - bool need_shift = true; - - for (int j = 0; j < dim; j++) - if (lex2[j] != lex[j]) { - need_shift = false; - break; - } - - if (!need_shift) - continue; - - if (amount > 0) { - if (lex2[dim] < lex[dim]) - continue; - } else if (amount < 0) { - if (lex2[dim] > lex[dim]) - continue; - } - - assign_const(stmt[i].xform, dim, lex2[dim] + amount); - } -} - -std::vector<std::set<int> > Loop::sort_by_same_loops(std::set<int> active, - int level) { - - std::set<int> not_nested_at_this_level; - std::map<ir_tree_node*, std::set<int> > sorted_by_loop; - std::map<int, std::set<int> > sorted_by_lex_order; - std::vector<std::set<int> > to_return; - bool lex_order_already_set = false; - for (std::set<int>::iterator it = active.begin(); it != active.end(); - it++) { - - if (stmt[*it].ir_stmt_node == NULL) - lex_order_already_set = true; - } - - if (lex_order_already_set) { - - for (std::set<int>::iterator it = active.begin(); it != active.end(); - it++) { - std::map<int, std::set<int> >::iterator it2 = - sorted_by_lex_order.find( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var)); - - if (it2 != sorted_by_lex_order.end()) - it2->second.insert(*it); - else { - - std::set<int> to_insert; - - to_insert.insert(*it); - - sorted_by_lex_order.insert( - std::pair<int, std::set<int> >( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var), to_insert)); - - } - - } - - for (std::map<int, std::set<int> >::iterator it2 = - sorted_by_lex_order.begin(); it2 != sorted_by_lex_order.end(); - it2++) - to_return.push_back(it2->second); - - } else { - - for (std::set<int>::iterator it = active.begin(); it != active.end(); - it++) { - - ir_tree_node* itn = stmt[*it].ir_stmt_node; - itn = itn->parent; - while ((itn != NULL) && (itn->payload != level - 1)) - itn = itn->parent; - - if (itn == NULL) - not_nested_at_this_level.insert(*it); - else { - std::map<ir_tree_node*, std::set<int> >::iterator it2 = - sorted_by_loop.find(itn); - - if (it2 != sorted_by_loop.end()) - it2->second.insert(*it); - else { - std::set<int> to_insert; - - to_insert.insert(*it); - - sorted_by_loop.insert( - std::pair<ir_tree_node*, std::set<int> >(itn, - to_insert)); - - } - - } - - } - if (not_nested_at_this_level.size() > 0) { - for (std::set<int>::iterator it = not_nested_at_this_level.begin(); - it != not_nested_at_this_level.end(); it++) { - std::set<int> temp; - temp.insert(*it); - to_return.push_back(temp); - - } - } - for (std::map<ir_tree_node*, std::set<int> >::iterator it2 = - sorted_by_loop.begin(); it2 != sorted_by_loop.end(); it2++) - to_return.push_back(it2->second); - } - return to_return; -} - -void update_successors(int n, int node_num[], int cant_fuse_with[], - Graph<std::set<int>, bool> &g, std::list<int> &work_list) { - - std::set<int> disconnect; - for (Graph<std::set<int>, bool>::EdgeList::iterator i = - g.vertex[n].second.begin(); i != g.vertex[n].second.end(); i++) { - int m = i->first; - - if (node_num[m] != -1) - throw loop_error("Graph input for fusion has cycles not a DAG!!"); - - std::vector<bool> check_ = g.getEdge(n, m); - - bool has_bad_edge_path = false; - for (int i = 0; i < check_.size(); i++) - if (!check_[i]) { - has_bad_edge_path = true; - break; - } - if (has_bad_edge_path) - cant_fuse_with[m] = std::max(cant_fuse_with[m], node_num[n]); - else - cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); - disconnect.insert(m); - } - - - for (std::set<int>::iterator i = disconnect.begin(); i != disconnect.end(); - i++) { - g.disconnect(n, *i); - - bool no_incoming_edges = true; - for (int j = 0; j < g.vertex.size(); j++) - if (j != *i) - if (g.hasEdge(j, *i)) { - no_incoming_edges = false; - break; - } - - - if (no_incoming_edges) - work_list.push_back(*i); - } - -} - -Graph<std::set<int>, bool> Loop::construct_induced_graph_at_level( - std::vector<std::set<int> > s, DependenceGraph dep, int dep_dim) { - Graph<std::set<int>, bool> g; - - for (int i = 0; i < s.size(); i++) - g.insert(s[i]); - - for (int i = 0; i < s.size(); i++) { - - for (int j = i + 1; j < s.size(); j++) { - bool has_true_edge_i_to_j = false; - bool has_true_edge_j_to_i = false; - bool is_connected_i_to_j = false; - bool is_connected_j_to_i = false; - for (std::set<int>::iterator ii = s[i].begin(); ii != s[i].end(); - ii++) { - - for (std::set<int>::iterator jj = s[j].begin(); - jj != s[j].end(); jj++) { - - std::vector<DependenceVector> dvs = dep.getEdge(*ii, *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && dvs[k].has_been_carried_at(dep_dim))) { - - if (dvs[k].is_data_dependence() - && dvs[k].has_negative_been_carried_at( - dep_dim)) { - //g.connect(i, j, false); - is_connected_i_to_j = true; - break; - } else { - //g.connect(i, j, true); - - has_true_edge_i_to_j = true; - //break - } - } - - //if (is_connected) - - // break; - // if (has_true_edge_i_to_j && !is_connected_i_to_j) - // g.connect(i, j, true); - dvs = dep.getEdge(*jj, *ii); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && dvs[k].has_been_carried_at(dep_dim))) { - - if (is_connected_i_to_j || has_true_edge_i_to_j) - throw loop_error( - "Graph input for fusion has cycles not a DAG!!"); - - if (dvs[k].is_data_dependence() - && dvs[k].has_negative_been_carried_at( - dep_dim)) { - //g.connect(i, j, false); - is_connected_j_to_i = true; - break; - } else { - //g.connect(i, j, true); - - has_true_edge_j_to_i = true; - //break; - } - } - - // if (is_connected) - //break; - // if (is_connected) - //break; - } - - - //if (is_connected) - // break; - } - - - if (is_connected_i_to_j) - g.connect(i, j, false); - else if (has_true_edge_i_to_j) - g.connect(i, j, true); - - if (is_connected_j_to_i) - g.connect(j, i, false); - else if (has_true_edge_j_to_i) - g.connect(j, i, true); - - - } - } - return g; -} - -std::vector<std::set<int> > Loop::typed_fusion(Graph<std::set<int>, bool> g) { - - bool roots[g.vertex.size()]; - - for (int i = 0; i < g.vertex.size(); i++) - roots[i] = true; - - for (int i = 0; i < g.vertex.size(); i++) - for (int j = i + 1; j < g.vertex.size(); j++) { - - if (g.hasEdge(i, j)) - roots[j] = false; - - if (g.hasEdge(j, i)) - roots[i] = false; - - } - - std::list<int> work_list; - int cant_fuse_with[g.vertex.size()]; - std::vector<std::set<int> > s; - //Each Fused set's representative node - - int node_to_fused_nodes[g.vertex.size()]; - int node_num[g.vertex.size()]; - for (int i = 0; i < g.vertex.size(); i++) { - if (roots[i] == true) - work_list.push_back(i); - cant_fuse_with[i] = 0; - node_to_fused_nodes[i] = 0; - node_num[i] = -1; - } - // topological sort according to chun's permute algorithm - // std::vector<std::set<int> > s = g.topoSort(); - std::vector<std::set<int> > s2 = g.topoSort(); - if (work_list.empty() || (s2.size() != g.vertex.size())) { - - std::cout << s2.size() << "\t" << g.vertex.size() << std::endl; - throw loop_error("Input for fusion not a DAG!!"); - - - } - int fused_nodes_counter = 0; - while (!work_list.empty()) { - int n = work_list.front(); - //int n_ = g.vertex[n].first; - work_list.pop_front(); - int node; - if (cant_fuse_with[n] == 0) - node = 0; - else - node = cant_fuse_with[n]; - - if ((fused_nodes_counter != 0) && (node != fused_nodes_counter)) { - int rep_node = node_to_fused_nodes[node]; - node_num[n] = node_num[rep_node]; - - try { - update_successors(n, node_num, cant_fuse_with, g, work_list); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - - } - for (std::set<int>::iterator it = g.vertex[n].first.begin(); - it != g.vertex[n].first.end(); it++) - s[node].insert(*it); - } else { - //std::set<int> new_node; - //new_node.insert(n_); - s.push_back(g.vertex[n].first); - node_to_fused_nodes[node] = n; - node_num[n] = ++node; - try { - update_successors(n, node_num, cant_fuse_with, g, work_list); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - - } - fused_nodes_counter++; - } - } - - return s; -} - -void Loop::setLexicalOrder(int dim, const std::set<int> &active, - int starting_order, std::vector<std::vector<std::string> > idxNames) { - if (active.size() == 0) - return; - - // check for sanity of parameters - if (dim < 0 || dim % 2 != 0) - throw std::invalid_argument( - "invalid constant loop level to set lexicographical order"); - std::vector<int> lex; - int ref_stmt_num; - for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { - if ((*i) < 0 || (*i) >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(*i)); - if (dim >= stmt[*i].xform.n_out()) - throw std::invalid_argument( - "invalid constant loop level to set lexicographical order"); - if (i == active.begin()) { - lex = getLexicalOrder(*i); - ref_stmt_num = *i; - } else { - std::vector<int> lex2 = getLexicalOrder(*i); - for (int j = 0; j < dim; j += 2) - if (lex[j] != lex2[j]) - throw std::invalid_argument( - "statements are not in the same sub loop nest"); - } - } - - // sepearate statements by current loop level types - int level = (dim + 2) / 2; - std::map<std::pair<LoopLevelType, int>, std::set<int> > active_by_level_type; - std::set<int> active_by_no_level; - for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { - if (level > stmt[*i].loop_level.size()) - active_by_no_level.insert(*i); - else - active_by_level_type[std::make_pair( - stmt[*i].loop_level[level - 1].type, - stmt[*i].loop_level[level - 1].payload)].insert(*i); - } - - // further separate statements due to control dependences - std::vector<std::set<int> > active_by_level_type_splitted; - for (std::map<std::pair<LoopLevelType, int>, std::set<int> >::iterator i = - active_by_level_type.begin(); i != active_by_level_type.end(); i++) - active_by_level_type_splitted.push_back(i->second); - for (std::set<int>::iterator i = active_by_no_level.begin(); - i != active_by_no_level.end(); i++) - for (int j = active_by_level_type_splitted.size() - 1; j >= 0; j--) { - std::set<int> controlled, not_controlled; - for (std::set<int>::iterator k = - active_by_level_type_splitted[j].begin(); - k != active_by_level_type_splitted[j].end(); k++) { - std::vector<DependenceVector> dvs = dep.getEdge(*i, *k); - bool is_controlled = false; - for (int kk = 0; kk < dvs.size(); kk++) - if (dvs[kk].type = DEP_CONTROL) { - is_controlled = true; - break; - } - if (is_controlled) - controlled.insert(*k); - else - not_controlled.insert(*k); - } - if (controlled.size() != 0 && not_controlled.size() != 0) { - active_by_level_type_splitted.erase( - active_by_level_type_splitted.begin() + j); - active_by_level_type_splitted.push_back(controlled); - active_by_level_type_splitted.push_back(not_controlled); - } - } - - // set lexical order separating loops with different loop types first - if (active_by_level_type_splitted.size() + active_by_no_level.size() > 1) { - int dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; - - Graph<std::set<int>, Empty> g; - for (std::vector<std::set<int> >::iterator i = - active_by_level_type_splitted.begin(); - i != active_by_level_type_splitted.end(); i++) - g.insert(*i); - for (std::set<int>::iterator i = active_by_no_level.begin(); - i != active_by_no_level.end(); i++) { - std::set<int> t; - t.insert(*i); - g.insert(t); - } - for (int i = 0; i < g.vertex.size(); i++) - for (int j = i + 1; j < g.vertex.size(); j++) { - bool connected = false; - for (std::set<int>::iterator ii = g.vertex[i].first.begin(); - ii != g.vertex[i].first.end(); ii++) { - for (std::set<int>::iterator jj = g.vertex[j].first.begin(); - jj != g.vertex[j].first.end(); jj++) { - std::vector<DependenceVector> dvs = dep.getEdge(*ii, - *jj); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && !dvs[k].has_been_carried_before( - dep_dim))) { - g.connect(i, j); - connected = true; - break; - } - if (connected) - break; - } - if (connected) - break; - } - connected = false; - for (std::set<int>::iterator ii = g.vertex[i].first.begin(); - ii != g.vertex[i].first.end(); ii++) { - for (std::set<int>::iterator jj = g.vertex[j].first.begin(); - jj != g.vertex[j].first.end(); jj++) { - std::vector<DependenceVector> dvs = dep.getEdge(*jj, - *ii); - // find the sub loop nest specified by stmt_num and level, - // only iteration space satisfiable statements returned. - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() - || (dvs[k].is_data_dependence() - && !dvs[k].has_been_carried_before( - dep_dim))) { - g.connect(j, i); - connected = true; - break; - } - if (connected) - break; - } - if (connected) - break; - } - } - - std::vector<std::set<int> > s = g.topoSort(); - if (s.size() != g.vertex.size()) - throw loop_error( - "cannot separate statements with different loop types at loop level " - + to_string(level)); - - // assign lexical order - int order = starting_order; - for (int i = 0; i < s.size(); i++) { - std::set<int> &cur_scc = g.vertex[*(s[i].begin())].first; - int sz = cur_scc.size(); - if (sz == 1) { - int cur_stmt = *(cur_scc.begin()); - assign_const(stmt[cur_stmt].xform, dim, order); - for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) - assign_const(stmt[cur_stmt].xform, j, 0); - order++; - } else { - setLexicalOrder(dim, cur_scc, order, idxNames); - order += sz; - } - } - } - // set lexical order seperating single iteration statements and loops - else { - std::set<int> true_singles; - std::set<int> nonsingles; - std::map<coef_t, std::set<int> > fake_singles; - std::set<int> fake_singles_; - - // sort out statements that do not require loops - for (std::set<int>::iterator i = active.begin(); i != active.end(); - i++) { - Relation cur_IS = getNewIS(*i); - if (is_single_iteration(cur_IS, dim + 1)) { - bool is_all_single = true; - for (int j = dim + 3; j < stmt[*i].xform.n_out(); j += 2) - if (!is_single_iteration(cur_IS, j)) { - is_all_single = false; - break; - } - if (is_all_single) - true_singles.insert(*i); - else { - fake_singles_.insert(*i); - try { - fake_singles[get_const(cur_IS, dim + 1, Set_Var)].insert( - *i); - } catch (const std::exception &e) { - fake_singles[posInfinity].insert(*i); - } - } - } else - nonsingles.insert(*i); - } - - - // split nonsingles forcibly according to negative dependences present (loop unfusible) - int dep_dim = get_dep_dim_of(ref_stmt_num, level); - - if (dim < stmt[ref_stmt_num].xform.n_out() - 1) { - - bool dummy_level_found = false; - - std::vector<std::set<int> > s; - - s = sort_by_same_loops(active, level); - bool further_levels_exist = false; - - if (!idxNames.empty()) - if (level <= idxNames[ref_stmt_num].size()) - if (idxNames[ref_stmt_num][level - 1].length() == 0) { - // && s.size() == 1) { - int order1 = 0; - dummy_level_found = true; - - for (int i = level; i < idxNames[ref_stmt_num].size(); - i++) - if (idxNames[ref_stmt_num][i].length() > 0) - further_levels_exist = true; - - } - - //if (!dummy_level_found) { - - if (s.size() > 1) { - - Graph<std::set<int>, bool> g = construct_induced_graph_at_level( - s, dep, dep_dim); - s = typed_fusion(g); - } - int order = 0; - for (int i = 0; i < s.size(); i++) { - - for (std::set<int>::iterator it = s[i].begin(); - it != s[i].end(); it++) - assign_const(stmt[*it].xform, dim, order); - - if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1)) - setLexicalOrder(dim + 2, s[i], order, idxNames); - - order++; - } - //} - /* else { - - int order1 = 0; - int order = 0; - for (std::set<int>::iterator i = active.begin(); - i != active.end(); i++) { - if (!further_levels_exist) - assign_const(stmt[*i].xform, dim, order1++); - else - assign_const(stmt[*i].xform, dim, order1); - - } - - if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1) && further_levels_exist) - setLexicalOrder(dim + 2, active, order, idxNames); - } - */ - } else { - int dummy_order = 0; - for (std::set<int>::iterator i = active.begin(); i != active.end(); - i++) - assign_const(stmt[*i].xform, dim, dummy_order++); - } - /*for (int i = 0; i < g2.vertex.size(); i++) - for (int j = i+1; j < g2.vertex.size(); j++) { - std::vector<DependenceVector> dvs = dep.getEdge(g2.vertex[i].first, g2.vertex[j].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() || - (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { - g2.connect(i, j); - break; - } - dvs = dep.getEdge(g2.vertex[j].first, g2.vertex[i].first); - for (int k = 0; k < dvs.size(); k++) - if (dvs[k].is_control_dependence() || - (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { - g2.connect(j, i); - break; - } - } - - std::vector<std::set<int> > s2 = g2.packed_topoSort(); - - std::vector<std::set<int> > splitted_nonsingles; - for (int i = 0; i < s2.size(); i++) { - std::set<int> cur_scc; - for (std::set<int>::iterator j = s2[i].begin(); j != s2[i].end(); j++) - cur_scc.insert(g2.vertex[*j].first); - splitted_nonsingles.push_back(cur_scc); - } - */ - //convert to dependence graph for grouped statements - //dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; - /*int order = 0; - for (std::set<int>::iterator j = active.begin(); j != active.end(); - j++) { - std::set<int> continuous; - std::cout<< active.size()<<std::endl; - while (nonsingles.find(*j) != nonsingles.end() && j != active.end()) { - continuous.insert(*j); - j++; - } - - printf("continuous size is %d\n", continuous.size()); - - - - if (continuous.size() > 0) { - std::vector<std::set<int> > s = typed_fusion(continuous, dep, - dep_dim); - - for (int i = 0; i < s.size(); i++) { - for (std::set<int>::iterator l = s[i].begin(); - l != s[i].end(); l++) { - assign_const(stmt[*l].xform, dim + 2, order); - setLexicalOrder(dim + 2, s[i]); - } - order++; - } - } - - if (j != active.end()) { - assign_const(stmt[*j].xform, dim + 2, order); - - for (int k = dim + 4; k < stmt[*j].xform.n_out(); k += 2) - assign_const(stmt[*j].xform, k, 0); - order++; - } - - if( j == active.end()) - break; - } - */ - - - // assign lexical order - /*int order = starting_order; - for (int i = 0; i < s.size(); i++) { - // translate each SCC into original statements - std::set<int> cur_scc; - for (std::set<int>::iterator j = s[i].begin(); j != s[i].end(); j++) - copy(s[i].begin(), s[i].end(), - inserter(cur_scc, cur_scc.begin())); - - // now assign the constant - for (std::set<int>::iterator j = cur_scc.begin(); - j != cur_scc.end(); j++) - assign_const(stmt[*j].xform, dim, order); - - if (cur_scc.size() > 1) - setLexicalOrder(dim + 2, cur_scc); - else if (cur_scc.size() == 1) { - int cur_stmt = *(cur_scc.begin()); - for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) - assign_const(stmt[cur_stmt].xform, j, 0); - } - - if (cur_scc.size() > 0) - order++; - } - */ - } -} - -void Loop::apply_xform() { - std::set<int> active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - apply_xform(active); -} - -void Loop::apply_xform(int stmt_num) { - std::set<int> active; - active.insert(stmt_num); - apply_xform(active); -} - -void Loop::apply_xform(std::set<int> &active) { - int max_n = 0; - - CG_outputBuilder *ocg = ir->builder(); - for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { - int n = stmt[*i].loop_level.size(); - if (n > max_n) - max_n = n; - - std::vector<int> lex = getLexicalOrder(*i); - - Relation mapping(2 * n + 1, n); - F_And *f_root = mapping.add_and(); - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_coef(mapping.input_var(2 * j), -1); - } - mapping = Composition(mapping, stmt[*i].xform); - mapping.simplify(); - - // match omega input/output variables to variable names in the code - for (int j = 1; j <= stmt[*i].IS.n_set(); j++) - mapping.name_input_var(j, stmt[*i].IS.set_var(j)->name()); - for (int j = 1; j <= n; j++) - mapping.name_output_var(j, - tmp_loop_var_name_prefix - + to_string(tmp_loop_var_name_counter + j - 1)); - mapping.setup_names(); - - Relation known = Extend_Set(copy(this->known), - mapping.n_out() - this->known.n_set()); - //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector<CG_outputRepr *>(mapping.n_out(), NULL)); - std::vector<std::string> loop_vars; - for (int j = 1; j <= stmt[*i].IS.n_set(); j++) - loop_vars.push_back(stmt[*i].IS.set_var(j)->name()); - std::vector<CG_outputRepr *> subs = output_substitutions(ocg, - Inverse(copy(mapping)), - std::vector<std::pair<CG_outputRepr *, int> >(mapping.n_out(), - std::make_pair(static_cast<CG_outputRepr *>(NULL), 0))); - stmt[*i].code = ocg->CreateSubstitutedStmt(0, stmt[*i].code, loop_vars, - subs); - stmt[*i].IS = Range(Restrict_Domain(mapping, stmt[*i].IS)); - stmt[*i].IS.simplify(); - - // replace original transformation relation with straight 1-1 mapping - mapping = Relation(n, 2 * n + 1); - f_root = mapping.add_and(); - for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * j), 1); - h.update_coef(mapping.input_var(j), -1); - } - for (int j = 1; j <= 2 * n + 1; j += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(j), 1); - h.update_const(-lex[j - 1]); - } - stmt[*i].xform = mapping; - } - - tmp_loop_var_name_counter += max_n; -} - -void Loop::addKnown(const Relation &cond) { - - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - - int n1 = this->known.n_set(); - - Relation r = copy(cond); - int n2 = r.n_set(); - - if (n1 < n2) - this->known = Extend_Set(this->known, n2 - n1); - else if (n1 > n2) - r = Extend_Set(r, n1 - n2); - - this->known = Intersection(this->known, r); -} - -void Loop::removeDependence(int stmt_num_from, int stmt_num_to) { - // check for sanity of parameters - if (stmt_num_from >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_from)); - if (stmt_num_to >= stmt.size()) - throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_to)); - - dep.disconnect(stmt_num_from, stmt_num_to); -} - -void Loop::dump() const { - for (int i = 0; i < stmt.size(); i++) { - std::vector<int> lex = getLexicalOrder(i); - std::cout << "s" << i + 1 << ": "; - for (int j = 0; j < stmt[i].loop_level.size(); j++) { - if (2 * j < lex.size()) - std::cout << lex[2 * j]; - switch (stmt[i].loop_level[j].type) { - case LoopLevelOriginal: - std::cout << "(dim:" << stmt[i].loop_level[j].payload << ")"; - break; - case LoopLevelTile: - std::cout << "(tile:" << stmt[i].loop_level[j].payload << ")"; - break; - default: - std::cout << "(unknown)"; - } - std::cout << ' '; - } - for (int j = 2 * stmt[i].loop_level.size(); j < lex.size(); j += 2) { - std::cout << lex[j]; - if (j != lex.size() - 1) - std::cout << ' '; - } - std::cout << std::endl; - } -} - -bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { - if (stmt.size() == 0) - return true; - - // check for sanity of parameters - for (int i = 0; i < stmt.size(); i++) { - if (stmt[i].loop_level.size() != num_dep_dim) - throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); - for (int j = 0; j < stmt[i].loop_level.size(); j++) - if (stmt[i].loop_level[j].type != LoopLevelOriginal) - throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); - } - if (T.size() != num_dep_dim) - throw std::invalid_argument("invalid transformation matrix"); - for (int i = 0; i < stmt.size(); i++) - if (T[i].size() != num_dep_dim + 1 && T[i].size() != num_dep_dim) - throw std::invalid_argument("invalid transformation matrix"); - // invalidate saved codegen computation - delete last_compute_cgr_; - last_compute_cgr_ = NULL; - delete last_compute_cg_; - last_compute_cg_ = NULL; - // build relation from matrix - Relation mapping(2 * num_dep_dim + 1, 2 * num_dep_dim + 1); - F_And *f_root = mapping.add_and(); - for (int i = 0; i < num_dep_dim; i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(2 * (i + 1)), -1); - for (int j = 0; j < num_dep_dim; j++) - if (T[i][j] != 0) - h.update_coef(mapping.input_var(2 * (j + 1)), T[i][j]); - if (T[i].size() == num_dep_dim + 1) - h.update_const(T[i][num_dep_dim]); - } - for (int i = 1; i <= 2 * num_dep_dim + 1; i += 2) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(i), -1); - h.update_coef(mapping.input_var(i), 1); - } - - // update transformation relations - for (int i = 0; i < stmt.size(); i++) - stmt[i].xform = Composition(copy(mapping), stmt[i].xform); - - // update dependence graph - for (int i = 0; i < dep.vertex.size(); i++) - for (DependenceGraph::EdgeList::iterator j = - dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); - j++) { - std::vector<DependenceVector> dvs = j->second; - for (int k = 0; k < dvs.size(); k++) { - DependenceVector &dv = dvs[k]; - switch (dv.type) { - case DEP_W2R: - case DEP_R2W: - case DEP_W2W: - case DEP_R2R: { - std::vector<coef_t> lbounds(num_dep_dim), ubounds( - num_dep_dim); - for (int p = 0; p < num_dep_dim; p++) { - coef_t lb = 0; - coef_t ub = 0; - for (int q = 0; q < num_dep_dim; q++) { - if (T[p][q] > 0) { - if (lb == -posInfinity - || dv.lbounds[q] == -posInfinity) - lb = -posInfinity; - else - lb += T[p][q] * dv.lbounds[q]; - if (ub == posInfinity - || dv.ubounds[q] == posInfinity) - ub = posInfinity; - else - ub += T[p][q] * dv.ubounds[q]; - } else if (T[p][q] < 0) { - if (lb == -posInfinity - || dv.ubounds[q] == posInfinity) - lb = -posInfinity; - else - lb += T[p][q] * dv.ubounds[q]; - if (ub == posInfinity - || dv.lbounds[q] == -posInfinity) - ub = posInfinity; - else - ub += T[p][q] * dv.lbounds[q]; - } - } - if (T[p].size() == num_dep_dim + 1) { - if (lb != -posInfinity) - lb += T[p][num_dep_dim]; - if (ub != posInfinity) - ub += T[p][num_dep_dim]; - } - lbounds[p] = lb; - ubounds[p] = ub; - } - dv.lbounds = lbounds; - dv.ubounds = ubounds; - - break; - } - default: - ; - } - } - j->second = dvs; - } - - // set constant loop values - std::set<int> active; - for (int i = 0; i < stmt.size(); i++) - active.insert(i); - setLexicalOrder(0, active); - - return true; -} - - -bool Loop::is_dependence_valid_based_on_lex_order(int i, int j, - const DependenceVector &dv, bool before) { - std::vector<int> lex_i = getLexicalOrder(i); - std::vector<int> lex_j = getLexicalOrder(j); - int last_dim; - if (!dv.is_scalar_dependence) { - for (last_dim = 0; - last_dim < lex_i.size() && (lex_i[last_dim] == lex_j[last_dim]); - last_dim++) - ; - last_dim = last_dim / 2; - if (last_dim == 0) - return true; - - for (int i = 0; i < last_dim; i++) { - if (dv.lbounds[i] > 0) - return true; - else if (dv.lbounds[i] < 0) - return false; - } - } - if (before) - return true; - - return false; - -} - |