Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
6.6 kB · 215 lines
C++
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216#include <minizinc/codegen.hh>
#include <../lib/codegen/analysis.hpp>
namespace MiniZinc {
/// Visit identifiervoid ModeAnalysis::vId(Id& x, Occurrence o, CG::Mode m) { // Use sites follow VarDecl* decl(x.decl()); if (o == Use && decl) update(decl, o, m);}/// Visit array literalvoid ModeAnalysis::vArrayLit(ArrayLit& a, Occurrence o, CG::Mode m) { // If the array contents are Boolean, this doesn't count as an occurrence; // we care about the context of the access. // But for anything else, the partiality emerges at the occurrence site. int sz(a.size()); for (int ii = 0; ii < sz; ++ii) { Expression* elt(a[ii]); if (o == Use || elt->type().bt() != Type::BT_BOOL) { update(elt, o, m); } }}/// Visit array accessvoid ModeAnalysis::vArrayAccess(ArrayAccess& a, Occurrence o, CG::Mode m) { ASTExprVec<Expression> idx(a.idx()); for (int ii = 0; ii < idx.size(); ++ii) update(idx[ii], o, m); if (a.type().bt() == Type::BT_BOOL) update(a.v(), o, +m); else update(a.v(), o, m);}/// Visit array comprehensionvoid ModeAnalysis::vComprehension(Comprehension& comp, Occurrence o, CG::Mode m) { // Comprehension behaves like an array access: // The current mode propagates to the generators, but only to non-Boolean bodies. if (o == Def) { int g_n(comp.n_generators()); for (int gg = 0; gg < g_n; ++gg) { int d_n(comp.n_decls(gg)); for (int d = 0; d < d_n; ++d) update(comp.decl(gg, d), o, m); update(comp.in(gg), o, m); if (comp.where(gg)) { update(comp.where(gg), Use, BytecodeProc::FUN); } } } if (o == Use || comp.e()->type().bt() != Type::BT_BOOL) { int g_n(comp.n_generators()); for (int gg = 0; gg < comp.n_generators(); ++gg) { if (comp.where(gg)) { update(comp.where(gg), Use, BytecodeProc::FUN); } } update(comp.e(), o, m); }}/// Visit if-then-elsevoid ModeAnalysis::vITE(ITE& ite, Occurrence o, CG::Mode m) { int sz(ite.size()); for (int ii = 0; ii < sz; ++ii) { // We need the condition to compute the value. update(ite.e_if(ii), Use, BytecodeProc::FUN); update(ite.e_then(ii), o, m); } update(ite.e_else(), o, m);}
/// Visit binary operatorvoid ModeAnalysis::vBinOp(BinOp& b, Occurrence o, CG::Mode m) { switch (b.op()) { case BOT_IMPL: { CG::Mode m_c = m.is_neg() ? m : +m; update(b.lhs(), o, -m_c); update(b.rhs(), o, m_c); break; } case BOT_RIMPL: { CG::Mode m_c = m.is_neg() ? m : +m; update(b.lhs(), o, m_c); update(b.rhs(), o, -m_c); break; } case BOT_OR: { CG::Mode m_c = m.is_neg() ? m : +m; update(b.lhs(), o, m_c); update(b.rhs(), o, m_c); break; } case BOT_AND: { CG::Mode m_c = m.is_neg() ? +m : m; update(b.lhs(), o, m_c); update(b.rhs(), o, m_c); break; } case BOT_EQ: case BOT_NQ: { CG::Mode m_l = b.lhs()->type().bt() == Type::BT_BOOL ? CG::Mode(BytecodeProc::FUN) : +m; CG::Mode m_r = b.rhs()->type().bt() == Type::BT_BOOL ? CG::Mode(BytecodeProc::FUN) : +m; update(b.lhs(), o, m_l); update(b.rhs(), o, m_r); } case BOT_EQUIV: case BOT_XOR: update(b.lhs(), o, BytecodeProc::FUN); update(b.rhs(), o, BytecodeProc::FUN); break; default: update(b.lhs(), o, m); update(b.rhs(), o, m); }}/// Visit unary operatorvoid ModeAnalysis::vUnOp(UnOp& u, Occurrence o, CG::Mode m) { switch (u.op()) { case UOT_NOT: update(u.e(), o, -m); break; default: update(u.e(), o, m); }}
/// Visit call// TODO: Add special cases for builtin calls, and interprocedural analysis// so we can get more precise mode analysis.void ModeAnalysis::vCall(Call& call, Occurrence o, CG::Mode m) { int sz(call.n_args()); if (call.id() == constants().ids.forall) { assert(sz == 1); CG::Mode m_r(m.is_neg() ? +m : m); update(call.arg(0), o, m_r); } else if (call.id() == constants().ids.exists) { assert(sz == 1); CG::Mode m_r(m.is_neg() ? m : +m); update(call.arg(0), o, m_r); } else if (call.id() == constants().ids.clause) { assert(sz == 2); CG::Mode m_r(m.is_neg() ? m : +m); update(call.arg(0), o, m_r); update(call.arg(1), o, -m_r); } else if (call.id() == constants().ids.assert) { update(call.arg(0), Use, BytecodeProc::ROOT); if (sz == 3) update(call.arg(2), o, m); } else if (call.id() == "array1d") { // No-op update(call.arg(sz - 1), o, m); } else if (call.id() == "index_set" || call.id() == "length") { if (o == Def) update(call.arg(0), Def, m); } else if (call.id() == "symmetry_breaking_constraint" || call.id() == "redundant_constraint") { // No-op update(call.arg(0), o, m); } else { // Propagate to the other functions. for (int ii = 0; ii < sz; ++ii) { Expression* arg(call.arg(ii)); // If arg is non-Boolean, this the partiality gets embedded here. // But if arg is Boolean, we have to assume the callee can do // anything with it, so the occurrence is considered FUN. if (arg->type().bt() == Type::BT_BOOL) { update(arg, Use, BytecodeProc::FUN); } else { update(arg, o, m); } } }}/// Visit letvoid ModeAnalysis::vLet(Let& let, Occurrence o, CG::Mode m) { ASTExprVec<Expression> bindings(let.let()); if (o == Def || let.type().bt() == Type::BT_BOOL) { // If the let has Boolean type, the _use_ of the let defines // the def-mode of the bound variables. for (Expression* e : bindings) { // Check whether this is a decl with a def. if (auto vd = e->dyn_cast<VarDecl>()) { if (vd->type().bt() != Type::BT_BOOL) update(vd, Def, m); /* if(Expression* v_e = vd->e()) { if(!v_e->type().isbool()) { update(v_e, Def, m); } } */ } else { // Must be a constraint, so it's a use. assert(e->type().isbool()); update(e, Use, m); } } update(let.in(), o, m); } else { // Non-Boolean use; the partiality is in an enclosing // context. update(let.in(), o, m); }}/// Visit variable declarationvoid ModeAnalysis::vVarDecl(VarDecl& decl, Occurrence o, CG::Mode m) { if (Id* x = decl.id()) update(x, o, m); if (Expression* d = decl.ti()->domain()) { if (o == Def) { update(d, Def, m); update(d, Use, m); } } if (Expression* e = decl.e()) update(e, o, m);}
void ModeAnalysis::vFunctionI(FunctionI& fun, Occurrence o, CG::Mode m) { // DO STUFF}}; // namespace MiniZinc