Skip to content

Commit

Permalink
[Codegen_LLVM] Annotate LLVM IR functions with nounwind/`mustprogre…
Browse files Browse the repository at this point in the history
…ss` attributes (halide#6897)

My reasoning is as follows, please correct me if i'm wrong:
1. Halide-generated code never throws exceptions
2. Halide-generated code always `call`s (as opposed to `invoke`s) the functions, there is no exception-safety RAII
3. Halide loops are meant to have finite number of iterations, they aren't meant to be endless and side-effect free
4. Halide (IR) assertions *might* abort.
5. Likewise, external callees *might* abort. (???)

Therefore, when not in presence of external calls,
it is obvious that (1) no exception will be unwinded
out of the halide-generated function, (2) none of the loops
will end up being endless with no observable side-effects.
... which is the semantics that is being stated by the
    LLVM IR function attributes `nounwind`+`mustprogress`.

I'm less clear as to what are the prerequisites on the behavior of
the external callees, but i do believe that they must also
at least not unwind. I guess they are also at least required to
either return or abort eventually.
  • Loading branch information
LebedevRI authored and ardier committed Mar 3, 2024
1 parent 70eb47a commit 9d09ca5
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
10 changes: 10 additions & 0 deletions src/CodeGen_Internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,16 @@ void set_function_attributes_from_halide_target_options(llvm::Function &fn) {
fn.addFnAttr("tune-cpu", mcpu_tune);
fn.addFnAttr("target-features", mattrs);

// Halide-generated IR is not exception-safe.
// No exception should unwind out of Halide functions.
// No exception should be thrown within Halide functions.
// All functions called by the Halide function must not unwind.
fn.setDoesNotThrow();

// Side-effect-free loops are undefined.
// But asserts and external calls *might* abort.
fn.setMustProgress();

// Turn off approximate reciprocals for division. It's too
// inaccurate even for us.
fn.addFnAttr("reciprocal-estimates", "none");
Expand Down
2 changes: 0 additions & 2 deletions src/CodeGen_LLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3377,7 +3377,6 @@ void CodeGen_LLVM::visit(const Call *op) {
if (op->is_pure()) {
call->setDoesNotAccessMemory();
}
call->setDoesNotThrow();
value = call;
} else {

Expand Down Expand Up @@ -3410,7 +3409,6 @@ void CodeGen_LLVM::visit(const Call *op) {
if (op->is_pure()) {
call->setDoesNotAccessMemory();
}
call->setDoesNotThrow();
if (!call->getType()->isVoidTy()) {
value = builder->CreateInsertElement(value, call, idx);
} // otherwise leave it as undef.
Expand Down

0 comments on commit 9d09ca5

Please sign in to comment.