diff options
Diffstat (limited to 'omegalib/code_gen/src/output_repr.cc')
-rw-r--r-- | omegalib/code_gen/src/output_repr.cc | 1931 |
1 files changed, 0 insertions, 1931 deletions
diff --git a/omegalib/code_gen/src/output_repr.cc b/omegalib/code_gen/src/output_repr.cc deleted file mode 100644 index 955cc14..0000000 --- a/omegalib/code_gen/src/output_repr.cc +++ /dev/null @@ -1,1931 +0,0 @@ -/***************************************************************************** - Copyright (C) 1994-2000 University of Maryland - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - utility functions for outputing CG_outputReprs - - Notes: - - History: - 07/30/10 collect various code outputing into one place, by Chun Chen -*****************************************************************************/ - -#include <omega.h> -#include <code_gen/CG_stringBuilder.h> -#include <code_gen/output_repr.h> -#include <basic/omega_error.h> -#include <math.h> -#include <stack> -#include <typeinfo> - -namespace omega { - -extern Tuple<Tuple<Relation> > projected_nIS; -int var_substitution_threshold = 100; -//protonu. -extern int upperBoundForLevel; -extern int lowerBoundForLevel; -extern bool fillInBounds; -//end--protonu. - -} - - -namespace omega { - -std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R_, Variable_ID v, const std::vector<CG_outputRepr *> &assigned_on_the_fly); - - -namespace { - - - - -void get_stride(const Constraint_Handle &h, Variable_ID &wc, coef_t &step){ - wc = 0; - for(Constr_Vars_Iter i(h,true); i; i++) { - assert(wc == 0); - wc = (*i).var; - step = ((*i).coef); - } -} - -} - -CG_outputRepr* outputIdent(CG_outputBuilder* ocg, const Relation &R_, Variable_ID v, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &R = const_cast<Relation &>(R_); - - switch (v->kind()) { - case Set_Var: { - int pos = v->get_position(); - if (assigned_on_the_fly[pos-1] != NULL) - return assigned_on_the_fly[pos-1]->clone(); - else - return ocg->CreateIdent(v->name()); - break; - } - case Global_Var: { - if (v->get_global_var()->arity() == 0) - return ocg->CreateIdent(v->name()); - else { - /* This should be improved to take into account the possible elimination - of the set variables. */ - int arity = v->get_global_var()->arity(); - //assert(arity <= last_level); - Tuple<CG_outputRepr *> argList; - // Relation R = Relation::True(arity); - - // name_codegen_vars(R); // easy way to make sure the names are correct. - for(int i = 1; i <= arity; i++) - argList.append(ocg->CreateIdent(R.set_var(i)->name())); - CG_outputRepr *call = ocg->CreateInvoke(v->get_global_var()->base_name(), argList); - return call; - } - break; - } - default: - throw std::invalid_argument("wrong variable type"); - } -} - - -//---------------------------------------------------------------------------- -// Translate equality constraints to if-condition and assignment. -// return.first is right-hand-side of assignment, return.second -// is true if assignment is required. -// -- by chun 07/29/2010 -// ---------------------------------------------------------------------------- -std::pair<CG_outputRepr *, bool> outputAssignment(CG_outputBuilder *ocg, const Relation &R_, Variable_ID v, Relation &enforced, CG_outputRepr *&if_repr, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &R = const_cast<Relation &>(R_); - - Conjunct *c = R.query_DNF()->single_conjunct(); - - // check whether to generate if-conditions from equality constraints - for (EQ_Iterator ei(c); ei; ei++) - if (!(*ei).has_wildcards() && abs((*ei).get_coef(v)) > 1) { - Relation r(R.n_set()); - F_And *f_super_root = r.add_and(); - F_Exists *fe = f_super_root->add_exists(); - Variable_ID e = fe->declare(); - F_And *f_root = fe->add_and(); - EQ_Handle h = f_root->add_EQ(); - for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - if ((*cvi).var == v) - h.update_coef(e, (*cvi).coef); - else - h.update_coef(r.set_var((*cvi).var->get_position()), (*cvi).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = r.get_local(g); - else - v2 = r.get_local(g, (*cvi).var->function_of()); - h.update_coef(v2, (*cvi).coef); - break; - } - default: - assert(0); - } - h.update_const((*ei).get_const()); - - r.copy_names(R); - r.setup_names(); - - // need if-condition to make sure this loop variable has integer value - if (!Gist(r, copy(enforced), 1).is_obvious_tautology()) { - coef_t coef = (*ei).get_coef(v); - coef_t sign = -((coef>0)?1:-1); - coef = abs(coef); - - CG_outputRepr *term = NULL; - for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) - if ((*cvi).var != v) { - CG_outputRepr *varRepr = outputIdent(ocg, R, (*cvi).var, assigned_on_the_fly); - coef_t t = sign*(*cvi).coef; - if (t == 1) - term = ocg->CreatePlus(term, varRepr); - else if (t == -1) - term = ocg->CreateMinus(term, varRepr); - else if (t > 0) - term = ocg->CreatePlus(term, ocg->CreateTimes(ocg->CreateInt(t), varRepr)); - else if (t < 0) - term = ocg->CreateMinus(term, ocg->CreateTimes(ocg->CreateInt(-t), varRepr)); - } - coef_t t = sign*(*ei).get_const(); - if (t > 0) - term = ocg->CreatePlus(term, ocg->CreateInt(t)); - else if (t < 0) - term = ocg->CreateMinus(term, ocg->CreateInt(-t)); - - term = ocg->CreateIntegerMod(term, ocg->CreateInt(coef)); - term = ocg->CreateEQ(term, ocg->CreateInt(0)); - - if_repr = ocg->CreateAnd(if_repr, term); - } - - enforced.and_with_EQ(*ei); - enforced.simplify(); - } - - // find the simplest assignment - std::pair<EQ_Handle, int> a = find_simplest_assignment(R, v, assigned_on_the_fly); - - // now generate assignment - if (a.second < INT_MAX) { - EQ_Handle eq = a.first; - CG_outputRepr *rop_repr = NULL; - - coef_t divider = eq.get_coef(v); - int sign = 1; - if (divider < 0) { - divider = -divider; - sign = -1; - } - - for (Constr_Vars_Iter cvi(eq); cvi; cvi++) - if ((*cvi).var != v) { - CG_outputRepr *var_repr = outputIdent(ocg, R, (*cvi).var, assigned_on_the_fly); - coef_t coef = (*cvi).coef; - if (-sign * coef == -1) - rop_repr = ocg->CreateMinus(rop_repr, var_repr); - else if (-sign * coef < -1) - rop_repr = ocg->CreateMinus(rop_repr, ocg->CreateTimes(ocg->CreateInt(sign * coef), var_repr)); - else if (-sign * coef == 1) - rop_repr = ocg->CreatePlus(rop_repr, var_repr); - else // -sign * coef > 1 - rop_repr = ocg->CreatePlus(rop_repr, ocg->CreateTimes(ocg->CreateInt(-sign * coef), var_repr)); - } - - coef_t c_term = -(eq.get_const() * sign); - - if (c_term > 0) - rop_repr = ocg->CreatePlus(rop_repr, ocg->CreateInt(c_term)); - else if (c_term < 0) - rop_repr = ocg->CreateMinus(rop_repr, ocg->CreateInt(-c_term)); - else if (rop_repr == NULL) - rop_repr = ocg->CreateInt(0); - - if (divider != 1) - rop_repr = ocg->CreateIntegerDivide(rop_repr, ocg->CreateInt(divider)); - - enforced.and_with_EQ(eq); - enforced.simplify(); - - if (a.second > var_substitution_threshold) - return std::make_pair(rop_repr, true); - else - return std::make_pair(rop_repr, false); - } - else - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); -} - - -//---------------------------------------------------------------------------- -// Don't use Substitutions class since it can't handle integer -// division. Instead, use relation mapping to a single output -// variable to get substitution. -- by chun, 07/19/2007 -//---------------------------------------------------------------------------- -Tuple<CG_outputRepr*> outputSubstitution(CG_outputBuilder* ocg, const Relation &R_, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &R = const_cast<Relation &>(R_); - - const int n = R.n_out(); - Tuple<CG_outputRepr*> oReprList; - - // Find substitution for each output variable - for (int i = 1; i <= n; i++) { - Relation mapping(n, 1); - F_And *f_root = mapping.add_and(); - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(1), 1); - h.update_coef(mapping.input_var(i), -1); - - Relation S = Composition(mapping, copy(R)); - - std::pair<EQ_Handle, int> a = find_simplest_assignment(S, S.output_var(1), assigned_on_the_fly); - - if (a.second < INT_MAX) { - while (a.second > 0) { - EQ_Handle eq = a.first; - std::set<int> candidates; - for (Constr_Vars_Iter cvi(eq); cvi; cvi++) - if ((*cvi).var->kind() == Input_Var) - candidates.insert((*cvi).var->get_position()); - - bool changed = false; - for (std::set<int>::iterator j = candidates.begin(); j != candidates.end(); j++) { - Relation S2 = Project(copy(S), *j, Input_Var); - std::pair<EQ_Handle, int> a2 = find_simplest_assignment(S2, S2.output_var(1), assigned_on_the_fly); - if (a2.second <= a.second) { - S = S2; - a = a2; - changed = true; - break; - } - } - if (!changed) - break; - } - } - - if (a.second < INT_MAX) { - CG_outputRepr *repr = NULL; - EQ_Handle eq = a.first; - Variable_ID v = S.output_var(1); - - for (int j = 1; j <= S.n_inp(); j++) - S.name_input_var(j, R.input_var(j)->name()); - S.setup_names(); - - int d = eq.get_coef(v); - assert(d != 0); - int sign = (d>0)?-1:1; - d = -sign * d; - for (Constr_Vars_Iter cvi(eq); cvi; cvi++) - if ((*cvi).var != v) { - int coef = sign * (*cvi).coef; - CG_outputRepr *op = outputIdent(ocg, S, (*cvi).var, assigned_on_the_fly); - if (coef > 1) - op = ocg->CreateTimes(ocg->CreateInt(coef), op); - else if (coef < -1) - op = ocg->CreateTimes(ocg->CreateInt(-coef), op); - if (coef > 0) - repr = ocg->CreatePlus(repr, op); - else if (coef < 0) - repr = ocg->CreateMinus(repr, op); - } - - int c = sign * eq.get_const(); - if (c > 0) - repr = ocg->CreatePlus(repr, ocg->CreateInt(c)); - else if (c < 0) - repr = ocg->CreateMinus(repr, ocg->CreateInt(-c)); - else if (repr == NULL) - repr = ocg->CreateInt(0); - - if (d != 1) - repr = ocg->CreateIntegerDivide(repr, ocg->CreateInt(d)); - - oReprList.append(repr); - } - else - oReprList.append(NULL); - } - - return oReprList; -} - -namespace { - -Relation create_stride_on_bound(int n, const std::map<Variable_ID, coef_t> &lb, coef_t stride) { - Relation result(n); - F_And *f_root = result.add_and(); - EQ_Handle h = f_root->add_stride(stride); - - for (std::map<Variable_ID, coef_t>::const_iterator i = lb.begin(); i != lb.end(); i++) { - if (i->first == NULL) - h.update_const(i->second); - else { - switch(i->first->kind()) { - case Input_Var: { - int pos = i->first->get_position(); - h.update_coef(result.set_var(pos), i->second); - break; - } - case Global_Var: { - Global_Var_ID g = i->first->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = result.get_local(g); - else - v = result.get_local(g, i->first->function_of()); - h.update_coef(v, i->second); - break; - } - default: - assert(0); - } - } - } - - return result; -} - -} - -//---------------------------------------------------------------------------- -// Find the most restrictive common stride constraint for a set of -// relations. -- by chun, 05/20/09 -// ---------------------------------------------------------------------------- -Relation greatest_common_step(const Tuple<Relation> &I, const Tuple<int> &active, int level, const Relation &known) { - assert(I.size() == active.size()); - int n = 0; - - std::vector<Relation> I1, I2; - for (int i = 1; i <= I.size(); i++) - if (active[i]) { - if (n == 0) - n = I[i].n_set(); - - Relation r1; - if (known.is_null()) - r1 = copy(I[i]); - else { - r1 = Intersection(copy(I[i]), copy(known)); - r1.simplify(); - } - I1.push_back(r1); - Relation r2 = Gist(copy(I[i]), copy(known)); - assert(r2.is_upper_bound_satisfiable()); - if (r2.is_obvious_tautology()) - return Relation::True(n); - I2.push_back(r2); - } - - std::vector<bool> is_exact(I2.size(), true); - std::vector<coef_t> step(I2.size(), 0); - std::vector<coef_t> messy_step(I2.size(), 0); - Variable_ID t_col = set_var(level); - std::map<Variable_ID, coef_t> lb; - - // first check all clean strides: t_col = ... (mod step) - for (size_t i = 0; i < I2.size(); i++) { - Conjunct *c = I2[i].query_DNF()->single_conjunct(); - - bool is_degenerated = false; - for (EQ_Iterator e = c->EQs(); e; e++) { - coef_t coef = abs((*e).get_coef(t_col)); - if (coef != 0 && !(*e).has_wildcards()) { - is_degenerated = true; - break; - } - } - if (is_degenerated) - continue; - - for (EQ_Iterator e = c->EQs(); e; e++) { - if ((*e).has_wildcards()) { - coef_t coef = abs((*e).get_coef(t_col)); - if (coef == 0) - continue; - if (coef != 1) { - is_exact[i] = false; - continue; - } - - coef_t this_step = abs(Constr_Vars_Iter(*e, true).curr_coef()); - assert(this_step != 1); - - if (lb.size() != 0) { - Relation test = create_stride_on_bound(n, lb, this_step); - if (Gist(test, copy(I1[i])).is_obvious_tautology()) { - if (step[i] == 0) - step[i] = this_step; - else - step[i] = lcm(step[i], this_step); - } - else - is_exact[i] = false; - } - else { - // try to find a lower bound that hits on stride - Conjunct *c = I2[i].query_DNF()->single_conjunct(); - for (GEQ_Iterator ge = c->GEQs(); ge; ge++) { - if ((*ge).has_wildcards() || (*ge).get_coef(t_col) != 1) - continue; - - std::map<Variable_ID, coef_t> cur_lb; - for (Constr_Vars_Iter cv(*ge); cv; cv++) - cur_lb[cv.curr_var()] = cv.curr_coef(); - cur_lb[NULL] = (*ge).get_const(); - - Relation test = create_stride_on_bound(n, cur_lb, this_step); - if (Gist(test, copy(I1[i])).is_obvious_tautology()) { - if (step[i] == 0) - step[i] = this_step; - else - step[i] = lcm(step[i], this_step); - - lb = cur_lb; - break; - } - } - - // no clean lower bound, thus we use this modular constraint as is - if (lb.size() == 0) { - std::map<Variable_ID, coef_t> cur_lb; - int wild_count = 0; - for (Constr_Vars_Iter cv(*e); cv; cv++) - if (cv.curr_var()->kind() == Wildcard_Var) - wild_count++; - else - cur_lb[cv.curr_var()] = cv.curr_coef(); - cur_lb[NULL] = (*e).get_const(); - - if (wild_count == 1) { - lb = cur_lb; - if (step[i] == 0) - step[i] = this_step; - else - step[i] = lcm(step[i], this_step); - } - } - - if (lb.size() == 0) - is_exact[i] = false; - } - } - } - } - - // aggregate all exact steps - coef_t global_step = 0; - for (size_t i = 0; i < is_exact.size(); i++) - if (is_exact[i]) - global_step = gcd(global_step, step[i]); - if (global_step == 1) - return Relation::True(n); - - // now check all messy strides: a*t_col = ... (mod step) - for (size_t i = 0; i < I2.size(); i++) - if (!is_exact[i]) { - Conjunct *c = I2[i].query_DNF()->single_conjunct(); - for (EQ_Iterator e = c->EQs(); e; e++) { - coef_t coef = abs((*e).get_coef(t_col)); - if (coef == 0 || coef == 1) - continue; - - // make a guess for messy stride condition -- by chun 07/27/2007 - coef_t this_step = abs(Constr_Vars_Iter(*e, true).curr_coef()); - this_step /= gcd(this_step, coef); - this_step = gcd(global_step, this_step); - if (this_step == 1) - continue; - - if (lb.size() != 0) { - Relation test = create_stride_on_bound(n, lb, this_step); - if (Gist(test, copy(I1[i])).is_obvious_tautology()) { - if (step[i] == 0) - step[i] = this_step; - else - step[i] = lcm(step[i], this_step); - } - } - else { - // try to find a lower bound that hits on stride - Conjunct *c = I2[i].query_DNF()->single_conjunct(); - for (GEQ_Iterator ge = c->GEQs(); ge; ge++) { - if ((*ge).has_wildcards() || (*ge).get_coef(t_col) != 1) - continue; - - std::map<Variable_ID, coef_t> cur_lb; - - for (Constr_Vars_Iter cv(*ge); cv; cv++) - cur_lb[cv.curr_var()] = cv.curr_coef(); - - cur_lb[NULL] = (*ge).get_const(); - - Relation test = create_stride_on_bound(n, cur_lb, this_step); - if (Gist(test, copy(I1[i])).is_obvious_tautology()) { - if (step[i] == 0) - step[i] = this_step; - else - step[i] = lcm(step[i], this_step); - - lb = cur_lb; - break; - } - } - } - } - } - - // aggregate all non-exact steps - for (size_t i = 0; i < is_exact.size(); i++) - if (!is_exact[i]) - global_step = gcd(global_step, step[i]); - if (global_step == 1 || global_step == 0) - return Relation::True(n); - - Relation result = create_stride_on_bound(n, lb, global_step); - - // check for statements that haven't been factored into global step - for (size_t i = 0; i < I1.size(); i++) - if (step[i] == 0) { - if (!Gist(copy(result), copy(I1[i])).is_obvious_tautology()) - return Relation::True(n); - } - - return result; -} - - -//----------------------------------------------------------------------------- -// Substitute variables in a statement according to mapping function. -//----------------------------------------------------------------------------- -CG_outputRepr* outputStatement(CG_outputBuilder *ocg, CG_outputRepr *stmt, int indent, const Relation &mapping_, const Relation &known_, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation mapping = copy(mapping_); - Relation known = copy(known_); - Tuple<std::string> loop_vars; - - for (int i = 1; i <= mapping.n_inp(); i++) - loop_vars.append(mapping.input_var(i)->name()); - - // discard non-existant variables from iteration spaces -- by chun 12/31/2008 - if (known.n_set() > mapping.n_out()) { - Relation r(known.n_set(), mapping.n_out()); - F_And *f_root = r.add_and(); - for (int i = 1; i <= mapping.n_out(); i++) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(r.input_var(i), 1); - h.update_coef(r.output_var(i), -1); - } - known = Range(Restrict_Domain(r, known)); - known.simplify(); - } - - // remove modular constraints from known to simplify mapping process -- by chun 11/10/2008 - Relation k(known.n_set()); - F_And *f_root = k.add_and(); - Conjunct *c = known.query_DNF()->single_conjunct(); - for (EQ_Iterator e = c->EQs(); e; e++) { - if (!(*e).has_wildcards()) - f_root->add_EQ(*e); - } - k.simplify(); - - // get variable substituion list - Relation Inv_mapping = Restrict_Domain(Inverse(mapping), k); - Tuple<CG_outputRepr*> sList = outputSubstitution(ocg, Inv_mapping, assigned_on_the_fly); - - return ocg->CreatePlaceHolder(indent, stmt, sList, loop_vars); -} - - -// find floor definition for variable such as m-3 <= 4v <= m -bool findFloorInequality(Relation &r, Variable_ID v, GEQ_Handle &h, Variable_ID excluded) { - Conjunct *c = r.single_conjunct(); - - std::set<Variable_ID> var_checked; - std::stack<Variable_ID> var_checking; - var_checking.push(v); - - while (!var_checking.empty()) { - Variable_ID v2 = var_checking.top(); - var_checking.pop(); - - bool is_floor = false; - for (GEQ_Iterator gi(c); gi; gi++) { - if (excluded != NULL && (*gi).get_coef(excluded) != 0) - continue; - - coef_t a = (*gi).get_coef(v2); - if (a < 0) { - for (GEQ_Iterator gi2(c); gi2; gi2++) { - coef_t b = (*gi2).get_coef(v2); - if (b == -a && (*gi).get_const()+(*gi2).get_const() < -a) { - bool match = true; - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - if ((*gi2).get_coef((*cvi).var) != -(*cvi).coef) { - match = false; - break; - } - if (!match) - continue; - for (Constr_Vars_Iter cvi(*gi2); cvi; cvi++) - if ((*gi).get_coef((*cvi).var) != -(*cvi).coef) { - match = false; - break; - } - if (match) { - var_checked.insert(v2); - is_floor = true; - if (v == v2) - h = *gi; - - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - if (((*cvi).var->kind() == Exists_Var || (*cvi).var->kind() == Wildcard_Var) && - var_checked.find((*cvi).var) == var_checked.end()) - var_checking.push((*cvi).var); - - break; - } - } - } - if (is_floor) - break; - } - } - if (!is_floor) - return false; - } - return true; -} - - - - -//----------------------------------------------------------------------------- -// Output a reqular equality or inequality to conditions. -// e.g. (i=5*j) -//----------------------------------------------------------------------------- -CG_outputRepr* output_as_guard(CG_outputBuilder* ocg, const Relation &guards_in, Constraint_Handle e, bool is_equality, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &guards = const_cast<Relation &>(guards_in); - if (e.has_wildcards()) - throw std::invalid_argument("constraint must not have wildcard"); - - Variable_ID v = (*Constr_Vars_Iter(e)).var; - - coef_t saved_coef = ((e).get_coef(v)); - int sign = saved_coef < 0 ? -1 : 1; - - (e).update_coef_during_simplify(v, -saved_coef+sign); - CG_outputRepr* rop = outputEasyBoundAsRepr(ocg, guards, e, v, false, 0, assigned_on_the_fly); - (e).update_coef_during_simplify(v,saved_coef-sign); - - CG_outputRepr* lop = outputIdent(ocg, guards, v, assigned_on_the_fly); - if (abs(saved_coef) != 1) - lop = ocg->CreateTimes(ocg->CreateInt(abs(saved_coef)), lop); - - - if (is_equality) { - return ocg->CreateEQ(lop, rop); - } - else { - if (saved_coef < 0) - return ocg->CreateLE(lop, rop); - else - return ocg->CreateGE(lop, rop); - } -} - - -//----------------------------------------------------------------------------- -// Output stride conditions from equalities. -// e.g. (exists alpha: i = 5*alpha) -//----------------------------------------------------------------------------- -CG_outputRepr *output_EQ_strides(CG_outputBuilder* ocg, const Relation &guards_in, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation guards = const_cast<Relation &>(guards_in); - Conjunct *c = guards.single_conjunct(); - - CG_outputRepr *eqRepr = NULL; - - for (EQ_Iterator ei(c->EQs()); ei; ei++) { - Variable_ID wc = NULL; - for (Constr_Vars_Iter cvi((*ei), true); cvi; cvi++) { - if (wc != NULL) - throw codegen_error("Can't generate equality condition with multiple wildcards"); - else - wc = (*cvi).var; - } - if (wc == NULL) - continue; - - coef_t step = (*ei).get_coef(wc); - - (*ei).update_coef_during_simplify(wc, 1-step); - CG_outputRepr* lop = outputEasyBoundAsRepr(ocg, guards, (*ei), wc, false, 0, assigned_on_the_fly); - (*ei).update_coef_during_simplify(wc, step-1); - - CG_outputRepr* rop = ocg->CreateInt(abs(step)); - CG_outputRepr* intMod = ocg->CreateIntegerMod(lop, rop); - CG_outputRepr* eqNode = ocg->CreateEQ(intMod, ocg->CreateInt(0)); - - eqRepr = ocg->CreateAnd(eqRepr, eqNode); - } - - return eqRepr; -} - - - -//----------------------------------------------------------------------------- -// Output hole conditions created by inequalities involving wildcards. -// e.g. (exists alpha: 4*alpha <= i <= 5*alpha) -// Collect wildcards -// For each whildcard -// collect lower and upper bounds in which wildcard appears -// For each lower bound -// create constraint with each upper bound -//----------------------------------------------------------------------------- -CG_outputRepr *output_GEQ_strides(CG_outputBuilder* ocg, const Relation &guards_in, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation guards = const_cast<Relation &>(guards_in); - Conjunct *c = guards.single_conjunct(); - - CG_outputRepr* geqRepr = NULL; - - std::set<Variable_ID> non_orphan_wildcard; - for (GEQ_Iterator gi(c); gi; gi++) { - int num_wild = 0; - Variable_ID first_one; - for (Constr_Vars_Iter cvi(*gi, true); cvi; cvi++) { - num_wild++; - if (num_wild == 1) - first_one = (*cvi).var; - else - non_orphan_wildcard.insert((*cvi).var); - } - if (num_wild > 1) - non_orphan_wildcard.insert(first_one); - } - - for (int i = 1; i <= (*(c->variables())).size(); i++) { - Variable_ID wc = (*(c->variables()))[i]; - if (wc->kind() == Wildcard_Var && non_orphan_wildcard.find(wc) == non_orphan_wildcard.end()) { - Tuple<GEQ_Handle> lower, upper; - for (GEQ_Iterator gi(c); gi; gi++) { - if((*gi).get_coef(wc) > 0) - lower.append(*gi); - else if((*gi).get_coef(wc) < 0) - upper.append(*gi); - } - - // low: c*alpha - x >= 0 - // up: -d*alpha + y >= 0 - for (Tuple_Iterator<GEQ_Handle> low(lower); low; low++) { - for (Tuple_Iterator<GEQ_Handle> up(upper); up; up++) { - coef_t low_coef = (*low).get_coef(wc); - coef_t up_coef = (*up).get_coef(wc); - - (*low).update_coef_during_simplify(wc, 1-low_coef); - CG_outputRepr* lowExpr = outputEasyBoundAsRepr(ocg, guards, *low, wc, false, 0, assigned_on_the_fly); - (*low).update_coef_during_simplify(wc, low_coef-1); - - (*up).update_coef_during_simplify(wc, -1-up_coef); - CG_outputRepr* upExpr = outputEasyBoundAsRepr(ocg, guards, *up, wc, false, 0, assigned_on_the_fly); - (*up).update_coef_during_simplify(wc, up_coef+1); - - CG_outputRepr* intDiv = ocg->CreateIntegerDivide(upExpr, ocg->CreateInt(-up_coef)); - CG_outputRepr* rop = ocg->CreateTimes(ocg->CreateInt(low_coef), intDiv); - CG_outputRepr* geqNode = ocg->CreateLE(lowExpr, rop); - - geqRepr = ocg->CreateAnd(geqRepr, geqNode); - } - } - } - } - - if (non_orphan_wildcard.size() > 0) { - // e.g. c*alpha - x >= 0 (*) - // -d*alpha + y >= 0 (*) - // e1*alpha + f1*beta + g1 >= 0 (**) - // e2*alpha + f2*beta + g2 >= 0 (**) - // ... - // TODO: should generate a testing loop for alpha using its lower and - // upper bounds from (*) constraints and do the same if-condition test - // for beta from each pair of opposite (**) constraints as above, - // and exit the loop when if-condition satisfied. - throw codegen_error("Can't generate multiple wildcard GEQ guards right now"); - } - - return geqRepr; -} - - -//----------------------------------------------------------------------------- -// Translate all constraints in a relation to guard conditions. -//----------------------------------------------------------------------------- -CG_outputRepr *outputGuard(CG_outputBuilder* ocg, const Relation &guards_in, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &guards = const_cast<Relation &>(guards_in); - if (guards.is_null() || guards.is_obvious_tautology()) - return NULL; - - CG_outputRepr* nodeRepr = NULL; - - CG_outputRepr *eqStrideRepr = output_EQ_strides(ocg, guards, assigned_on_the_fly); - nodeRepr = ocg->CreateAnd(nodeRepr, eqStrideRepr); - - CG_outputRepr *geqStrideRepr = output_GEQ_strides(ocg, guards, assigned_on_the_fly); - nodeRepr = ocg->CreateAnd(nodeRepr, geqStrideRepr); - - Conjunct *c = guards.single_conjunct(); - for(EQ_Iterator ei(c->EQs()); ei; ei++) - if (!(*ei).has_wildcards()) { - CG_outputRepr *eqRepr = output_as_guard(ocg, guards, (*ei), true, assigned_on_the_fly); - nodeRepr = ocg->CreateAnd(nodeRepr, eqRepr); - } - for(GEQ_Iterator gi(c->GEQs()); gi; gi++) - if (!(*gi).has_wildcards()) { - CG_outputRepr *geqRepr = output_as_guard(ocg, guards, (*gi), false, assigned_on_the_fly); - nodeRepr = ocg->CreateAnd(nodeRepr, geqRepr); - } - - return nodeRepr; -} - - -//----------------------------------------------------------------------------- -// one is 1 for LB -// this function is overloaded should replace the original one -//----------------------------------------------------------------------------- -CG_outputRepr *outputLBasRepr(CG_outputBuilder* ocg, const GEQ_Handle &g, - Relation &bounds, Variable_ID v, - coef_t stride, const EQ_Handle &strideEQ, - Relation known, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { -#if ! defined NDEBUG - coef_t v_coef; - assert((v_coef = g.get_coef(v)) > 0); -#endif - - std::string s; - CG_outputRepr *lbRepr; - if (stride == 1) { - lbRepr = outputEasyBoundAsRepr(ocg, bounds, g, v, false, 1, assigned_on_the_fly); - } - else { - if (!boundHitsStride(g,v,strideEQ,stride,known)) { - bounds.setup_names(); // boundsHitsStride resets variable names - - CG_stringBuilder oscg; - std::string c = GetString(outputEasyBoundAsRepr(&oscg, bounds, strideEQ, v, true, 0, assigned_on_the_fly)); - CG_outputRepr *cRepr = NULL; - if (c != std::string("0")) - cRepr = outputEasyBoundAsRepr(ocg, bounds, strideEQ, v, true, 0, assigned_on_the_fly); - std::string LoverM = GetString(outputEasyBoundAsRepr(&oscg, bounds, g, v, false, 1, assigned_on_the_fly)); - CG_outputRepr *LoverMRepr = NULL; - if (LoverM != std::string("0")) - LoverMRepr = outputEasyBoundAsRepr(ocg, bounds, g, v, false, 1, assigned_on_the_fly); - - if (code_gen_debug > 2) { - fprintf(DebugFile,"::: LoverM is %s\n", LoverM.c_str()); - fprintf(DebugFile,"::: c is %s\n", c.c_str()); - } - - int complexity1 = 0, complexity2 = 0; - for (size_t i = 0; i < c.length(); i++) - if (c[i] == '+' || c[i] == '-' || c[i] == '*' || c[i] == '/') - complexity1++; - else if (c[i] == ',') - complexity1 += 2; - for (size_t i = 0; i < LoverM.length(); i++) - if (LoverM[i] == '+' || LoverM[i] == '-' || LoverM[i] == '*' || LoverM[i] == '/') - complexity2++; - else if (LoverM[i] == ',') - complexity2 += 2; - - if (complexity1 < complexity2) { - CG_outputRepr *idUp = LoverMRepr; - CG_outputRepr *c1Repr = ocg->CreateCopy(cRepr); - idUp = ocg->CreateMinus(idUp, c1Repr); - idUp = ocg->CreatePlus(idUp, ocg->CreateInt(stride-1)); - CG_outputRepr *idLow = ocg->CreateInt(stride); - lbRepr = ocg->CreateTimes(ocg->CreateInt(stride), - ocg->CreateIntegerDivide(idUp, idLow)); - lbRepr = ocg->CreatePlus(lbRepr, cRepr); - } - else { - CG_outputRepr *LoverM1Repr = ocg->CreateCopy(LoverMRepr); - CG_outputRepr *imUp = ocg->CreateMinus(cRepr, LoverM1Repr); - CG_outputRepr *imLow = ocg->CreateInt(stride); - CG_outputRepr *intMod = ocg->CreateIntegerMod(imUp, imLow); - lbRepr = ocg->CreatePlus(LoverMRepr, intMod); - } - } - else { - // boundsHitsStride resets variable names - bounds.setup_names(); - lbRepr = outputEasyBoundAsRepr(ocg, bounds, g, v, false, 0, assigned_on_the_fly); - } - } - - return lbRepr; -} - -//----------------------------------------------------------------------------- -// one is -1 for UB -// this function is overloaded should replace the original one -//----------------------------------------------------------------------------- -CG_outputRepr *outputUBasRepr(CG_outputBuilder* ocg, const GEQ_Handle &g, - Relation & bounds, - Variable_ID v, - coef_t /*stride*/, // currently unused - const EQ_Handle &/*strideEQ*/, //currently unused - const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - assert(g.get_coef(v) < 0); - CG_outputRepr* upRepr = outputEasyBoundAsRepr(ocg, bounds, g, v, false, 0, assigned_on_the_fly); - return upRepr; -} - -//----------------------------------------------------------------------------- -// Print the expression for the variable given as v. Works for both -// GEQ's and EQ's, but produces intDiv (not intMod) when v has a nonunit -// coefficient. So it is OK for loop bounds, but for checking stride -// constraints, you want to make sure the coef of v is 1, and insert the -// intMod yourself. -// -// original name is outputEasyBound -//----------------------------------------------------------------------------- -CG_outputRepr* outputEasyBoundAsRepr(CG_outputBuilder* ocg, Relation &bounds, - const Constraint_Handle &g, Variable_ID v, - bool ignoreWC, - int ceiling, - const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - // assert ignoreWC => g is EQ - // rewrite constraint as foo (== or <= or >=) v, return foo as string - - CG_outputRepr* easyBoundRepr = NULL; - - coef_t v_coef = g.get_coef(v); - int v_sign = v_coef > 0 ? 1 : -1; - v_coef *= v_sign; - assert(v_coef > 0); - // foo is (-constraint)/v_sign/v_coef - - int sign_adj = -v_sign; - - //---------------------------------------------------------------------- - // the following generates +- cf*varName - //---------------------------------------------------------------------- - for(Constr_Vars_Iter c2(g, false); c2; c2++) { - if ((*c2).var != v && (!ignoreWC || (*c2).var->kind()!=Wildcard_Var)) { - - coef_t cf = (*c2).coef*sign_adj; - assert(cf != 0); - - CG_outputRepr *varName; - if ((*c2).var->kind() == Wildcard_Var) { - GEQ_Handle h; - if (!findFloorInequality(bounds, (*c2).var, h, v)) { - if (easyBoundRepr != NULL) { - easyBoundRepr->clear(); - delete easyBoundRepr; - } - return NULL; - } - varName = outputEasyBoundAsRepr(ocg, bounds, h, (*c2).var, false, 0, assigned_on_the_fly); - } - else { - varName = outputIdent(ocg, bounds, (*c2).var, assigned_on_the_fly); - } - CG_outputRepr *cfRepr = NULL; - - if (cf > 1) { - cfRepr = ocg->CreateInt(cf); - CG_outputRepr* rbRepr = ocg->CreateTimes(cfRepr, varName); - easyBoundRepr = ocg->CreatePlus(easyBoundRepr, rbRepr); - } - else if (cf < -1) { - cfRepr = ocg->CreateInt(-cf); - CG_outputRepr* rbRepr = ocg->CreateTimes(cfRepr, varName); - easyBoundRepr = ocg->CreateMinus(easyBoundRepr, rbRepr); - } - else if (cf == 1) { - easyBoundRepr = ocg->CreatePlus(easyBoundRepr, varName); - } - else if (cf == -1) { - easyBoundRepr = ocg->CreateMinus(easyBoundRepr, varName); - } - } - } - - if (g.get_const()) { - coef_t cf = g.get_const()*sign_adj; - assert(cf != 0); - if (cf > 0) { - easyBoundRepr = ocg->CreatePlus(easyBoundRepr, ocg->CreateInt(cf)); - } - else { - easyBoundRepr = ocg->CreateMinus(easyBoundRepr, ocg->CreateInt(-cf)); - } - } - else { - if(easyBoundRepr == NULL) { - easyBoundRepr = ocg->CreateInt(0); - } - } - - if (v_coef > 1) { - assert(ceiling >= 0); - if (ceiling) { - easyBoundRepr= ocg->CreatePlus(easyBoundRepr, ocg->CreateInt(v_coef-1)); - } - easyBoundRepr = ocg->CreateIntegerDivide(easyBoundRepr, ocg->CreateInt(v_coef)); - } - - return easyBoundRepr; -} - - -//---------------------------------------------------------------------------- -// Translate inequality constraints to loop or assignment. -// if return.second is true, return.first is loop structure, -// otherwise it is assignment. -// ---------------------------------------------------------------------------- -std::pair<CG_outputRepr *, bool> outputBounds(CG_outputBuilder* ocg, const Relation &bounds, Variable_ID v, int indent, Relation &enforced, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation b = copy(bounds); - Conjunct *c = b.query_DNF()->single_conjunct(); - - // Elaborate stride simplification which is complementary to gist function - // since we further target the specific loop variable. -- by chun 08/07/2008 - Relation r1 = Relation::True(b.n_set()), r2 = Relation::True(b.n_set()); - for (EQ_Iterator ei(c); ei; ei++) { - if ((*ei).get_coef(v) != 0 && (*ei).has_wildcards()) { // stride condition found - coef_t sign; - if ((*ei).get_coef(v) > 0) - sign = 1; - else - sign = -1; - - coef_t stride = 0; - for (Constr_Vars_Iter cvi(*ei, true); cvi; cvi++) - if ((*cvi).var->kind() == Wildcard_Var) { - stride = abs((*cvi).coef); - break; - } - - // check if stride hits lower bound - bool found_match = false; - if (abs((*ei).get_coef(v)) != 1) { // expensive matching for non-clean stride condition - coef_t d = stride / gcd(abs((*ei).get_coef(v)), stride); - Relation r3 = Relation::True(b.n_set()); - r3.and_with_EQ(*ei); - - for (GEQ_Iterator gi(c); gi; gi++) { - if ((*gi).get_coef(v) == 1 && !(*gi).has_wildcards()) { - Relation r4(b.n_set()); - F_And *f_root = r4.add_and(); - Stride_Handle h = f_root->add_stride(d); - - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - int pos = (*cvi).var->get_position(); - h.update_coef(r4.set_var(pos), (*cvi).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r4.get_local(g); - else - v = r4.get_local(g, (*cvi).var->function_of()); - h.update_coef(v, (*cvi).coef); - break; - } - default: - fprintf(DebugFile, "can't deal with the variable type in lower bound\n"); - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); - } - h.update_const((*gi).get_const()); - - Relation r5 = Gist(copy(r3), Intersection(copy(r4), copy(enforced))); - - // replace original stride condition with striding from this lower bound - if (r5.is_obvious_tautology()) { - r1 = Intersection(r1, r4); - found_match = true; - break; - } - } - } - } - else { - for (GEQ_Iterator gi(c); gi; gi++) { - if ((*gi).get_coef(v) == abs((*ei).get_coef(v)) && !(*gi).has_wildcards()) { // potential matching lower bound found - Relation r(b.n_set()); - Stride_Handle h = r.add_and()->add_stride(stride); - - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - int pos = (*cvi).var->get_position(); - if ((*cvi).var != v) { - int t1 = int_mod((*cvi).coef, stride); - if (t1 != 0) { - coef_t t2 = enforced.query_variable_mod(enforced.set_var(pos), stride); - if (t2 != posInfinity) - h.update_const(t1*t2); - else - h.update_coef(r.set_var(pos), t1); - } - } - else - h.update_coef(r.set_var(pos), (*cvi).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = enforced.get_local(g); - else - v = enforced.get_local(g, (*cvi).var->function_of()); - coef_t t = enforced.query_variable_mod(v, stride); - if (t != posInfinity) - h.update_const(t*(*cvi).coef); - else { - Variable_ID v2; - if (g->arity() == 0) - v2 = r.get_local(g); - else - v2 = r.get_local(g, (*cvi).var->function_of()); - h.update_coef(v2, (*cvi).coef); - } - break; - } - default: - fprintf(DebugFile, "can't deal with the variable type in lower bound\n"); - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); - } - h.update_const((*gi).get_const()); - - bool t = true; - { - Conjunct *c2 = r.query_DNF()->single_conjunct(); - EQ_Handle h2; - for (EQ_Iterator ei2(c2); ei2; ei2++) { - h2 = *ei2; - break; - } - - int sign; - if (h2.get_coef(v) == (*ei).get_coef(v)) - sign = 1; - else - sign = -1; - - t = int_mod(h2.get_const() - sign * (*ei).get_const(), stride) == 0; - - if (t != false) - for (Constr_Vars_Iter cvi(h2); cvi; cvi++) - if ((*cvi).var->kind() != Wildcard_Var && - int_mod((*cvi).coef - sign * (*ei).get_coef((*cvi).var), stride) != 0) { - t = false; - break; - } - - if (t != false) - for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) - if ((*cvi).var->kind() != Wildcard_Var && - int_mod((*cvi).coef - sign * h2.get_coef((*cvi).var), stride) != 0) { - t = false; - break; - } - - } - - if (t) { - // replace original stride condition with striding from this lower bound - F_And *f_root = r1.and_with_and(); - Stride_Handle h = f_root->add_stride(stride); - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - h.update_coef(r1.set_var((*cvi).var->get_position()), (*cvi).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r1.get_local(g); - else - v = r1.get_local(g, (*cvi).var->function_of()); - h.update_coef(v, (*cvi).coef); - break; - } - default: - fprintf(DebugFile, "can't deal with the variable type in lower bound\n"); - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); - } - h.update_const((*gi).get_const()); - - found_match = true; - break; - } - } - } - } - - if (!found_match) - r1.and_with_EQ(*ei); - } - else if ((*ei).get_coef(v) == 0) { - Relation r3 = Relation::True(b.n_set()); - r3.and_with_EQ(*ei); - Relation r4 = Gist(r3, copy(enforced)); - if (!r4.is_obvious_tautology()) - r2.and_with_EQ(*ei); - } - else - r2.and_with_EQ(*ei); - } - - // restore remaining inequalities - { - std::map<Variable_ID, Variable_ID> exists_mapping; - F_Exists *fe = r2.and_with_and()->add_exists(); - F_And *f_root = fe->add_and(); - for (GEQ_Iterator gi(c); gi; gi++) { - GEQ_Handle h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: { - int pos = v->get_position(); - h.update_coef(r2.set_var(pos), cvi.curr_coef()); - break; - } - case Exists_Var: - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(v); - Variable_ID e; - if (p == exists_mapping.end()) { - e = fe->declare(); - exists_mapping[v] = e; - } - else - e = (*p).second; - h.update_coef(e, cvi.curr_coef()); - break; - } - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = r2.get_local(g); - else - v2 = r2.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(0); - } - } - h.update_const((*gi).get_const()); - } - } - - // overwrite original bounds - { - r1.simplify(); - r2.simplify(); - Relation b2 = Intersection(r1, r2); - b2.simplify(); - for (int i = 1; i <= b.n_set(); i++) - b2.name_set_var(i, b.set_var(i)->name()); - b2.setup_names(); - b = b2; - c = b.query_DNF()->single_conjunct(); - } - - - // get loop strides - EQ_Handle strideEQ; - bool foundStride = false; // stride that can be translated to loop - bool foundSimpleStride = false; // stride that starts from const value - coef_t step = 1; - int num_stride = 0; - - for (EQ_Iterator ei(c); ei; ei++) { - if ((*ei).get_coef(v) != 0 && (*ei).has_wildcards()) { - num_stride++; - - if (abs((*ei).get_coef(v)) != 1) - continue; - - bool t = true; - coef_t d = 1; - for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) - if ((*cvi).var->kind() == Wildcard_Var) { - assert(d==1); - d = abs((*cvi).coef); - } - else if ((*cvi).var->kind() == Input_Var) { - if ((*cvi).var != v) - t = false; - } - else - t = false; - - if (d > step) { - step = d; - foundSimpleStride = t; - strideEQ = *ei; - foundStride = true; - } - } - } - - // More than one stride or complex stride found, we should move all - // but strideEQ to body's guard condition. alas, not implemented. - if (!(num_stride == 0 || (num_stride == 1 && foundStride))) - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); - - // get loop bounds - int lower_bounds = 0, upper_bounds = 0; - Tuple<CG_outputRepr *> lbList; - Tuple<CG_outputRepr *> ubList; - coef_t const_lb = negInfinity, const_ub = posInfinity; - for (GEQ_Iterator g(c); g; g++) { - coef_t coef = (*g).get_coef(v); - if (coef == 0) - continue; - else if (coef > 0) { // lower bound - lower_bounds++; - if ((*g).is_const(v) && !foundStride) { - //no variables but v in constr - coef_t L,m; - L = -((*g).get_const()); - - m = (*g).get_coef(v); - coef_t sb = (int) (ceil(((float) L) /m)); - set_max(const_lb, sb); - } - else if ((*g).is_const(v) && foundSimpleStride) { - // no variables but v in constr - //make LB fit the stride constraint - coef_t L,m,s,c; - L = -((*g).get_const()); - m = (*g).get_coef(v); - s = step; - c = strideEQ.get_const(); - coef_t sb = (s * (int) (ceil( (float) (L - (c * m)) /(s*m))))+ c; - set_max(const_lb, sb); - } - else - lbList.append(outputLBasRepr(ocg, *g, b, v, step, strideEQ, enforced, assigned_on_the_fly)); - } - else { // upper bound - upper_bounds++; - if ((*g).is_const(v)) { - // no variables but v in constraint - set_min(const_ub,-(*g).get_const()/(*g).get_coef(v)); - } - else - ubList.append(outputUBasRepr(ocg, *g, b, v, step, strideEQ, assigned_on_the_fly)); - } - } - - CG_outputRepr *lbRepr = NULL; - CG_outputRepr *ubRepr = NULL; - if (const_lb != negInfinity) - lbList.append(ocg->CreateInt(const_lb)); - if (lbList.size() > 1) - lbRepr = ocg->CreateInvoke("max", lbList); - else if (lbList.size() == 1) - lbRepr = lbList[1]; - - //protonu - if(fillInBounds && lbList.size() == 1 && const_lb != negInfinity) - lowerBoundForLevel = const_lb; - //end-protonu - - if (const_ub != posInfinity) - ubList.append(ocg->CreateInt(const_ub)); - if (ubList.size() > 1) - ubRepr = ocg->CreateInvoke("min", ubList); - else if (ubList.size() == 1) - ubRepr = ubList[1]; - - //protonu - if(fillInBounds && const_ub != posInfinity) - upperBoundForLevel = const_ub; - //end-protonu - - if (upper_bounds == 0 || lower_bounds == 0) { - return std::make_pair(static_cast<CG_outputRepr *>(NULL), false); - } - else { - // bookkeeping catched constraints in new_knwon - F_Exists *fe = enforced.and_with_and()->add_exists(); - F_And *f_root = fe->add_and(); - std::map<Variable_ID, Variable_ID> exists_mapping; - std::stack<std::pair<GEQ_Handle, Variable_ID> > floor_geq_stack; - std::set<Variable_ID> floor_var_set; - - if (foundStride) { - EQ_Handle h = f_root->add_EQ(); - for (Constr_Vars_Iter cvi(strideEQ); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - int pos = (*cvi).var->get_position(); - h.update_coef(enforced.set_var(pos), (*cvi).coef); - break; - } - case Exists_Var: - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find((*cvi).var); - Variable_ID e; - if (p == exists_mapping.end()) { - e = fe->declare(); - exists_mapping[(*cvi).var] = e; - } - else - e = (*p).second; - h.update_coef(e, (*cvi).coef); - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID e; - if (g->arity() == 0) - e = enforced.get_local(g); - else - e = enforced.get_local(g, (*cvi).var->function_of()); - h.update_coef(e, (*cvi).coef); - break; - } - default: - assert(0); - } - h.update_const(strideEQ.get_const()); - } - - for (GEQ_Iterator gi(c); gi; gi++) - if ((*gi).get_coef(v) != 0) { - GEQ_Handle h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) - switch ((*cvi).var->kind()) { - case Input_Var: { - int pos = (*cvi).var->get_position(); - h.update_coef(enforced.set_var(pos), (*cvi).coef); - break; - } - case Exists_Var: - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find((*cvi).var); - Variable_ID e; - if (p == exists_mapping.end()) { - e = fe->declare(); - exists_mapping[(*cvi).var] = e; - } - else - e = (*p).second; - h.update_coef(e, (*cvi).coef); - - if (floor_var_set.find((*cvi).var) == floor_var_set.end()) { - GEQ_Handle h2; - findFloorInequality(b, (*cvi).var, h2, v); - floor_geq_stack.push(std::make_pair(h2, (*cvi).var)); - floor_var_set.insert((*cvi).var); - } - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID e; - if (g->arity() == 0) - e = enforced.get_local(g); - else - e = enforced.get_local(g, (*cvi).var->function_of()); - h.update_coef(e, (*cvi).coef); - break; - } - default: - assert(0); - } - h.update_const((*gi).get_const()); - } - - // add floor definition involving variables appeared in bounds - while (!floor_geq_stack.empty()) { - std::pair<GEQ_Handle, Variable_ID> p = floor_geq_stack.top(); - floor_geq_stack.pop(); - - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(p.first); cvi; cvi++) { - switch ((*cvi).var->kind()) { - case Input_Var: { - int pos = (*cvi).var->get_position(); - h1.update_coef(enforced.input_var(pos), (*cvi).coef); - h2.update_coef(enforced.input_var(pos), -(*cvi).coef); - break; - } - case Exists_Var: - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p2 = exists_mapping.find((*cvi).var); - Variable_ID e; - if (p2 == exists_mapping.end()) { - e = fe->declare(); - exists_mapping[(*cvi).var] = e; - } - else - e = (*p2).second; - h1.update_coef(e, (*cvi).coef); - h2.update_coef(e, -(*cvi).coef); - - if (floor_var_set.find((*cvi).var) == floor_var_set.end()) { - GEQ_Handle h3; - findFloorInequality(b, (*cvi).var, h3, v); - floor_geq_stack.push(std::make_pair(h3, (*cvi).var)); - floor_var_set.insert((*cvi).var); - } - break; - } - case Global_Var: { - Global_Var_ID g = (*cvi).var->get_global_var(); - Variable_ID e; - if (g->arity() == 0) - e = enforced.get_local(g); - else - e = enforced.get_local(g, (*cvi).var->function_of()); - h1.update_coef(e, (*cvi).coef); - h2.update_coef(e, -(*cvi).coef); - break; - } - default: - assert(0); - } - } - h1.update_const(p.first.get_const()); - h2.update_const(-p.first.get_const()); - h2.update_const(-p.first.get_coef(p.second)-1); - } - enforced.simplify(); - - CG_outputRepr *stRepr = NULL; - if (step != 1) - stRepr = ocg->CreateInt(abs(step)); - CG_outputRepr *indexRepr = outputIdent(ocg, b, v, assigned_on_the_fly); - CG_outputRepr *ctrlRepr = ocg->CreateInductive(indexRepr, lbRepr, ubRepr, stRepr); - - return std::make_pair(ctrlRepr, true); - } -} - - -Relation project_onto_levels(Relation R, int last_level, bool wildcards) { - assert(last_level >= 0 && R.is_set() && last_level <= R.n_set()); - if (last_level == R.n_set()) return R; - - int orig_vars = R.n_set(); - int num_projected = orig_vars - last_level; - R = Extend_Set(R,num_projected - ); // Project out vars numbered > last_level - Mapping m1 = Mapping::Identity(R.n_set()); // now orig_vars+num_proj - - for(int i=last_level+1; i <= orig_vars; i++) { - m1.set_map(Set_Var, i, Exists_Var, i); - m1.set_map(Set_Var, i+num_projected, Set_Var, i); - } - - MapRel1(R, m1, Comb_Id); - R.finalize(); - R.simplify(); - if (!wildcards) - R = Approximate(R,1); - assert(R.is_set()); - return R; -} - - -// Check if the lower bound already enforces the stride by -// (Where m is coef of v in g and L is the bound on m*v): -// Check if m divides L evenly and Check if this l.bound on v implies strideEQ -bool boundHitsStride(const GEQ_Handle &g, Variable_ID v, - const EQ_Handle &strideEQ, - coef_t /*stride*/, // currently unused - Relation known) { -/* m = coef of v in g; - L = bound on v part of g; -*/ - // Check if m divides L evenly - coef_t m = g.get_coef(v); - Relation test(known.n_set()); - F_Exists *e = test.add_exists(); // g is "L >= mv" - Variable_ID alpha = e->declare(); // want: "l = m alpha" - F_And *a = e->add_and(); - EQ_Handle h = a->add_EQ(); - for(Constr_Vars_Iter I(g,false); I; I++) - if((*I).var != v) { - if((*I).var->kind() != Global_Var) - h.update_coef((*I).var, (*I).coef); - else - h.update_coef(test.get_local((*I).var->get_global_var()), (*I).coef); - } - - h.update_const(g.get_const()); - h.update_coef(alpha,m); // set alpha's coef to m - if (!(Gist(test,copy(known)).is_obvious_tautology())) - return false; - // Check if this lower bound on v implies the strideEQ - Relation boundRel = known; // want: "known and l = m v" - boundRel.and_with_EQ(g); // add in l = mv - Relation strideRel(known.n_set()); - strideRel.and_with_EQ(strideEQ); - return Gist(strideRel, boundRel).is_obvious_tautology(); -} - - -// // Return true if there are no variables in g except wildcards & v -bool isSimpleStride(const EQ_Handle &g, Variable_ID v) { - EQ_Handle gg = g; // should not be necessary, but iterators are - // a bit brain-dammaged - bool is_simple=true; - for(Constr_Vars_Iter cvi(gg, false); cvi && is_simple; cvi++) - is_simple = ((*cvi).coef == 0 || (*cvi).var == v - || (*cvi).var->kind() == Wildcard_Var); - return is_simple; -} - - -int countStrides(Conjunct *c, Variable_ID v, EQ_Handle &strideEQ, - bool &simple) { - int strides=0; - for(EQ_Iterator G(c); G; G++) - for(Constr_Vars_Iter I(*G, true); I; I++) - if (((*I).coef != 0) && (*G).get_coef(v) != 0) { - strides++; - simple = isSimpleStride(*G,v); - strideEQ = *G; - break; - } - return strides; -} - -namespace { - -bool hasEQ(Relation r, int level) { - r.simplify(); - Variable_ID v = set_var(level); - Conjunct *s_conj = r.single_conjunct(); - for(EQ_Iterator G(s_conj); G; G++) - if ((*G).get_coef(v)) - return true; - return false; -} - - - -static Relation pickEQ(Relation r, int level) { - r.simplify(); - Variable_ID v = set_var(level); - Conjunct *s_conj = r.single_conjunct(); - for(EQ_Iterator E(s_conj); E; E++) - if ((*E).get_coef(v)) { - Relation test_rel(r.n_set()); - test_rel.and_with_EQ(*E); - return test_rel; - } - assert(0); - return r; -} - -/* pickBound will return an EQ as a GEQ if it finds one */ -Relation pickBound(Relation r, int level, int UB) { - r.simplify(); - Variable_ID v = set_var(level); - Conjunct *s_conj = r.single_conjunct(); - for(GEQ_Iterator G(s_conj); G; G++) { - if ((UB && (*G).get_coef(v) < 0) - || (!UB && (*G).get_coef(v) > 0) ) { - Relation test_rel(r.n_set()); - test_rel.and_with_GEQ(*G); - return test_rel; - } - } - for(EQ_Iterator E(s_conj); E; E++) { - if ((*E).get_coef(v)) { - Relation test_rel(r.n_set()); - test_rel.and_with_GEQ(*E); - if ((UB && (*E).get_coef(v) > 0) - || (!UB && (*E).get_coef(v) < 0) ) - test_rel = Complement(test_rel); - return test_rel; - } - } - assert(0); - return r; -} - -} - -Relation pickOverhead(Relation r, int liftTo) { - r.simplify(); - Conjunct *s_conj = r.single_conjunct(); - for(GEQ_Iterator G(s_conj); G; G++) { - Relation test_rel(r.n_set()); - test_rel.and_with_GEQ(*G); - Variable_ID v; - coef_t pos = -1; - coef_t c= 0; - for(Constr_Vars_Iter cvi(*G, false); cvi; cvi++) - if ((*cvi).coef && (*cvi).var->kind() == Input_Var - && (*cvi).var->get_position() > pos) { - v = (*cvi).var; - pos = (*cvi).var->get_position(); - c = (*cvi).coef; - } -#if 0 - fprintf(DebugFile,"Coef = %d, constraint = %s\n", - c,(const char *)test_rel.print_formula_to_string()); -#endif - return test_rel; - } - for(EQ_Iterator E(s_conj); E; E++) { - assert(liftTo >= 1); - int pos = max((*E).max_tuple_pos(),max_fs_arity(*E)+1); - -/* Pick stride constraints only when the variables with stride are outer - loop variables */ - if ((*E).has_wildcards() && pos < liftTo) { - Relation test_rel(r.n_set()); - test_rel.and_with_EQ(*E); - return test_rel; - } - else if (!(*E).has_wildcards() && pos <= liftTo) { - Relation test_rel(r.n_set()); - test_rel.and_with_EQ(*E); - test_rel.simplify(); - test_rel = EQs_to_GEQs(test_rel,true); - return pickOverhead(test_rel,liftTo); - } - } - if (code_gen_debug>1) { - fprintf(DebugFile,"Could not find overhead:\n"); - r.prefix_print(DebugFile); - } - return Relation::True(r.n_set()); -} - - - -bool hasBound(Relation r, int level, int UB) { - r.simplify(); - Variable_ID v = set_var(level); - Conjunct *s_conj = r.single_conjunct(); - for(GEQ_Iterator G(s_conj); G; G++) { - if (UB && (*G).get_coef(v) < 0) return true; - if (!UB && (*G).get_coef(v) > 0) return true; - } - for(EQ_Iterator E(s_conj); E; E++) { - if ((*E).get_coef(v)) return true; - } - return false; -} - -bool find_any_constraint(int s, int level, Relation &kr, int direction, - Relation &S, bool approx) { - /* If we don't intersect I with restrictions, the combination - of S and restrictions can be unsatisfiable, which means that - the new split node gets pruned away and we still don't have - finite bounds -> infinite recursion. */ - - Relation I = projected_nIS[level][s]; - I = Gist(I,copy(kr)); - if(approx) I = Approximate(I); - if (hasBound(I,level,direction)) { - Relation pickfrom; - if(has_nonstride_EQ(I,level)) - pickfrom = pickEQ(I,level); - else - pickfrom = pickBound(I,level,direction); - S = pickOverhead(pickfrom,level); - if(S.is_obvious_tautology()) S = Relation::Null(); - return !S.is_null(); - } - return false; -} - - -bool has_nonstride_EQ(Relation r, int level) { - r.simplify(); - Variable_ID v = set_var(level); - Conjunct *s_conj = r.single_conjunct(); - for(EQ_Iterator G(s_conj); G; G++) - if ((*G).get_coef(v) && !(*G).has_wildcards()) - return true; - return false; -} - - -Relation minMaxOverhead(Relation r, int level) { - r.finalize(); - r.simplify(); - Conjunct *s_conj = r.single_conjunct(); - GEQ_Handle LBs[50],UBs[50]; - int numLBs = 0; - int numUBs = 0; - Variable_ID v = set_var(level); - for(GEQ_Iterator G(s_conj); G; G++) if ((*G).get_coef(v)) { - GEQ_Handle g = *G; - if (g.get_coef(v) > 0) LBs[numLBs++] = g; - else UBs[numUBs++] = g; - } - if (numLBs <= 1 && numUBs <= 1) { - return Relation::True(r.n_set()); - } - Relation r1(r.n_set()); - Relation r2(r.n_set()); - if (numLBs > 1) { - // remove a max in lower bound - r1.and_with_GEQ(LBs[0]); - r2.and_with_GEQ(LBs[1]); - r1 = project_onto_levels(Difference(r1,r2),level-1,0); - } - else { - // remove a min in upper bound - r1.and_with_GEQ(UBs[0]); - r2.and_with_GEQ(UBs[1]); - r1 = project_onto_levels(Difference(r1,r2),level-1,0); - } -#if 0 - fprintf(DebugFile,"Testing %s\n",(const char *)r1.print_formula_to_string()); - fprintf(DebugFile,"will removed overhead on bounds of t%d: %s\n",level, - (const char *)r.print_formula_to_string()); -#endif - - return pickOverhead(r1, -1); -} - -std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R_, Variable_ID v, const std::vector<CG_outputRepr *> &assigned_on_the_fly) { - Relation &R = const_cast<Relation &>(R_); - Conjunct *c = R.single_conjunct(); - - int min_cost = INT_MAX; - EQ_Handle eq; - for (EQ_Iterator ei(c->EQs()); ei; ei++) - if (!(*ei).has_wildcards() && (*ei).get_coef(v) != 0) { - int cost = 0; - - if (abs((*ei).get_coef(v)) != 1) - cost += 4; // divide cost - - int num_var = 0; - for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) - if ((*cvi).var != v) { - num_var++; - if ((*cvi).var->kind() == Global_Var && (*cvi).var->get_global_var()->arity() > 0) { - cost += 10; // function cost - } - if (abs((*cvi).coef) != 1) - cost += 2; // multiply cost - if ((*cvi).var->kind() == Input_Var && assigned_on_the_fly[(*cvi).var->get_position()-1] != NULL) { - cost += 5; // substituted variable cost - } - } - if ((*ei).get_const() != 0) - num_var++; - if (num_var > 1) - cost += num_var - 1; // addition cost - - if (cost < min_cost) { - min_cost = cost; - eq = *ei; - } - } - - return std::make_pair(eq, min_cost); -} - -int max_fs_arity(const Constraint_Handle &c) { - int max_arity=0; - for(Constr_Vars_Iter cv(c); cv; cv++) - if((*cv).var->kind() == Global_Var) - max_arity = max(max_arity,(*cv).var->get_global_var()->arity()); - return max_arity; -} - -} |