this repo has no description
at develop 6.6 kB view raw
1#include <minizinc/codegen.hh> 2 3#include <../lib/codegen/analysis.hpp> 4 5namespace MiniZinc { 6 7/// Visit identifier 8void ModeAnalysis::vId(Id& x, Occurrence o, CG::Mode m) { 9 // Use sites follow 10 VarDecl* decl(x.decl()); 11 if (o == Use && decl) update(decl, o, m); 12} 13/// Visit array literal 14void ModeAnalysis::vArrayLit(ArrayLit& a, Occurrence o, CG::Mode m) { 15 // If the array contents are Boolean, this doesn't count as an occurrence; 16 // we care about the context of the access. 17 // But for anything else, the partiality emerges at the occurrence site. 18 int sz(a.size()); 19 for (int ii = 0; ii < sz; ++ii) { 20 Expression* elt(a[ii]); 21 if (o == Use || elt->type().bt() != Type::BT_BOOL) { 22 update(elt, o, m); 23 } 24 } 25} 26/// Visit array access 27void ModeAnalysis::vArrayAccess(ArrayAccess& a, Occurrence o, CG::Mode m) { 28 ASTExprVec<Expression> idx(a.idx()); 29 for (int ii = 0; ii < idx.size(); ++ii) update(idx[ii], o, m); 30 if (a.type().bt() == Type::BT_BOOL) 31 update(a.v(), o, +m); 32 else 33 update(a.v(), o, m); 34} 35/// Visit array comprehension 36void ModeAnalysis::vComprehension(Comprehension& comp, Occurrence o, CG::Mode m) { 37 // Comprehension behaves like an array access: 38 // The current mode propagates to the generators, but only to non-Boolean bodies. 39 if (o == Def) { 40 int g_n(comp.n_generators()); 41 for (int gg = 0; gg < g_n; ++gg) { 42 int d_n(comp.n_decls(gg)); 43 for (int d = 0; d < d_n; ++d) update(comp.decl(gg, d), o, m); 44 update(comp.in(gg), o, m); 45 if (comp.where(gg)) { 46 update(comp.where(gg), Use, BytecodeProc::FUN); 47 } 48 } 49 } 50 if (o == Use || comp.e()->type().bt() != Type::BT_BOOL) { 51 int g_n(comp.n_generators()); 52 for (int gg = 0; gg < comp.n_generators(); ++gg) { 53 if (comp.where(gg)) { 54 update(comp.where(gg), Use, BytecodeProc::FUN); 55 } 56 } 57 update(comp.e(), o, m); 58 } 59} 60/// Visit if-then-else 61void ModeAnalysis::vITE(ITE& ite, Occurrence o, CG::Mode m) { 62 int sz(ite.size()); 63 for (int ii = 0; ii < sz; ++ii) { 64 // We need the condition to compute the value. 65 update(ite.e_if(ii), Use, BytecodeProc::FUN); 66 update(ite.e_then(ii), o, m); 67 } 68 update(ite.e_else(), o, m); 69} 70 71/// Visit binary operator 72void ModeAnalysis::vBinOp(BinOp& b, Occurrence o, CG::Mode m) { 73 switch (b.op()) { 74 case BOT_IMPL: { 75 CG::Mode m_c = m.is_neg() ? m : +m; 76 update(b.lhs(), o, -m_c); 77 update(b.rhs(), o, m_c); 78 break; 79 } 80 case BOT_RIMPL: { 81 CG::Mode m_c = m.is_neg() ? m : +m; 82 update(b.lhs(), o, m_c); 83 update(b.rhs(), o, -m_c); 84 break; 85 } 86 case BOT_OR: { 87 CG::Mode m_c = m.is_neg() ? m : +m; 88 update(b.lhs(), o, m_c); 89 update(b.rhs(), o, m_c); 90 break; 91 } 92 case BOT_AND: { 93 CG::Mode m_c = m.is_neg() ? +m : m; 94 update(b.lhs(), o, m_c); 95 update(b.rhs(), o, m_c); 96 break; 97 } 98 case BOT_EQ: 99 case BOT_NQ: { 100 CG::Mode m_l = b.lhs()->type().bt() == Type::BT_BOOL ? CG::Mode(BytecodeProc::FUN) : +m; 101 CG::Mode m_r = b.rhs()->type().bt() == Type::BT_BOOL ? CG::Mode(BytecodeProc::FUN) : +m; 102 update(b.lhs(), o, m_l); 103 update(b.rhs(), o, m_r); 104 } 105 case BOT_EQUIV: 106 case BOT_XOR: 107 update(b.lhs(), o, BytecodeProc::FUN); 108 update(b.rhs(), o, BytecodeProc::FUN); 109 break; 110 default: 111 update(b.lhs(), o, m); 112 update(b.rhs(), o, m); 113 } 114} 115/// Visit unary operator 116void ModeAnalysis::vUnOp(UnOp& u, Occurrence o, CG::Mode m) { 117 switch (u.op()) { 118 case UOT_NOT: 119 update(u.e(), o, -m); 120 break; 121 default: 122 update(u.e(), o, m); 123 } 124} 125 126/// Visit call 127// TODO: Add special cases for builtin calls, and interprocedural analysis 128// so we can get more precise mode analysis. 129void ModeAnalysis::vCall(Call& call, Occurrence o, CG::Mode m) { 130 int sz(call.n_args()); 131 if (call.id() == constants().ids.forall) { 132 assert(sz == 1); 133 CG::Mode m_r(m.is_neg() ? +m : m); 134 update(call.arg(0), o, m_r); 135 } else if (call.id() == constants().ids.exists) { 136 assert(sz == 1); 137 CG::Mode m_r(m.is_neg() ? m : +m); 138 update(call.arg(0), o, m_r); 139 } else if (call.id() == constants().ids.clause) { 140 assert(sz == 2); 141 CG::Mode m_r(m.is_neg() ? m : +m); 142 update(call.arg(0), o, m_r); 143 update(call.arg(1), o, -m_r); 144 } else if (call.id() == constants().ids.assert) { 145 update(call.arg(0), Use, BytecodeProc::ROOT); 146 if (sz == 3) update(call.arg(2), o, m); 147 } else if (call.id() == "array1d") { 148 // No-op 149 update(call.arg(sz - 1), o, m); 150 } else if (call.id() == "index_set" || call.id() == "length") { 151 if (o == Def) update(call.arg(0), Def, m); 152 } else if (call.id() == "symmetry_breaking_constraint" || call.id() == "redundant_constraint") { 153 // No-op 154 update(call.arg(0), o, m); 155 } else { 156 // Propagate to the other functions. 157 for (int ii = 0; ii < sz; ++ii) { 158 Expression* arg(call.arg(ii)); 159 // If arg is non-Boolean, this the partiality gets embedded here. 160 // But if arg is Boolean, we have to assume the callee can do 161 // anything with it, so the occurrence is considered FUN. 162 if (arg->type().bt() == Type::BT_BOOL) { 163 update(arg, Use, BytecodeProc::FUN); 164 } else { 165 update(arg, o, m); 166 } 167 } 168 } 169} 170/// Visit let 171void ModeAnalysis::vLet(Let& let, Occurrence o, CG::Mode m) { 172 ASTExprVec<Expression> bindings(let.let()); 173 if (o == Def || let.type().bt() == Type::BT_BOOL) { 174 // If the let has Boolean type, the _use_ of the let defines 175 // the def-mode of the bound variables. 176 for (Expression* e : bindings) { 177 // Check whether this is a decl with a def. 178 if (auto vd = e->dyn_cast<VarDecl>()) { 179 if (vd->type().bt() != Type::BT_BOOL) update(vd, Def, m); 180 /* 181 if(Expression* v_e = vd->e()) { 182 if(!v_e->type().isbool()) { 183 update(v_e, Def, m); 184 } 185 } 186 */ 187 } else { 188 // Must be a constraint, so it's a use. 189 assert(e->type().isbool()); 190 update(e, Use, m); 191 } 192 } 193 update(let.in(), o, m); 194 } else { 195 // Non-Boolean use; the partiality is in an enclosing 196 // context. 197 update(let.in(), o, m); 198 } 199} 200/// Visit variable declaration 201void ModeAnalysis::vVarDecl(VarDecl& decl, Occurrence o, CG::Mode m) { 202 if (Id* x = decl.id()) update(x, o, m); 203 if (Expression* d = decl.ti()->domain()) { 204 if (o == Def) { 205 update(d, Def, m); 206 update(d, Use, m); 207 } 208 } 209 if (Expression* e = decl.e()) update(e, o, m); 210} 211 212void ModeAnalysis::vFunctionI(FunctionI& fun, Occurrence o, CG::Mode m) { 213 // DO STUFF 214} 215}; // namespace MiniZinc