This is an archive of the discontinued LLVM Phabricator instance.

[mlir][LLVM] Add delayed intrinsic import support
AbandonedPublic

Authored by Dinistro on Aug 8 2023, 5:14 AM.

Details

Summary

This commit introduces support for specific intrinsics imports to be
delayed after all instructions of a function were imported. This is
necesarry to import debug intrinsics correctly.

Debug intrinsics in LLVM are excluded from the define-before-use
invariant, i.e., they can reference SSA values that do not dominate
them. So far, we had implemented checks to stop the import of such
intrinsics, but there were always additional cases that were not
covered (the latest being terminators that define such used values).
To resolve this cleanly, the delayed intrinsic conversion functionality
is necessary. It allows the debug intrinsic conversion to place the
newly created MLIR operation in the correct place, while being certain
that the defining operation was already converted.

So far, this is only relevant for two LLVM debug intrinsics, that's
why the tablegen support was not added.

Diff Detail

Event Timeline

Dinistro created this revision.Aug 8 2023, 5:14 AM
Herald added a reviewer: dcaballe. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
Dinistro requested review of this revision.Aug 8 2023, 5:14 AM
zero9178 added inline comments.Aug 8 2023, 5:49 AM
mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
82

Returning ArrayRef here is imo a bit of a premature optimization where it doesn't really matter and raises a lot of questions about object lifetime. I'd prefer returning SmallVector<unsigned> to always be safe from stack-use-after-return.

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
56–58
105–111

You can improve on the logic here by not trying to manually find a block that dominates op in its successor list, but rather querying the dominator tree to give you blocks that it dominates.
Calling domInfo.getNode(op->getBlock())->children() would give you a list of all blocks immediately dominated by the op's block. You could place the intrinsic in any of these.

One thing I am curious about, is it okay to place the debug intrinsic in the exception handling block of an invoke, right before the LandingPadOp? If not, you might have to exclude these or choose a different insertion point than the start.

347
mlir/test/Target/LLVMIR/Import/debug-info.ll
417

Could we add CHECK: lines to make sure that the @llvm.dbg.value exists?

Dinistro updated this revision to Diff 548195.Aug 8 2023, 6:42 AM

address review comments and remove usage of dominance.

mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
82

I agree that this isn't great, but I followed the design of the other interface functions.
Changing all the interface member functions would require changes in all implementation of it.

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
105–111

After internal discussion, we decided to drop the potentially expensive dominance usage with a simpler check if one of the block has a unique predecessor.
This ensures that the dominance tree is no recomputed for each terminator.

Regarding the LandingPad: You are right, this is indeed invalid. We decided to now insert all the intrinsics right before the terminator of the selected block.

mlir/test/Target/LLVMIR/Import/debug-info.ll
417

Good catch, I forgot to do that as I initially used this test to check if this still causes crashes ^^

Dinistro marked 2 inline comments as done.Aug 9 2023, 5:01 AM

I've implemented a less intrusive change that is more specific to the two debug intrinsics: https://reviews.llvm.org/D157496

Dinistro abandoned this revision.Aug 9 2023, 6:08 AM

Abandoned in favor of the simpler solution.