Skip to content
Draft
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
12 changes: 12 additions & 0 deletions src/Bounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,18 @@ Interval bounds_of_expr_in_scope(const Expr &expr, const Scope<Interval> &scope,
return bounds_of_expr_in_scope_with_indent(expr, scope, fb, const_bound, 0);
}

Expr and_condition_over_domain(const Expr &e, const Scope<Interval> &varying) {
internal_assert(e.type().is_bool()) << "Expr provided to and_condition_over_domain is not boolean: " << e << "\n";
Interval bounds = bounds_of_expr_in_scope(e, varying);
internal_assert(bounds.has_lower_bound()) << "Failed to produce bound on boolean value in and_condition_over_domain" << e << "\n";
// Minimum of a boolean value is sufficient condition, implies expression.
return simplify(bounds.min);
}

Expr or_condition_over_domain(const Expr &c, const Scope<Interval> &varying) {
return simplify(!and_condition_over_domain(simplify(!c), varying));
}

void merge_boxes(Box &a, const Box &b) {
if (b.empty()) {
return;
Expand Down
16 changes: 16 additions & 0 deletions src/Bounds.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ Expr find_constant_bound(const Expr &e, Direction d,
* +/-inf. */
Interval find_constant_bounds(const Expr &e, const Scope<Interval> &scope);

/** Take a conditional that includes variables that vary over some
* domain, and convert it to a more conservative (less frequently
* true) condition that doesn't depend on those variables. Formally,
* the output expr implies the input expr.
*
* The condition may be a vector condition, in which case we also
* 'and' over the vector lanes, and return a scalar result. */
Expr and_condition_over_domain(const Expr &c, const Scope<Interval> &varying);

/** Take a conditional that includes variables that vary over some
* domain, and convert it to a weaker (less frequently false) condition
* that doesn't depend on those variables. Formally, the input expr
* implies the output expr. Note that this function might be unable to
* provide a better response than simply const_true(). */
Expr or_condition_over_domain(const Expr &c, const Scope<Interval> &varying);

/** Represents the bounds of a region of arbitrary dimension. Zero
* dimensions corresponds to a scalar region. */
struct Box {
Expand Down
9 changes: 8 additions & 1 deletion src/Simplify_Cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,20 @@ Expr Simplify::visit(const Cast *op, ExprInfo *info) {
} else if (cast &&
op->type.is_int_or_uint() &&
cast->type.is_int_or_uint() &&
cast->value.type().is_int_or_uint() &&
op->type.bits() <= cast->type.bits() &&
op->type.bits() <= op->value.type().bits()) {
// If this is a cast between integer types, where the
// outer cast is narrower than the inner cast and the
// inner cast's argument, the inner cast can be
// eliminated. The inner cast is either a sign extend
// or a zero extend, and the outer cast truncates the extended bits
// or a zero extend, and the outer cast truncates the extended bits.
// The requirement that cast->value is itself int-or-uint is crucial:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments should not spend this much space arguing why a hypothetical alternative version of this would be buggy. After the first sentence it's enough to just say that everything involved needs to be an int.

// a float source makes `cast` an fp-to-int conversion, whose low
// bits are not the same as an fp-to-int conversion of a narrower
// type. For example, int32(uint64(float64(-21))) evaluates to 0
// (float-to-uint of a negative value saturates to 0 in Halide),
// while the stripped form int32(float64(-21)) evaluates to -21.
if (op->type == cast->value.type()) {
return mutate(cast->value, info);
} else {
Expand Down
386 changes: 51 additions & 335 deletions src/Solve.cpp

Large diffs are not rendered by default.

18 changes: 0 additions & 18 deletions src/Solve.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,6 @@ Interval solve_for_outer_interval(const Expr &c, const std::string &variable);
* true inside of it, and might be true or false outside of it. */
Interval solve_for_inner_interval(const Expr &c, const std::string &variable);

/** Take a conditional that includes variables that vary over some
* domain, and convert it to a more conservative (less frequently
* true) condition that doesn't depend on those variables. Formally,
* the output expr implies the input expr.
*
* The condition may be a vector condition, in which case we also
* 'and' over the vector lanes, and return a scalar result. */
Expr and_condition_over_domain(const Expr &c, const Scope<Interval> &varying);

/** Take a conditional that includes variables that vary over some
* domain, and convert it to a weaker (less frequently false) condition
* that doesn't depend on those variables. Formally, the input expr
* implies the output expr. Note that this function might be unable to
* provide a better response than simply const_true(). */
Expr or_condition_over_domain(const Expr &c, const Scope<Interval> &varying);

void solve_test();

} // namespace Internal
} // namespace Halide

Expand Down
1 change: 1 addition & 0 deletions test/correctness/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ tests(GROUPS correctness
sliding_over_guard_with_if.cpp
sliding_reduction.cpp
sliding_window.cpp
solve.cpp
sort_exprs.cpp
specialize.cpp
specialize_to_gpu.cpp
Expand Down
Loading
Loading