void visit_lt(Expr a, Expr b) { a.accept(this); Monotonic ra = result; b.accept(this); Monotonic rb = result; result = unify(flip(ra), rb); }
void visit_eq(Expr a, Expr b) { a.accept(this); Monotonic ra = result; b.accept(this); Monotonic rb = result; if (ra == Monotonic::Constant && rb == Monotonic::Constant) { result = Monotonic::Constant; } else { result = Monotonic::Unknown; } }
Expr product(Expr e) { Internal::FindFreeVars v; e.accept(&v); Func f("product"); f(v.free_vars) *= e; return f(v.free_vars); }
Expr sum(Expr e) { Internal::FindFreeVars v; e.accept(&v); Func f("sum"); f(v.free_vars) += e; return f(v.free_vars); }
void Function::define(const vector<string> &args, Expr value) { assert(value.defined() && "Undefined expression in right-hand-side of function definition\n"); // Make sure all the vars in the value are either args or are // attached to some parameter CheckVars check; check.pure_args = args; value.accept(&check); assert(!check.reduction_domain.defined() && "Reduction domain referenced in pure function definition"); if (!contents.defined()) { contents = new FunctionContents; contents.ptr->name = unique_name('f'); } assert(!contents.ptr->value.defined() && "Function is already defined"); contents.ptr->value = value; contents.ptr->args = args; for (size_t i = 0; i < args.size(); i++) { Schedule::Dim d = {args[i], For::Serial}; contents.ptr->schedule.dims.push_back(d); } }
std::unique_ptr<Expr> InstantiationVisitor::clone(Expr& e) { std::unique_ptr<Expr> result; e.accept(*this); swap(result, _expr); return std::move(result); }
void visit_conditional(Expr condition, T true_case, T false_case) { Expr old_predicate = predicate; predicate = const_false(); true_case.accept(this); Expr true_predicate = predicate; predicate = const_false(); if (false_case.defined()) false_case.accept(this); Expr false_predicate = predicate; bool old_varies = varies; predicate = const_false(); varies = false; condition.accept(this); if (is_one(predicate) || is_one(old_predicate)) { predicate = const_true(); } else if (varies) { if (is_one(true_predicate) || is_one(false_predicate)) { predicate = const_true(); } else { predicate = (old_predicate || predicate || true_predicate || false_predicate); } } else { predicate = (old_predicate || predicate || (condition && true_predicate) || ((!condition) && false_predicate)); } varies = varies || old_varies; }
int main() { string input; while(true) { cout << "Evaluate >> "; getline(cin, input); if(input == "exit") break; else { Parser * p = new Parser(input); SExpr se; Expr * root = p->E(); // Evaluates S-Expr with visitor root->accept(se); cout << endl; delete p; } } return 0; }
Expr minimum(Expr e) { Internal::FindFreeVars v; e.accept(&v); Func f("minimum"); f(v.free_vars) = e.type().max(); f(v.free_vars) = min(f(v.free_vars), e); return f(v.free_vars); }
Expr IRMutator::mutate(const Expr &e) { if (e.defined()) { e.accept(this); } else { expr = Expr(); } stmt = Stmt(); return std::move(expr); }
Expr IRMutator::mutate(Expr e) { if (e.defined()) { e.accept(this); } else { expr = Expr(); } stmt = Stmt(); return expr; }
void IRGraphVisitor::include(const Expr &e) { if (visited.count(e.ptr)) { return; } else { visited.insert(e.ptr); e.accept(this); return; } }
Expr product(Expr e, const std::string &name) { Internal::FindFreeVars v; e.accept(&v); assert(v.rdom.defined() && "Expression passed to product must reference a reduction domain"); Func f(name); f(v.free_vars) *= e; return f(v.free_vars); }
Expr maximum(Expr e, const std::string &name) { Internal::FindFreeVars v; e.accept(&v); assert(v.rdom.defined() && "Expression passed to maximum must reference a reduction domain"); Func f(name); f(v.free_vars) = e.type().min(); f(v.free_vars) = max(f(v.free_vars), e); return f(v.free_vars); }
int main(){ std::string equation; std::getline(std::cin,equation,'\n'); Parser parser(equation); Expr* e ; e = parser.expr(); SExper sexper; e->accept(sexper); std::cout << std::endl; }
// Pass an IRVisitor through to all Exprs referenced in the ReductionDomainContents void accept(IRVisitor *visitor) { for (const ReductionVariable &rvar : domain) { if (rvar.min.defined()) { rvar.min.accept(visitor); } if (rvar.extent.defined()) { rvar.extent.accept(visitor); } } if (predicate.defined()) { predicate.accept(visitor); } }
Expr IRRewriter::rewrite(Expr e) { if (e.defined()) { e.accept(this); e = expr; } else { e = Expr(); } expr = Expr(); stmt = Stmt(); func = Func(); return e; }
void Function::define_reduction(const vector<Expr> &args, Expr value) { assert(defined() && "Can't add a reduction definition without a regular definition first"); assert(!is_reduction() && "Function already has a reduction definition"); assert(value.defined() && "Undefined expression in right-hand-side of reduction"); // Check the dimensionality matches assert(args.size() == contents.ptr->args.size() && "Dimensionality of reduction definition must match dimensionality of pure definition"); // The pure args are those naked vars in the args that are not in // a reduction domain and are not parameters vector<string> pure_args; for (size_t i = 0; i < args.size(); i++) { assert(args[i].defined() && "Undefined expression in left-hand-side of reduction"); if (const Variable *var = args[i].as<Variable>()) { if (!var->param.defined() && !var->reduction_domain.defined()) { assert(var->name == contents.ptr->args[i] && "Pure argument to update step must have the same name as pure argument to initialization step in the same dimension"); pure_args.push_back(var->name); } } } // Make sure all the vars in the args and the value are either // pure args, in the reduction domain, or a parameter CheckVars check; check.pure_args = pure_args; value.accept(&check); for (size_t i = 0; i < args.size(); i++) { args[i].accept(&check); } assert(check.reduction_domain.defined() && "No reduction domain referenced in reduction definition"); contents.ptr->reduction_args = args; contents.ptr->reduction_value = value; contents.ptr->reduction_domain = check.reduction_domain; // First add the pure args in order for (size_t i = 0; i < pure_args.size(); i++) { Schedule::Dim d = {pure_args[i], For::Serial}; contents.ptr->reduction_schedule.dims.push_back(d); } // Then add the reduction domain outside of that for (size_t i = 0; i < check.reduction_domain.domain().size(); i++) { Schedule::Dim d = {check.reduction_domain.domain()[i].var, For::Serial}; contents.ptr->reduction_schedule.dims.push_back(d); } }
void print_expr(std::ostream& os, const Expr& e) { struct V : Expr::Visitor { V(std::ostream& os) : os(os) { } void visit(const Id& n) { print_atom(os, n); } void visit(const Bool& e) { print_atom(os, e); } void visit(const Int& e) { print_atom(os, e); } void visit(const Var& e) { print_expr(os, e.name()); } // Arithmetic expressions void visit(const Add& e) { print_node(os, "add", e); } void visit(const Sub& e) { print_node(os, "sub", e); } void visit(const Mul& e) { print_node(os, "mul", e); } void visit(const Div& e) { print_node(os, "div", e); } void visit(const Neg& e) { print_node(os, "neg", e); } void visit(const Pos& e) { print_node(os, "pos", e); } // Relational expressions void visit(const Eq& e) { print_node(os, "eq", e); } void visit(const Ne& e) { print_node(os, "ne", e); } void visit(const Lt& e) { print_node(os, "lt", e); } void visit(const Gt& e) { print_node(os, "gt", e); } void visit(const Le& e) { print_node(os, "le", e); } void visit(const Ge& e) { print_node(os, "ge", e); } // Logical expressions void visit(const And& e) { print_node(os, "and", e); } void visit(const Or& e) { print_node(os, "or", e); } void visit(const Imp& e) { print_node(os, "imp", e); } void visit(const Iff& e) { print_node(os, "iff", e); } void visit(const Not& e) { print_node(os, "not", e); } void visit(const Bind& e) { print_node(os, "bind", e); } void visit(const Forall& e) { print_node(os, "forall", e); } void visit(const Exists& e) { print_node(os, "exists", e); } void visit(const Bool_type& t) { print_symbol(os, "bool"); } void visit(const Int_type& t) { print_symbol(os, "int"); } std::ostream& os; }; // Print bools as true. os << std::boolalpha; V v(os); e.accept(v); }
void visit(const AssertStmt *op) { Expr m = op->message; FindErrorHandler f; m.accept(&f); if (f.result) { Expr c = op->condition; ParseCondition p; c.accept(&p); if (p.left.defined() && p.right.defined()) { const Call *reinterpret_call = p.left.as<Call>(); if (!reinterpret_call || !reinterpret_call->is_intrinsic(Call::reinterpret)) return; Expr name = reinterpret_call->args[0]; const Variable *V = name.as<Variable>(); string name_host_ptr = V->name; int expected_alignment = alignments_needed[name_host_ptr]; if (is_const(p.right, expected_alignment)) { count++; alignments_needed.erase(name_host_ptr); } } } }
void include(const Expr &e) { if (result.defined()) return; set<const IRNode *, Expr::Compare>::iterator iter = visited.find(e.ptr); if (iter != visited.end()) { if (e.as<IntImm>() || e.as<FloatImm>() || e.as<Variable>() || e.as<Cast>()) { return; } result = e; } else { e.accept(this); visited.insert(e.ptr); } }
Expr mutate(const Expr &e) { if (e.defined()) { map<Expr, string, IRDeepCompare>::iterator iter = scope.find(e); if (iter != scope.end()) { expr = Variable::make(e.type(), iter->second); } else { e.accept(this); } } else { expr = Expr(); } stmt = Stmt(); return std::move(expr); }
void visit_let(const std::string &name, Expr value, T body) { bool old_varies = varies; varies = false; value.accept(this); bool value_varies = varies; varies |= old_varies; if (value_varies) { varying.push(name, 0); } body.accept(this); if (value_varies) { varying.pop(name); } predicate = substitute(name, value, predicate); }
void include(const Expr &e) { if (result.defined()) return; set<const IRNode *>::iterator iter = visited.find(e.ptr); if (iter != visited.end()) { if (e.as<Variable>() || is_const(e)) { return; } result = e; } else { e.accept(this); visited.insert(e.ptr); } }
void accept(IRVisitor *visitor) const { if (predicate.defined()) { predicate.accept(visitor); } for (Expr val : values) { val.accept(visitor); } for (Expr arg : args) { arg.accept(visitor); } stage_schedule.accept(visitor); for (const Specialization &s : specializations) { if (s.condition.defined()) { s.condition.accept(visitor); } s.definition.accept(visitor); } }
Tuple argmin(Expr e, const std::string &name) { Internal::FindFreeVars v; e.accept(&v); Func f(name); assert(v.rdom.defined() && "Expression passed to argmin must reference a reduction domain"); Tuple initial_tup(vector<Expr>(v.rdom.dimensions()+1)); Tuple update_tup(vector<Expr>(v.rdom.dimensions()+1)); for (int i = 0; i < v.rdom.dimensions(); i++) { initial_tup[i] = 0; update_tup[i] = v.rdom[i]; } int value_index = (int)initial_tup.size()-1; initial_tup[value_index] = e.type().max(); update_tup[value_index] = e; f(v.free_vars) = initial_tup; Expr better = e < f(v.free_vars)[value_index]; f(v.free_vars) = tuple_select(better, update_tup, f(v.free_vars)); return f(v.free_vars); }
void IpeSequence::describe(int offset) { AstDumpToNode logger(stdout, offset + 3); char pad[32] = { '\0' }; if (offset < 32) { char* tptr = pad; for (int i = 0; i < offset; i++) *tptr++ = ' '; *tptr = '\0'; } printf("%s#<IpeSequence\n", pad); for (int i = 1; i <= body.length; i++) { Expr* expr = body.get(i); if (isBlockStmt(expr) == true) { IpeSequence* seq = (IpeSequence*) expr; seq->describe(offset + 3); } else { printf("%s ", pad); expr->accept(&logger); printf("\n"); } } printf("%s>\n", pad); }
pair<int, int> ModulusRemainder::analyze(Expr e) { e.accept(this); return make_pair(modulus, remainder); }
void print(Expr ir) { ir.accept(this); }
bool expr_depends_on_var(Expr e, string v) { ExprDependsOnVar depends(v); e.accept(&depends); return depends.result; }