This revision updates the llvm dialect inliner to explicitly disallow
the inlining of variadic functions. Already previously the inlining
failed if the number of function arguments did not match the number of
call arguments. After the change, inlining checks the function is not
variadic and it does not contain a va_start intrinsic.
This revision changes the alloca handling in the LLVM inliner.
It ensures that alloca operations, even those nested within a
region operation, can be relocated to the entry block of the function,
or the closest ancestor region that is marked with either the
isolated from above or automatic allocation scope trait.
While the LLVM dialect does not have any region operations,
the inlining interface may be used on IR that mixes different
dialects.
The disallowlist was used as a migration strategy while support was
extended to more side effecting operations. We now (to the best of our
knowledge) support all side effecting operations, so never fail
`isLegalToInline` on any LLVM operation.
There is no test included, because that's exactly the reason for this
change: there are no more unsupported operations in inlining; the
existing tests for unsupported inlines have already been burninated.
MLIR can't really be const-correct (it would need a `ConstValue` class
alongside the `Value` class really, like `ArrayRef` and
`MutableArrayRef`). This is however making is more consistent: method
that are directly modifying the Value shouldn't be marked const.
The revision adds the dbg label intrinsic to the allow list of
operations that are legal to inline.
Reviewed By: zero9178
Differential Revision: https://reviews.llvm.org/D159359
Currently, inlining a function with a `noalias` parameter leads to a large loss of optimization potential as the `noalias` parameter, an important hint for alias analysis, is lost completely.
This patch fixes this with the same approach as LLVM by annotating all users of the `noalias` parameter with appropriate alias and noalias scope lists.
The implementation done here is not as sophisticated as LLVMs, which has more infrastructure related to escaping and captured pointers, but should work in the majority of important cases.
Any deficiency can be addressed in future patches.
Related LLVM code: 27ade4b554/llvm/lib/Transforms/Utils/InlineFunction.cpp (L1090)
Differential Revision: https://reviews.llvm.org/D155712
Handling access groups is luckily rather trivial: Any access groups from the call instruction are simply appended to any memory operations.
This is similar to one of the steps when handling alias scopes.
This patch nevertheless implements it as a separate function purely for readability purposes as it uses a different interface than alias scopes.
Differential Revision: https://reviews.llvm.org/D155795
Currently when inlining, any alias scope information previously attached to the call op is lost. This leads to a loss of information that could be used by alias analysis to determine that two memory access operations do not alias.
This patch fixes this issue by also taking any alias scopes of the call operation into account. These can then simply be appended onto any inlined operations.
This is analogous to the following code in LLVM: 1768c4597e/llvm/lib/Transforms/Utils/InlineFunction.cpp (L940)
Differential Revision: https://reviews.llvm.org/D155595
This is the first and most basic and important step for inlining memory operations with alias scopes.
For correctness, it is required that any alias scopes of inlined operations are replaced with deep copies. This is necessary as otherwise the same function could be inlined twice in one function, and suddenly the alias scopes extended.
A simple example would be `foo(a, b); foo(a2, b2)`. `a` and `a2` may alias. If `foo` is inlined in both instances, the store and load operations from `foo` may suddenly claim that `a` and `a2` do not alias if we were to keep the original alias scopes.
This is analogous to the following class/code in LLVM: 4eef2e30d6/llvm/lib/Transforms/Utils/InlineFunction.cpp (L985)
Differential Revision: https://reviews.llvm.org/D155479
This commit changes intrinsics that have immarg parameter attributes to
model these parameters as attributes, instead of operands. Using
operands only works if the operation is an `llvm.mlir.constant`,
otherwise the exported LLVMIR is invalid.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D151692
This operation is not marked pure because it needs to survive DCE, but
is otherwise safe to inline.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D151070
We can not yet generate new aliasing metadata based on these arguments
because their global nature does not allow parallel inlining, but since
this is not necessary for correctness, we allow inlining functions that
have arguments with the noalias attribute for now.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D151067
The MLIR classes Type/Attribute/Operation/Op/Value support
cast/dyn_cast/isa/dyn_cast_or_null functionality through llvm's doCast
functionality in addition to defining methods with the same name.
This change begins the migration of uses of the method to the
corresponding function call as has been decided as more consistent.
Note that there still exist classes that only define methods directly,
such as AffineExpr, and this does not include work currently to support
a functional cast/isa call.
Context:
* https://mlir.llvm.org/deprecation/ at "Use the free function variants for dyn_cast/cast/isa/…"
* Original discussion at https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443
Implementation:
This follows a previous patch that updated calls
`op.cast<T>()-> cast<T>(op)`. However some cases could not handle an
unprefixed `cast` call due to occurrences of variables named cast, or
occurring inside of class definitions which would resolve to the method.
All C++ files that did not work automatically with `cast<T>()` are
updated here to `llvm::cast` and similar with the intention that they
can be easily updated after the methods are removed through a
find-replace.
See https://github.com/llvm/llvm-project/compare/main...tpopp:llvm-project:tidy-cast-check
for the clang-tidy check that is used and then update printed
occurrences of the function to include `llvm::` before.
One can then run the following:
```
ninja -C $BUILD_DIR clang-tidy
run-clang-tidy -clang-tidy-binary=$BUILD_DIR/bin/clang-tidy -checks='-*,misc-cast-functions'\
-export-fixes /tmp/cast/casts.yaml mlir/*\
-header-filter=mlir/ -fix
rm -rf $BUILD_DIR/tools/mlir/**/*.inc
```
Differential Revision: https://reviews.llvm.org/D150348
These don't require any special handling, apart checking for unsupported
metadata, which is already implemented.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D150255
When the natural stack alignment is not set or is larger than or equal
to the target alignment required by a read-only byval argument defined
by an alloca, avoid the copy by just realigning the alloca to the target
alignment.
The code to check existing alignment is reorganized a bit to avoid
redundant casts.
This also includes a bugfix for passing a null DataLayoutInterface to
the DataLayout constructor when no parent op defines
DataLayoutInterface, and will now pass ModuleOp instead in this case.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D148557
Support LLVM::StackSaveOp and LLVM::StackRestoreOp in the LLVM dialect
inliner in MLIR.
Inserts new LLVM::StackSaveOp and LLVM::StackRestoreOp intrinsics when
dynamic allocas are detected in the inlined blocks. This may result in
multiple saves/restores in the same block if some are already present in
the caller, which is legal IR, but is cleaned up in LLVM. There is not
yet a canonicalization pattern for this on LLVM dialect in MLIR.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D148011
The revision ensures the newly introduced argument
and result handlers cannot be used for type conversion.
Instead use the existing materializeCallConversion hook to
perform type conversions.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D147605
These operations do not on their own require special handling to be
inlined, and can just be inlined as is.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D147148
This is a subset of the full LLVM functionality to detect whether
realignment is necessary, conservatively copying byval arguments
whenever we cannot prove that the alignment requirement is met.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D147049
Use a disallowlist approach to deselect attributes on arguments and
return values that are not yet supported, but allow the rest to be
present when inlining.
To achieve fast lookup in `isLegalToInline`, the set of unsupported
function attributes is cached on the inliner interface object during
construction. By using a set of StringAttrs this should just amount to a
pointer lookup.
Depends on D146633
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D146729
This revealed a test case that wasn't hitting the intended branch
because the inlinees had no function definition.
Depends on D146628
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D146633
A fully fledged LLVM inliner will require a lot of logic. Since
`LLVMDialect.cpp` is large enough as it is, preemptively outline the
inlining logic into a separate `.cpp` file. This will also allow us to
add a `DEBUG_TYPE` for debugging the inliner.
The name `LLVMInlining` was chosen over `LLVMInlinerInterface` to keep
the option open for exposing inlining functionality even when not
invoked through the `DialectInlinerInterface`.
Depends on D146616
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D146628