summaryrefslogtreecommitdiff
path: root/omegalib/codegen/src/codegen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'omegalib/codegen/src/codegen.cc')
-rwxr-xr-xomegalib/codegen/src/codegen.cc378
1 files changed, 0 insertions, 378 deletions
diff --git a/omegalib/codegen/src/codegen.cc b/omegalib/codegen/src/codegen.cc
deleted file mode 100755
index 92ca702..0000000
--- a/omegalib/codegen/src/codegen.cc
+++ /dev/null
@@ -1,378 +0,0 @@
-/*****************************************************************************
- Copyright (C) 1994-2000 the Omega Project Team
- Copyright (C) 2005-2011 Chun Chen
- All Rights Reserved.
-
- Purpose:
- CodeGen class as entry point for code generation.
-
- Notes:
- Loop variable name prefix should not cause any possible name conflicts
- with original loop variables wrapped in statement holder. This guarantees
- that variable substitution done correctly in the generated code.
-
- History:
- 04/24/96 MMGenerateCode, added by Fortran D people. Lei Zhou
- 09/17/08 loop overhead removal based on actual nesting depth -- by chun
- 03/05/11 fold MMGenerateCode into CodeGen class, Chun Chen
-*****************************************************************************/
-
-#include <typeinfo>
-#include <omega.h>
-#include <basic/util.h>
-#include <math.h>
-#include <vector>
-#include <algorithm>
-
-#include <code_gen/CG.h>
-#include <code_gen/codegen.h>
-#include <code_gen/CG_outputBuilder.h>
-#include <code_gen/codegen_error.h>
-
-namespace omega {
-
-const std::string CodeGen::loop_var_name_prefix = "t";
-const int CodeGen::var_substitution_threshold = 10;
-
-//Anand--adding stuff to make Chun's code work with Gabe's
-std::vector< std::vector<int> > smtNonSplitLevels;
-std::vector< std::vector<std::string> > loopIdxNames;//per stmt
-std::vector< std::pair<int, std::string> > syncs;
-
-
-
-CodeGen::CodeGen(const std::vector<Relation> &xforms, const std::vector<Relation> &IS, const Relation &known, std::vector< std::vector<int> > smtNonSplitLevels_ , std::vector< std::vector<std::string> > loopIdxNames_, std::vector< std::pair<int, std::string> > syncs_) {
- // check for sanity of parameters
- int num_stmt = IS.size();
- if (xforms.size() != num_stmt)
- throw std::invalid_argument("number of iteration spaces does not match number of transformations");
- known_ = copy(known);
- if (known_.n_out() != 0)
- throw std::invalid_argument("known condition must be a set relation");
- if (known_.is_null())
- known_ = Relation::True(0);
- else
- known_.simplify(2, 4);
- if (!known_.is_upper_bound_satisfiable())
- return;
- if (known_.number_of_conjuncts() > 1)
- throw std::invalid_argument("only one conjunct allowed in known condition");
- xforms_ = xforms;
- for (int i = 0; i < num_stmt; i++) {
- xforms_[i].simplify();
- if (!xforms_[i].has_single_conjunct())
- throw std::invalid_argument("mapping relation must have only one conjunct");
- if (xforms_[i].n_inp() != IS[i].n_inp() || IS[i].n_out() != 0)
- throw std::invalid_argument("illegal iteration space or transformation arity");
- }
-
-
- //protonu--
- //easier to handle this as a global
- smtNonSplitLevels = smtNonSplitLevels_;
- syncs = syncs_;
- loopIdxNames = loopIdxNames_;
- //end-protonu
-
-
-
- // find the maximum iteration space dimension we are going to operate on
- int num_level = known_.n_inp();
- for (int i = 0; i < num_stmt; i++)
- if (xforms_[i].n_out() > num_level)
- num_level = xforms_[i].n_out();
- known_ = Extend_Set(known_, num_level-known_.n_inp());
- for (int i = 1; i <= num_level; i++)
- known_.name_set_var(i, loop_var_name_prefix + to_string(i));
- known_.setup_names();
-
- // split disjoint conjunctions in original iteration spaces
- std::vector<Relation> new_IS;
- for (int i = 0; i < num_stmt; i++) {
- for (int j = 1; j <= IS[i].n_inp(); j++)
- xforms_[i].name_input_var(j, const_cast<std::vector<Relation> &>(IS)[i].input_var(j)->name());
- for (int j = 1; j <= xforms_[i].n_out(); j++)
- xforms_[i].name_output_var(j, loop_var_name_prefix + to_string(j));
- xforms_[i].setup_names();
-
- Relation R = Range(Restrict_Domain(copy(xforms_[i]), copy(IS[i])));
- R = Intersection(Extend_Set(R, num_level-R.n_inp()), copy(known_));
- R.simplify(2, 4);
- if (R.is_inexact())
- throw codegen_error("cannot generate code for inexact iteration spaces");
-
- while(R.is_upper_bound_satisfiable()) {
- DNF *dnf = R.query_DNF();
- DNF_Iterator c(dnf);
- Relation R2 = Relation(R, *c);
- R2.simplify();
- new_IS.push_back(copy(R2));
- remap_.push_back(i);
- c.next();
- if (!c.live())
- break;
- Relation remainder(R, *c);
- c.next();
- while (c.live()) {
- remainder = Union(remainder, Relation(R, *c));
- c.next();
- }
- R = Difference(remainder, R2);
- R.simplify(2, 4);
- }
- }
-
- // number of new statements after splitting
- num_stmt = new_IS.size();
- if(!smtNonSplitLevels.empty())
- smtNonSplitLevels.resize(num_stmt);
- // assign a dummy value to loops created for the purpose of expanding to maximum dimension
- for (int i = 0; i < num_stmt; i++) {
- if (xforms[remap_[i]].n_out() < num_level) {
- F_And *f_root = new_IS[i].and_with_and();
- for (int j = xforms[remap_[i]].n_out()+1; j <= num_level; j++) {
- EQ_Handle h = f_root->add_EQ();
- h.update_coef(new_IS[i].set_var(j), 1);
- h.update_const(posInfinity);
- }
- new_IS[i].simplify();
- }
- }
-
- // calculate projected subspaces for each loop level once and save for CG tree manipulation later
- projected_IS_ = std::vector<std::vector<Relation> >(num_level);
- for (int i = 0; i < num_level; i++)
- projected_IS_[i] = std::vector<Relation>(num_stmt);
- for (int i = 0; i < num_stmt; i++) {
- if (num_level > 0)
- projected_IS_[num_level-1][i] = new_IS[i];
- for (int j = num_level-1; j >= 1; j--) {
- projected_IS_[j-1][i] = Project(copy(projected_IS_[j][i]), j+1, Set_Var);
- projected_IS_[j-1][i].simplify(2, 4);
- }
- }
-}
-
-
-CG_result *CodeGen::buildAST(int level, const BoolSet<> &active, bool split_on_const, const Relation &restriction) {
- if (level > num_level())
- return new CG_leaf(this, active);
-
- int num_active_stmt = active.num_elem();
- if (num_active_stmt == 0)
- return NULL;
- else if (num_active_stmt == 1)
- return new CG_loop(this, active, level, buildAST(level+1, active, true, restriction));
-
- // use estimated constant bounds for fast non-overlap iteration space splitting
- if (split_on_const) {
- std::vector<std::pair<std::pair<coef_t, coef_t>, int> > bounds;
-
- for (BoolSet<>::const_iterator i = active.begin(); i != active.end(); i++) {
- Relation r = Intersection(copy(projected_IS_[level-1][*i]), copy(restriction));
- r.simplify(2, 4);
- if (!r.is_upper_bound_satisfiable())
- continue;
- coef_t lb, ub;
- r.single_conjunct()->query_variable_bounds(r.set_var(level),lb,ub);
- bounds.push_back(std::make_pair(std::make_pair(lb, ub), *i));
- }
- sort(bounds.begin(), bounds.end());
-
- std::vector<Relation> split_cond;
- std::vector<CG_result *> split_child;
-
- coef_t prev_val = -posInfinity;
- coef_t next_val = bounds[0].first.second;
- BoolSet<> next_active(active.size());
- int i = 0;
- while (i < bounds.size()) {
- if (bounds[i].first.first <= next_val) {
- next_active.set(bounds[i].second);
- next_val = max(next_val, bounds[i].first.second);
- i++;
- }
- else {
- Relation r(num_level());
- F_And *f_root = r.add_and();
- if (prev_val != -posInfinity) {
- GEQ_Handle h = f_root->add_GEQ();
- h.update_coef(r.set_var(level), 1);
- h.update_const(-prev_val-1);
- }
- if (next_val != posInfinity) {
- GEQ_Handle h = f_root->add_GEQ();
- h.update_coef(r.set_var(level), -1);
- h.update_const(next_val);
- }
- r.simplify();
-
- Relation new_restriction = Intersection(copy(r), copy(restriction));
- new_restriction.simplify(2, 4);
- CG_result *child = buildAST(level, next_active, false, new_restriction);
- if (child != NULL) {
- split_cond.push_back(copy(r));
- split_child.push_back(child);
- }
- next_active.unset_all();
- prev_val = next_val;
- next_val = bounds[i].first.second;
- }
- }
- if (!next_active.empty()) {
- Relation r = Relation::True(num_level());
- if (prev_val != -posInfinity) {
- F_And *f_root = r.and_with_and();
- GEQ_Handle h = f_root->add_GEQ();
- h.update_coef(r.set_var(level), 1);
- h.update_const(-prev_val-1);
- r.simplify();
- }
- Relation new_restriction = Intersection(copy(r), copy(restriction));
- new_restriction.simplify(2, 4);
- CG_result *child = buildAST(level, next_active, false, new_restriction);
- if (child != NULL) {
- split_cond.push_back(copy(r));
- split_child.push_back(child);
- }
- }
-
- if (split_child.size() == 0)
- return NULL;
- else if (split_child.size() == 1)
- return split_child[0];
- else
- return new CG_split(this, active, split_cond, split_child);
- }
- // check bound conditions exhaustively for non-overlap iteration space splitting
- else {
- std::vector<Relation> Rs(active.size());
- for (BoolSet<>::const_iterator i = active.begin(); i != active.end(); i++) {
- Rs[*i] = Intersection(Approximate(copy(projected_IS_[level-1][*i])), copy(restriction));
- Rs[*i].simplify(2, 4);
- }
- Relation hull = SimpleHull(Rs);
-
- //protonu-warn Chun about this change
- //This does some fancy splitting of statements into loops with the
- //fewest dimentions, but that's not necessarily what we want when
- //code-gening for CUDA. smtNonSplitLevels keeps track per-statment of
- //the levels that should not be split on.
- bool checkForSplits = true;
- for (BoolSet<>::const_iterator i = active.begin(); i != active.end(); i++) {
- if(*i < smtNonSplitLevels.size())
- for(int k = 0; k <smtNonSplitLevels[*i].size(); k++)
- if(smtNonSplitLevels[*i][k] == (level-2)){
- checkForSplits = false;
- break;
- }
- }
-
-
-
-
- for (BoolSet<>::const_iterator i = active.begin(); i != active.end() && checkForSplits; i++) {
- Relation r = Gist(copy(Rs[*i]), copy(hull), 1);
- if (r.is_obvious_tautology())
- continue;
- r = EQs_to_GEQs(r);
-
- for (GEQ_Iterator e = r.single_conjunct()->GEQs(); e; e++) {
- if ((*e).has_wildcards())
- continue;
-
- Relation cond = Relation::True(num_level());
- BoolSet<> first_chunk(active.size());
- BoolSet<> second_chunk(active.size());
-
- if ((*e).get_coef(hull.set_var(level)) > 0) {
- cond.and_with_GEQ(*e);
- cond = Complement(cond);;
- cond.simplify();
- second_chunk.set(*i);
- }
- else if ((*e).get_coef(hull.set_var(level)) < 0) {
- cond.and_with_GEQ(*e);
- cond.simplify();
- first_chunk.set(*i);
- }
- else
- continue;
-
- bool is_proper_split_cond = true;
- for (BoolSet<>::const_iterator j = active.begin(); j != active.end(); j++)
- if ( *j != *i) {
- bool in_first = Intersection(copy(Rs[*j]), copy(cond)).is_upper_bound_satisfiable();
- bool in_second = Difference(copy(Rs[*j]), copy(cond)).is_upper_bound_satisfiable();
-
- if (in_first && in_second) {
- is_proper_split_cond = false;
- break;
- }
-
- if (in_first)
- first_chunk.set(*j);
- else if (in_second)
- second_chunk.set(*j);
- }
-
- if (is_proper_split_cond && first_chunk.num_elem() != 0 && second_chunk.num_elem() != 0) {
- CG_result *first_cg = buildAST(level, first_chunk, false, copy(cond));
- CG_result *second_cg = buildAST(level, second_chunk, false, Complement(copy(cond)));
- if (first_cg == NULL)
- return second_cg;
- else if (second_cg == NULL)
- return first_cg;
- else {
- std::vector<Relation> split_cond;
- std::vector<CG_result *> split_child;
- split_cond.push_back(copy(cond));
- split_child.push_back(first_cg);
- split_cond.push_back(Complement(copy(cond)));
- split_child.push_back(second_cg);
-
- return new CG_split(this, active, split_cond, split_child);
- }
- }
- }
- }
- return new CG_loop(this, active, level, buildAST(level+1, active, true, restriction));
- }
-}
-
-
-CG_result *CodeGen::buildAST(int effort) {
- if (remap_.size() == 0)
- return NULL;
-
- CG_result *cgr = buildAST(1, ~BoolSet<>(remap_.size()), true, Relation::True(num_level()));
- if (cgr == NULL)
- return NULL;
-
-
- // break down the complete iteration space condition to levels of bound/guard condtions
- cgr = cgr->recompute(cgr->active_, copy(known_), copy(known_));
-
-
-
- if (cgr == NULL)
- return NULL;
-
- // calculate each loop's nesting depth
- int depth = cgr->populateDepth();
-
-
- // redistribute guard condition locations by additional splittings
- std::pair<CG_result *, Relation> result = cgr->liftOverhead(min(effort,depth), false);
-
- // since guard conditions are postponed for non-loop levels, hoist them now.
- // this enables proper if-condition simplication when outputting actual code.
- result.first->hoistGuard();
-
-
-
-
- return result.first;
-}
-
-}