This is an archive of the discontinued LLVM Phabricator instance.

[mlir][transform] Better debugging facilites for invalid API usage
ClosedPublic

Authored by springerm on Apr 3 2023, 8:32 AM.

Details

Summary

This revision adds additional "expensive-checks" checks to the transform dialect that detect the most common cases of:

  • Missing consumesHandle side effects on transform ops.
  • Patterns that remove operations but do not notify the transform dialect.

In essence, these additional checks are looking for dangling pointers to erased payload ops in the transform dialect state and crash the program execution (by dereferencing free'd memory) or triggering an assertion failure. It is recommended to run these extra checks with ASAN. Otherwise, certain failures may not be detected. The ASAN error message can also be used to find the faulty transform op/pattern.

This change also fixes a few faulty transform ops.

Depends On: D147446

Diff Detail

Event Timeline

springerm created this revision.Apr 3 2023, 8:32 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 3 2023, 8:32 AM
springerm requested review of this revision.Apr 3 2023, 8:32 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 3 2023, 8:32 AM
nicolasvasilache accepted this revision.Apr 3 2023, 9:10 AM
nicolasvasilache added inline comments.
mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
691

spew

This revision is now accepted and ready to land.Apr 3 2023, 9:10 AM
ftynse added inline comments.Apr 5 2023, 1:29 AM
mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
580

This should be LLVM_ENABLE_ABI_BREAKING_CHECKS because it changes the size of the object.

mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
750

Nit: if only the second part is needed, use llvm::make_second_range. This will also allow auto to be expanded for better readabiltiy.

751

Avoid shadowing iterator names, this is terrible for readability and may backfire if the loop is no longer a range-for.

793

Can we have something similar for values? Consuming an op also consumes values defined by this op (op results or block arguments).

869

Nit: can we factor this loop out into a function so the parent function doesn't get excessively long?

871–874

Same as above (make_second_range and not reusing it for two loops).

887–892

This looks similar to forgetMapping, can we refactor/reuse that somehow. Specifically, this creates a situation where a handle can be associated with zero payload operations, which usually results in the handle being dropped completely, but not here. Some refactoring is likely necessary because we cannot drop the handle from the direct mapping without invalidating the iterator used in the outer loop.

892

On a second thought, it looks reasonable to keep those handles so we report a nice diagnostic about using an invalidated handle instead of asserting on "unknown handle". (And we should update the other place not to assert.) However, let's have some more explanation as to why this doesn't interfere with the other expensive check: handle invalidation happens before this and keeps track of invalidated handles with pregenerated error messages, so we don't need the association to still be there when the invalidated handle is accessed.

901–905

I'm hesitating about making these definite errors instead. This can happen in "syntactically valid but semantically invalid" transform IR that we get from the user and have no other way of checking for validity, so not crashing sounds preferable. However, we will still crash in the dangling-pointer case and there is no workaround for that.

springerm marked 10 inline comments as done.Apr 11 2023, 11:44 PM
springerm added inline comments.
mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
793

I'm going to do that as part of a second revision that adds the same "expensive check" for OpResults. I think we need a second cachedNames.

869

I'd prefer to keep it here because consumedPayloadOps is also defined in this function. Otherwise, I have to add another field to TransformState (or pass additional parameters around).

892

Using forgetHandle actually cleans up the code quite a bit.

This revision was automatically updated to reflect the committed changes.
springerm marked 3 inline comments as done.