Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reenable warning about unscheduled update definitions #6602

Merged
merged 5 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/HelloMatlab/iir_blur.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Func blur_cols_transpose(Func input, Expr height, Expr alpha) {
blur.compute_at(transpose, yo);

// Vectorize computations within the strips.
blur.update(0)
.vectorize(x);
blur.update(1)
.reorder(x, ry)
.vectorize(x);
Expand Down
4 changes: 4 additions & 0 deletions apps/fft/fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,10 @@ ComplexFunc fft2d_r2c(Func r,
dft.update(4).allow_race_conditions().vectorize(n0z1, vector_size);
dft.update(5).allow_race_conditions().vectorize(n0z2, vector_size);

// Intentionally serial
dft.update(0).unscheduled();
dft.update(3).unscheduled();

// Our result is undefined outside these bounds.
dft.bound(n0, 0, N0);
dft.bound(n1, 0, (N1 + 1) / 2 + 1);
Expand Down
1 change: 1 addition & 0 deletions apps/linear_algebra/src/blas_l1_generators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class AXPYGenerator : public Generator<AXPYGenerator<T>> {
Var ii("ii");
result_.update().vectorize(vecs, vec_size);
}
result_.update(1).unscheduled(); // Leave the tail unvectorized

result_.bound(i, 0, x_.width());
result_.dim(0).set_bounds(0, x_.width());
Expand Down
2 changes: 1 addition & 1 deletion src/Derivative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1808,7 +1808,7 @@ void ReverseAccumulationVisitor::propagate_halide_function_call(
// If previous update has a different set of reduction variables,
// don't merge
const vector<ReductionVariable> &rvars =
func_to_update.update(update_id).get_schedule().rvars();
func_to_update.function().update(update_id).schedule().rvars();
if (!merged_r.defined()) {
return rvars.empty();
}
Expand Down
27 changes: 27 additions & 0 deletions src/Func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ bool is_const_assignment(const string &func_name, const vector<Expr> &args, cons
} // namespace

void Stage::set_dim_type(const VarOrRVar &var, ForType t) {
definition.schedule().touched() = true;
bool found = false;
vector<Dim> &dims = definition.schedule().dims();
for (auto &dim : dims) {
Expand Down Expand Up @@ -407,6 +408,7 @@ void Stage::set_dim_type(const VarOrRVar &var, ForType t) {
}

void Stage::set_dim_device_api(const VarOrRVar &var, DeviceAPI device_api) {
definition.schedule().touched() = true;
bool found = false;
vector<Dim> &dims = definition.schedule().dims();
for (auto &dim : dims) {
Expand Down Expand Up @@ -662,12 +664,15 @@ bool apply_split_directive(const Split &s, vector<ReductionVariable> &rvars,
} // anonymous namespace

Func Stage::rfactor(const RVar &r, const Var &v) {
definition.schedule().touched() = true;
return rfactor({{r, v}});
}

Func Stage::rfactor(vector<pair<RVar, Var>> preserved) {
user_assert(!definition.is_init()) << "rfactor() must be called on an update definition\n";

definition.schedule().touched() = true;

const string &func_name = function.name();
vector<Expr> &args = definition.args();
vector<Expr> &values = definition.values();
Expand Down Expand Up @@ -969,6 +974,8 @@ void Stage::split(const string &old, const string &outer, const string &inner, c
<< outer << " and " << inner << " with factor of " << factor << "\n";
vector<Dim> &dims = definition.schedule().dims();

definition.schedule().touched() = true;

// Check that the new names aren't already in the dims list.
for (auto &dim : dims) {
string new_names[2] = {inner, outer};
Expand Down Expand Up @@ -1116,6 +1123,7 @@ void Stage::split(const string &old, const string &outer, const string &inner, c
}

Stage &Stage::split(const VarOrRVar &old, const VarOrRVar &outer, const VarOrRVar &inner, const Expr &factor, TailStrategy tail) {
definition.schedule().touched() = true;
if (old.is_rvar) {
user_assert(outer.is_rvar) << "Can't split RVar " << old.name() << " into Var " << outer.name() << "\n";
user_assert(inner.is_rvar) << "Can't split RVar " << old.name() << " into Var " << inner.name() << "\n";
Expand All @@ -1128,6 +1136,7 @@ Stage &Stage::split(const VarOrRVar &old, const VarOrRVar &outer, const VarOrRVa
}

Stage &Stage::fuse(const VarOrRVar &inner, const VarOrRVar &outer, const VarOrRVar &fused) {
definition.schedule().touched() = true;
if (!fused.is_rvar) {
user_assert(!outer.is_rvar) << "Can't fuse Var " << fused.name()
<< " from RVar " << outer.name() << "\n";
Expand Down Expand Up @@ -1211,6 +1220,8 @@ class CheckForFreeVars : public IRGraphVisitor {
Stage Stage::specialize(const Expr &condition) {
user_assert(condition.type().is_bool()) << "Argument passed to specialize must be of type bool\n";

definition.schedule().touched() = true;

// The condition may not depend on Vars or RVars
Internal::CheckForFreeVars check;
condition.accept(&check);
Expand Down Expand Up @@ -1242,6 +1253,9 @@ void Stage::specialize_fail(const std::string &message) {
const vector<Specialization> &specializations = definition.specializations();
user_assert(specializations.empty() || specializations.back().failure_message.empty())
<< "Only one specialize_fail() may be defined per Stage.";

definition.schedule().touched() = true;

(void)definition.add_specialization(const_true());
Specialization &s = definition.specializations().back();
s.failure_message = message;
Expand Down Expand Up @@ -1383,6 +1397,8 @@ void Stage::remove(const string &var) {
}

Stage &Stage::rename(const VarOrRVar &old_var, const VarOrRVar &new_var) {
definition.schedule().touched() = true;

if (old_var.is_rvar) {
user_assert(new_var.is_rvar)
<< "In schedule for " << name()
Expand Down Expand Up @@ -1472,11 +1488,13 @@ Stage &Stage::rename(const VarOrRVar &old_var, const VarOrRVar &new_var) {
}

Stage &Stage::allow_race_conditions() {
definition.schedule().touched() = true;
definition.schedule().allow_race_conditions() = true;
return *this;
}

Stage &Stage::atomic(bool override_associativity_test) {
definition.schedule().touched() = true;
definition.schedule().atomic() = true;
definition.schedule().override_atomic_associativity_test() = override_associativity_test;
return *this;
Expand Down Expand Up @@ -1600,6 +1618,7 @@ Stage &Stage::tile(const std::vector<VarOrRVar> &previous,
}

Stage &Stage::reorder(const std::vector<VarOrRVar> &vars) {
definition.schedule().touched() = true;
const string &func_name = function.name();
vector<Expr> &args = definition.args();
vector<Expr> &values = definition.values();
Expand Down Expand Up @@ -1839,18 +1858,21 @@ Stage &Stage::hexagon(const VarOrRVar &x) {
}

Stage &Stage::prefetch(const Func &f, const VarOrRVar &at, const VarOrRVar &from, Expr offset, PrefetchBoundStrategy strategy) {
definition.schedule().touched() = true;
PrefetchDirective prefetch = {f.name(), at.name(), from.name(), std::move(offset), strategy, Parameter()};
definition.schedule().prefetches().push_back(prefetch);
return *this;
}

Stage &Stage::prefetch(const Internal::Parameter &param, const VarOrRVar &at, const VarOrRVar &from, Expr offset, PrefetchBoundStrategy strategy) {
definition.schedule().touched() = true;
PrefetchDirective prefetch = {param.name(), at.name(), from.name(), std::move(offset), strategy, param};
definition.schedule().prefetches().push_back(prefetch);
return *this;
}

Stage &Stage::compute_with(LoopLevel loop_level, const map<string, LoopAlignStrategy> &align) {
definition.schedule().touched() = true;
loop_level.lock();
user_assert(!loop_level.is_inlined() && !loop_level.is_root())
<< "Undefined loop level to compute with\n";
Expand Down Expand Up @@ -1906,6 +1928,11 @@ std::string Stage::source_location() const {
return definition.source_location();
}

void Stage::unscheduled() {
user_assert(!definition.schedule().touched()) << "Stage::unscheduled called on an update definition with a schedule\n";
definition.schedule().touched() = true;
}

void Func::invalidate_cache() {
if (pipeline_.defined()) {
pipeline_.invalidate_cache();
Expand Down
7 changes: 6 additions & 1 deletion src/Func.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ class Stage {
Stage(Internal::Function f, Internal::Definition d, size_t stage_index)
: function(std::move(f)), definition(std::move(d)), stage_index(stage_index) {
internal_assert(definition.defined());
definition.schedule().touched() = true;

dim_vars.reserve(function.args().size());
for (const auto &arg : function.args()) {
Expand Down Expand Up @@ -474,6 +473,12 @@ class Stage {
* empty string if no debug symbols were found or the debug
* symbols were not understood. Works on OS X and Linux only. */
std::string source_location() const;

/** Assert that this stage has intentionally been given no schedule, and
* suppress the warning about unscheduled update definitions that would
* otherwise fire. This counts as a schedule, so calling this twice on the
* same Stage will fail the assertion. */
void unscheduled();
};

// For backwards compatibility, keep the ScheduleHandle name.
Expand Down
6 changes: 3 additions & 3 deletions src/ScheduleFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2078,12 +2078,12 @@ bool validate_schedule(Function f, const Stmt &s, const Target &target, bool is_
const Definition &r = f.update((int)i);
if (!r.schedule().touched()) {
user_warning
<< "Warning: Update step " << i
<< "Update definition " << i
<< " of function " << f.name()
<< " has not been scheduled, even though some other"
<< " steps have been. You may have forgotten to"
<< " definitions have been. You may have forgotten to"
<< " schedule it. If this was intentional, call "
<< f.name() << ".update(" << i << ") to suppress"
<< f.name() << ".update(" << i << ").unscheduled() to suppress"
<< " this warning.\n";
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/autoschedulers/adams2019/cost_model_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ class CostModel : public Generator<CostModel<training>> {
};

// Pipeline features processing
conv1_stage1.compute_root().vectorize(c);
conv1_stage1.compute_root().vectorize(c).update().vectorize(c);
squashed_head1_filter.compute_root().vectorize(c);

// Schedule features processing. The number of schedule
Expand Down
11 changes: 8 additions & 3 deletions test/correctness/atomics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,14 @@ void test_predicated_hist(const Backend &backend) {
hist(im(r)) = min(hist(im(r)) + cast<T>(1), cast<T>(100)); // cas loop

RDom r2(0, img_size);
// This predicate means that the update definitions below can't actually be
// atomic, because the if isn't included in the atomic block.
r2.where(hist(im(r2)) > cast<T>(0) && hist(im(r2)) < cast<T>(90));
hist(im(r2)) -= cast<T>(1); // atomic add
hist(im(r2)) = min(hist(im(r2)) + cast<T>(1), cast<T>(100)); // cas loop
hist(im(r2)) -= cast<T>(1);
hist(im(r2)) = min(hist(im(r2)) + cast<T>(1), cast<T>(100));

hist.update(3).unscheduled();
hist.update(4).unscheduled();

hist.compute_root();
for (int update_id = 0; update_id < 3; update_id++) {
Expand Down Expand Up @@ -531,7 +536,7 @@ void test_nested_atomics(const Backend &backend) {
Expr new_max = max(im(r), old_max);
arg_max() = {new_index, new_max};

im.compute_inline().atomic();
im.compute_inline().atomic().update().atomic();
arg_max.compute_root();
switch (backend) {
case Backend::CPU: {
Expand Down
6 changes: 6 additions & 0 deletions test/correctness/compute_with.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ int multiple_fuse_group_test() {
p.fuse(x, y, t).parallel(t);
h.fuse(x, y, t).parallel(t);
h.compute_with(p, t);
h.update(0).unscheduled();
h.update(1).unscheduled();
h.update(2).unscheduled();

f.update(0).compute_with(g, y, LoopAlignStrategy::AlignEnd);
f.compute_with(g, x);
Expand Down Expand Up @@ -1277,6 +1280,7 @@ int update_stage_test() {
g.compute_root();
f.compute_root();

f.update(0).unscheduled();
f.update(1).compute_with(g.update(0), y);

g.bound(x, 0, g_size).bound(y, 0, g_size);
Expand Down Expand Up @@ -1659,6 +1663,8 @@ int update_stage_diagonal_test() {

f.update(1).compute_with(g.update(0), y);
g.update(0).compute_with(h, y);
f.update(0).unscheduled();
g.update(1).unscheduled();

g.bound(x, 0, g_size).bound(y, 0, g_size);
f.bound(x, 0, f_size).bound(y, 0, f_size);
Expand Down
1 change: 1 addition & 0 deletions test/correctness/extern_bounds_inference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ int main(int argc, char **argv) {
f1.compute_at(g, y);
f2.compute_at(g, x);
g.reorder(y, x).vectorize(y, 4);
g.update().unscheduled();

g.infer_input_bounds({W, H});

Expand Down
2 changes: 2 additions & 0 deletions test/correctness/named_updates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ int main(int argc, char **argv) {
more_updates.a.vectorize(r, 4);
more_updates.b.vectorize(r, 4);
more_updates.c.vectorize(r, 4);

f.update().unscheduled(); // fix_first isn't scheduled
}

// Define the same thing without all the weird syntax and without
Expand Down
2 changes: 1 addition & 1 deletion test/correctness/parallel_reductions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int main(int argc, char **argv) {
sum_rows.compute_root().vectorize(i, 4).parallel(j);
sum_rows.update().parallel(j);
sum_cols.compute_root().vectorize(j, 4);
sum_cols.update();
sum_cols.update().unscheduled();
out.output_buffer().dim(0).set_bounds(0, 256);

Buffer<int> result = out.realize({256});
Expand Down
4 changes: 2 additions & 2 deletions test/correctness/sliding_reduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ int main(int argc, char **argv) {
f(x, y) = call_count(f(x, y));

f.unroll(y, 2);
f.update(0);
f.update(1);
f.update(0).unscheduled();
f.update(1).unscheduled();

Func g("g");
g(x, y) = f(x, y) + f(x, y - 1) + f(x, y - 2);
Expand Down
11 changes: 4 additions & 7 deletions test/correctness/tuple_reduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,13 @@ int main(int argc, char **argv) {
f.hexagon(y).vectorize(x, 32);
}
for (int i = 0; i < 10; i++) {
f.update(i).unscheduled();
if (i & 1) {
if (target.has_gpu_feature()) {
f.update(i).gpu_tile(x, y, xo, yo, xi, yi, 16, 16);
} else if (target.has_feature(Target::HVX)) {
f.update(i).hexagon(y).vectorize(x, 32);
}
} else {
f.update(i);
}
}

Expand Down Expand Up @@ -103,14 +102,13 @@ int main(int argc, char **argv) {

// Schedule the even update steps on the gpu
for (int i = 0; i < 10; i++) {
f.update(i).unscheduled();
if (i & 1) {
if (target.has_gpu_feature()) {
f.update(i).gpu_tile(x, y, xo, yo, xi, yi, 16, 16);
} else if (target.has_feature(Target::HVX)) {
f.update(i).hexagon(y).vectorize(x, 32);
}
} else {
f.update(i);
}
}

Expand Down Expand Up @@ -146,9 +144,8 @@ int main(int argc, char **argv) {

// Schedule the even update steps on the gpu
for (int i = 0; i < 10; i++) {
if (i & 1) {
f.update(i);
} else {
f.update(i).unscheduled();
if ((i & 1) == 0) {
if (target.has_gpu_feature()) {
f.update(i).gpu_tile(x, y, xo, yo, xi, yi, 16, 16);
} else if (target.has_feature(Target::HVX)) {
Expand Down
2 changes: 1 addition & 1 deletion test/correctness/vectorized_initialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main(int argc, char **argv) {
f(x) = x;
f(r) = f(r - 1) + f(r + 1);
f.compute_root().vectorize(x, 4);
f.update();
f.update().unscheduled();

g(x) = f(x);
Buffer<int> result = g.realize({4});
Expand Down
1 change: 1 addition & 0 deletions test/warning/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ tests(GROUPS warning
hidden_pure_definition.cpp
require_const_false.cpp
sliding_vectors.cpp
unscheduled_update_def.cpp
)

# Don't look for "Success!" in warning tests, look for "Warning:" instead.
Expand Down
17 changes: 17 additions & 0 deletions test/warning/unscheduled_update_def.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "Halide.h"

using namespace Halide;

int main(int argc, char **argv) {
Func f;
Var x;

f(x) = 0;
f(x) += 5;

f.vectorize(x, 8);

f.realize({1024});

return 0;
}