void visit(const Variable *v) { string var_name = v->name; expr = v; if (internal.contains(var_name)) { // Don't capture internally defined vars return; } if (v->reduction_domain.defined()) { if (explicit_rdom) { if (v->reduction_domain.same_as(rdom.domain())) { // This variable belongs to the explicit reduction domain, so // skip it. return; } else { // This should be converted to a pure variable and // added to the free vars list. var_name = unique_name('v'); expr = Variable::make(v->type, var_name); } } else { if (!rdom.defined()) { // We're looking for a reduction domain, and this variable // has one. Capture it. rdom = RDom(v->reduction_domain); return; } else if (!rdom.domain().same_as(v->reduction_domain)) { // We were looking for a reduction domain, and already // found one. This one is different! user_error << "Inline reduction \"" << name << "\" refers to reduction variables from multiple reduction domains: " << v->name << ", " << rdom.x.name() << "\n"; } else { // Recapturing an already-known reduction domain return; } } } if (v->param.defined()) { // Skip parameters return; } for (size_t i = 0; i < free_vars.size(); i++) { if (var_name == free_vars[i].name()) return; } free_vars.push_back(Var(var_name)); call_args.push_back(v); }
Func blur_then_transpose(Func f, Func coeff, Expr size, Expr sigma) { Func blurred = performBlur(f, coeff, size, sigma); // Also compute attenuation due to zero boundary condition by // blurring an image of ones in the same way. This gives a // boundary condition equivalent to reweighting the Gaussian // near the edge. (TODO: add a generator param to select // different boundary conditions). Func ones; ones(x, y) = 1.0f; Func attenuation = performBlur(ones, coeff, size, sigma); // Invert the attenuation so we can multiply by it. The // attenuation is the same for every row/channel so we only // need one column. Func inverse_attenuation; inverse_attenuation(y) = 1.0f / attenuation(0, y); // Transpose it Func transposed; transposed(x, y) = blurred(y, x); // Correct for attenuation Func out; out(x, y) = transposed(x, y) * inverse_attenuation(x); // Schedule it. Var yi, xi, yii, xii; attenuation.compute_root(); inverse_attenuation.compute_root().vectorize(y, 8); out.compute_root() .tile(x, y, xi, yi, 8, 32) .tile(xi, yi, xii, yii, 8, 8) .vectorize(xii).unroll(yii).parallel(y); blurred.compute_at(out, y); transposed.compute_at(out, xi).vectorize(y).unroll(x); for (int i = 0; i < blurred.num_update_definitions(); i++) { RDom r = blurred.reduction_domain(i); if (r.defined()) { blurred.update(i).reorder(x, r); } blurred.update(i).vectorize(x, 8).unroll(x); } return out; }
Expr::Expr(const RDom &d) : contents(new ExprContents(makeVar((d[0].name())), Int(32))) { contents->isRVar = true; assert(d.dimensions() == 1 && "Can only use single-dimensional domains directly as expressions\n"); setRDom(d); child(d[0].min()); child(d[0].size()); }
FindFreeVars(RDom r, const string &n) : rdom(r), explicit_rdom(r.defined()), name(n) { }
bool RDom::operator==(const RDom &other) const { assert(isDefined() && other.isDefined() && "Reduction domain not defined"); return contents == other.contents; }