-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add TailStrategy::Predicate #5856
Conversation
The existence of a static Call::as_tag that takes an Expr sort of implies that Tags should be their own IR nodes rather than a call type. What do you think the pros/cons of making Tag a separate IRNode are? E.g. would it duplicate a bunch of code from Call handlers and methods? |
I don't know that Call::as_tag implies tags should be their own IR node. I do think that might make sense regardless. Pros:
Cons:
I think that con is pretty big, and the pros are pretty small. At the very least, we should make that change in a separate PR I think. |
if (call && (call->is_intrinsic(Call::likely) || | ||
call->is_intrinsic(Call::likely_if_innermost) || | ||
call->is_intrinsic(Call::strict_float))) { | ||
const Call *call = Call::as_tag(c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (const Call *call == Call::as_tag(c)) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
call
is used below :) I made this change at first and had to revert it for that.
Bug injected in #5856: the change in Simplify_Let.cpp was inadvertently stripping `strict_float()` calls that wrapped the RHS of a Let-expr, which can change results nontrivially in some cases. I don't think a new test for this fix is practical -- it would be a little fragile, as it would rely on the specifics of simplification that could change over time. As a drive-by, also added an explicit rule to Simplify_Call to ensure that strict_float(strict_float(x)) -> strict_float(x) in *all* cases. (The existing rule didn't do this in all cases.) Also added an assertion to Codegen_LLVM.cpp that no calls of the form strict_float(strict_float(x)) should ever be seen at that point.
* Don't strip strict_float() from lets Bug injected in #5856: the change in Simplify_Let.cpp was inadvertently stripping `strict_float()` calls that wrapped the RHS of a Let-expr, which can change results nontrivially in some cases. I don't think a new test for this fix is practical -- it would be a little fragile, as it would rely on the specifics of simplification that could change over time. As a drive-by, also added an explicit rule to Simplify_Call to ensure that strict_float(strict_float(x)) -> strict_float(x) in *all* cases. (The existing rule didn't do this in all cases.)
This PR adds a new
TailStrategy::Predicate
. This is very similar toTailStrategy::GuardWithIf
, except it uses predicated loops unconditionally, instead of heuristically choosing based on the target.On some targets, we think using predicated loads/stores is always faster than scalarizing (Hexagon). On these targets, we can just use predicated loads/stores for
TailStrategy::GuardWithIf
. On these targets, usingTailStrategy::Predicate
will not change anything.On most other targets, predicated loads/stores are expensive (emulated with scalar code). In particular, the cost of inserting and extracting the scalars to/from vectors can be high. On these targets, Halide scalarizes the whole body of the loop instead. This is unfortunate in some cases, when the loop is very expensive, it can be worth the added overhead to assemble the scalarized loads/stores into vectors, so we can vectorize the expensive computation. This PR allows programmers to ask for this with the new tail strategy.