This fixes the following failure when doing a clean build (in particular
no .ninja* lying around) of lib/libMLIRMemRefToLLVM.a only:
```
In file included from mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp:18:
mlir/include/mlir/Dialect/Func/IR/FuncOps.h:29:10: fatal error: mlir/Dialect/Func/IR/FuncOps.h.inc: No such file or directory
```
Add missing constant propogation folder for spirv.Select
Implement additional folding when both selections are equivalent or the
condition is a constant Scalar/SplatVector.
Allows for constant folding in the IndexToSPIRV pass.
Part of work #70704
This patch updates `LowerContractionToSMMLAPattern` to unroll larger vector contracts into multiple smmla instructions.
Now accepts up to [8,8,8] tiles (previously only [2,2,8]). The N/M dimensions must be powers of 2. `vector.extract_strided_slice`/`vector.insert_strided_slice` divides the contract into tiles to be processed in a row.
This commit ensures that SROA does no longer attempt to split allocas
that are indexed into dynamically. Dynamic indices into arrays are
allowed to be negative or out-of-bounds, when the alloca containing the
array has memory backing these produced indices.
Currently, `simplifyMul()` asserts that either `lhs` or `rhs` is
symbolic or constant. This method is called by the overloaded `*`
operator for `AffineExpr`s which leads to a crash when building a
multiplication expression where neither operand is symbolic or constant.
This patch returns a `nullptr` from `simplifyMul()` to signal that the
expression could not be simplified instead.
Fix https://github.com/llvm/llvm-project/issues/75770
This doesn't change functionality, but lets us avoid attaching all the
interfaces after 513cdb82223a106f183b49a40d9acb1f7efbbe7e turned casting
without loading into an error.
Reland #82363 after fixing build failure
https://lab.llvm.org/buildbot/#/builders/5/builds/41428.
Memory sanitizer detects usage of `RawData` union member which is not
filled directly. Instead, the code relies on filling `Data` union
member, which is a struct consisting of signing schema parameters.
According to https://en.cppreference.com/w/cpp/language/union, this is
UB:
"It is undefined behavior to read from the member of the union that
wasn't most recently written".
Instead of relying on compiler allowing us to do dirty things, do not
use union and only store `RawData`. Particular ptrauth parameters are
obtained on demand via bit operations.
Original PR description below.
Emit `__ptrauth`-qualified types as `DIDerivedType` metadata nodes in IR
with tag `DW_TAG_LLVM_ptrauth_type`, baseType referring to the type
which has the qualifier applied, and the following parameters
representing the signing schema:
- `ptrAuthKey` (integer)
- `ptrAuthIsAddressDiscriminated` (boolean)
- `ptrAuthExtraDiscriminator` (integer)
- `ptrAuthIsaPointer` (boolean)
- `ptrAuthAuthenticatesNullValues` (boolean)
Co-authored-by: Ahmed Bougacha <ahmed@bougacha.org>
Last resort resolution of cycles introduced a sparse conversion without
explicit sparse deallocation (which is not inserted by any automatic
means). This fixes 2 out of 5 remaining asan detected leaks in sparse
integration tests.
Hi @joker-eph, This PR adds XeGPU 2D block operators. It contains:
1. `TensorDescType` and `TensorDescAttr` definitions
2. `MemoryScopeAttr` and `CacheHintAttr` definitions which are used by
`TensorDescAttr`.
3. `CreateNdDescOp`, `PrefetchNdOp`, `LoadNdOp`, and `StoreNdOp`
definitions, and their corresponding testcases for illustration.
---------
Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
Emits `2.0e+00f` instead of `(float)2.0e+00`.
This helps consumers of the emitted code, especially when there are
large numbers of floating point literals, to have a simple AST.
This commit changes MLIR's SROA implementation back from being pattern
based into a full pass. This is beneficial for upcoming changes that
rely more heavily on the datalayout.
Unfortunately, this change required substantial test changes, as the
IRBuilder no cleans up the IR.
This commit changes MLIR's Mem2Reg implementation back from being
pattern based into a full pass. Using Mem2Reg as a pattern is
wasteful, as each application can invalidate the dominance info.
Applying changes in bulk allows for reuse of the same dominance info.
Unfortunately, this requires some test changes, due to the `IRBuilder`
not simplifying IR.
The previous implementation decomposes tanh(x) into
`(exp(2x) - 1)/(exp(2x)+1), x < 0`
`(1 - exp(-2x))/(1 + exp(-2x)), x >= 0`
This is fine as it avoids overflow with the exponential, but the whole
decomposition is computed for both cases unconditionally, then the
result is chosen based off the sign of the input. This results in doing
two expensive exp computations.
The proposed change avoids doing the whole computation twice by
exploiting the reflection symmetry `tanh(-x) = -tanh(x)`. We can
"normalize" the input to be positive by setting `y = sign(x) * x`, where
the sign of `x` is computed as `sign(x) = (float)(x > 0) * (-2) + 1`.
Then compute `z = tanh(y) `with the decomposition above for `x >=0` and
"denormalize" the result `z * sign(x)` to retain the sign. The reason it
is done this way is that it is very amenable to vectorization.
This method trades the duplicate decomposition computations (which takes
5 instructions including an extra expensive exp and div) for 4 cheap
instructions to compute the signs value
`arith.cmpf `(which is a pre-existing instruction in the previous impl)
`arith.sitofp`
`arith.mulf`
`arith.addf`
and 1 more instruction to get the right sign in the result
5. `arith.mulf`.
Moreover, numerically, this implementation will yield the exact same
results as the previous implementation.
As part of the relanding, a casting issue from the original commit has
been fixed, i.e. casting bool to float with `uitofp`. Additionally a
correctness test with `mlir-cpu-runner` has been added.
MSVC fails to parse this construct, leading to
MlirTranslateMain.cpp(70): error C2065: 'inputSplitMarker': undeclared identifier
Just switching to brace init works around the issue
Buffers are no longer deallocation by One-Shot Bufferize. This is now
done by a separate buffer deallocation pass.
Also fix a bug in the `vector.mask` folding, which was triggered by
`-buffer-deallocation-pipeline`, which runs the canonicalizer.
This PR adds promised interface declarations for all interfaces declared
in `InitAllDialects.h`.
Promised interfaces allow a dialect to declare that it will have an
implementation of a particular interface, crashing the program if one
isn't provided when the interface is used.
This change lifts the restriction that purely allocated empty sparse
tensors cannot escape the method. Instead it makes a best effort to add
a finalizing operation before the escape.
This assumes that
(1) we never build sparse tensors across method boundaries
(e.g. allocate in one, insert in other method)
(2) if we have other uses of the empty allocation in the
same method, we assume that either that op will fail
or will do the finalization for us.
This is best-effort, but fixes some very obvious missing cases.
This simply updates the rewrites to propagate the scalable flags (which
as they do not alter the vector shape, is pretty simple).
The added tests are simply scalable versions of the existing vector
tests.
…5025)"
This reverts commit 58ef9bec071383744fb703ff08df9806f25e4095.
There is a bool to float casting issue that needs to be sorted out to
make sure this is target independent
Following the discussion from [this
thread](https://discourse.llvm.org/t/handling-cyclic-dependencies-in-debug-info/67526/11),
this PR adds support for recursive DITypes.
This PR adds:
1. DIRecursiveTypeAttrInterface: An interface that DITypeAttrs can
implement to indicate that it supports recursion. See full description
in code.
2. Importer & exporter support (The only DITypeAttr that implements the
interface is DICompositeTypeAttr, so the exporter is only implemented
for composites too. There will be two methods that each llvm DI type
that supports mutation needs to implement since there's nothing
general).
---------
Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
Introduces a SubscriptOp that allows to write IR like
```
func.func @load_store(%arg0: !emitc.array<4x8xf32>, %arg1: !emitc.array<3x5xf32>, %arg2: index, %arg3: index) {
%0 = emitc.subscript %arg0[%arg2, %arg3] : <4x8xf32>, index, index
%1 = emitc.subscript %arg1[%arg2, %arg3] : <3x5xf32>, index, index
emitc.assign %0 : f32 to %1 : f32
return
}
```
which gets translated into the C++ code
```
v1[v2][v3] = v0[v1][v2];
```
To make this happen, this
- adds the SubscriptOp
- allows the subscript op as rhs of emitc.assign
- updates the emitter to print SubscriptOps
The emitter prints emitc.subscript in a delayed fashing to allow it
being used as lvalue.
I.e. while processing
```
%0 = emitc.subscript %arg0[%arg2, %arg3] : <4x8xf32>, index, index
```
it will not emit any text, but record in the `valueMapper` that the name
for `%0` is `v0[v1][v2]`, see `CppEmitter::getSubscriptName`. Only when
that result is then used (here in `emitc.assign`), that name is inserted
into the text.
This commit adds a new test-only op:
`sparse_tensor.has_runtime_library`. The op returns "1" if the sparse
compiler runs in runtime library mode.
This op is useful for writing test cases that require different IR
depending on whether the sparse compiler runs in runtime library or
codegen mode.
This commit fixes a memory leak in `sparse_pack_d.mlir`. This test case
uses `sparse_tensor.assemble` to create a sparse tensor SSA value from
existing buffers. This runtime library reallocates+copies the existing
buffers; the codegen path does not. Therefore, the test requires
additional deallocations when running in runtime library mode.
Alternatives considered:
- Make the codegen path allocate. "Codegen" is the "default" compilation
mode and it is handling `sparse_tensor.assemble` correctly. The issue is
with the runtime library path, which should not allocate. Therefore, it
is better to put a workaround in the runtime library path than to work
around the issue with a new flag in the codegen path.
- Add a `sparse_tensor.runtime_only` attribute to
`bufferization.dealloc_tensor`. Verifying that the attribute can only be
attached to `bufferization.dealloc_tensor` may introduce an unwanted
dependency of `MLIRSparseTensorDialect` on `MLIRBufferizationDialect`.
This commit fixes a memory leak in `sparse_codegen_foreach.mlir`. The
bufferization inserted a copy for the operand of `sparse_tensor.foreach`
because it conservatively assumed that the op writes to the operand.
The previous implementation decomposes `tanh(x)` into
`(exp(2x) - 1)/(exp(2x)+1), x < 0`
`(1 - exp(-2x))/(1 + exp(-2x)), x >= 0`
This is fine as it avoids overflow with the exponential, but the whole
decomposition is computed for both cases unconditionally, then the
result is chosen based off the sign of the input. This results in doing
two expensive `exp` computations.
The proposed change avoids doing the whole computation twice by
exploiting the reflection symmetry `tanh(-x) = -tanh(x)`. We can
"normalize" the input to be positive by setting `y = sign(x) * x`, where
the sign of `x` is computed as `sign(x) = (float)(x > 0) * (-2) + 1`.
Then compute `z = tanh(y)` with the decomposition above for `x >=0` and
"denormalize" the result `z * sign(x)` to retain the sign. The reason it
is done this way is that it is very amenable to vectorization.
This method trades the duplicate decomposition computations (which takes
5 instructions including an extra expensive `exp` and `div`) for 4 cheap
instructions to compute the signs value
1. `arith.cmpf` (which is a pre-existing instruction in the previous
impl)
2. `arith.sitofp`
3. `arith.mulf`
4. `arith.addf`
and 1 more instruction to get the right sign in the result
5. `arith.mulf`. Moreover, numerically, this implementation will yield
the exact same results as the previous implementation.
This patch adds support for masked vectorisation of depthwise 1D WC
convolutions,`linalg.depthwise_conv_1d_nwc_wc`. This is implemented by
adding support for masking.
Two major assumptions are made:
* only the channel dimension can be dynamic/scalable (i.e. the
trailing dim),
* when specifying vector sizes to use in the vectoriser, only the size
corresponding to the channel dim is effectively used (other dims are
inferred from the context).
In terms of scalable vectorisation, this should be sufficient to cover
all practical cases (i.e. making arbitrary dim scalable wouldn't make
much sense). As for more generic cases with dynamic shapes (e.g. W or N
dims being dynamic), more work would be needed. In particular, one would
have to consider the filter and input/output tensors separately.
This allows to define custom splitters, which is interesting for
non-MLIR inputs and outputs to `mlir-translate`. For example, one may
use `; -----` as a splitter of `.ll` files. The splitters are now passed
as arguments into `splitAndProcessBuffer`, the input splitter defaulting
to the previous default (`// -----`) and the output splitter defaulting
to the empty string, which also corresponds to the previous default. The
behavior of the input split marker should not change at all; however,
outputs now have one new line *more* than before if there is no splitter
(old: `insertMarkerInOutput = false`, new: `outputSplitMarker = ""`) and
one new line *less* if there is one. The value of the input splitter is
exposed as a command line options of `mlir-translate` and other tools as
an optional value to the previously existing flag `-split-input-file`,
which defaults to the default splitter if not specified; the value of
the output splitter is exposed with the new `-output-split-marker`,
which default to the empty string in `mlir-translate` and the default
splitter in the other tools. In short, the previous usage or omission of
the flags should result in previous behavior (modulo the new lines
mentioned before).
Adds a new pass option `add-result-attr` that will make the pass add the
attribute `{bufferize.result}` to each argument that was converted from
a result.
This is important e.g. when later using the python bindings / execution
engine to understand which arguments are actually results.
To be able to test this, the pass option was added to the tablegen. To
avoid collisions with the existing, manually defined option struct
`BufferResultsToOutParamsOptions`, that one was renamed to
`BufferResultsToOutParamsOpts`.
isAccessIndexInvariant had outdated code and didn't handle IR with
multiple
affine.apply ops, which is inconvenient when used as a utility. This is
addressed by switching to use the proper API on AffineValueMap. Add
mlir::affine::isInvariantAccess exposed for outside use and tested via
the test pass. Add a method on AffineValueMap. Add test cases to
exercise simplification and composition for invariant access analysis.
A TODO/FIXME has been added but this issue existed before.
Because `arith.select` does not propagate poison of the second or third
operand depending on the condition, some canonicalization patterns are
currently incorrect. This patch removes these incorrect patterns, and
adds a new pattern to fix the case of `i1` select with constants.
Patterns that are removed:
* select(predA, select(predB, x, y), y) => select(and(predA, predB), x,
y)
* select(predA, select(predB, y, x), y) => select(and(predA,
not(predB)), x, y)
* select(predA, x, select(predB, x, y)) => select(or(predA, predB), x,
y)
* select(predA, x, select(predB, y, x)) => select(or(predA, not(predB)),
x, y)
* arith.select %arg, %x, %y : i1 => and(%arg, %x) or and(!%arg, %y)
Pattern that is added:
* select(pred, false, true) => not(pred) for i1
The first two patterns are incorrect when `predB` is poison and `predA`
is false, as a non-poison `y` gets compiled to `poison`. The next two
patterns are incorrect when `predB` is poison and `predA` is true, as a
non-poison `x` gets compiled to `poison`. The last pattern is incorrect
as it propagates poison from all operands afer compilation.
Discussion at https://discourse.llvm.org/t/inliner-cost-model/2992
This change adds a callback that reports whether inlining
of the particular call site (communicated via ResolvedCall argument)
is profitable or not. The default MLIR inliner pass behavior
is unchanged, i.e. the callback always returns true.
This callback may be used to customize the inliner behavior
based on the target specifics (like target instructions costs),
profitability of the inlining for further optimizations
(e.g. if inlining may enable loop optimizations or scalar optimizations
due to object shape propagation), optimization levels (e.g. -Os inlining
may be quite different from -Ofast inlining), etc.
One of the questions is whether the ResolvedCall entity represents
enough of the context for the custom inlining models to come up with
the profitability decision. I think we can start with this and
extend it as necessary.
---------
Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
Previously reduction variables were always passed by value into and out
of the initialization and combiner regions of the OpenMP reduction
declare operation.
This worked well for reductions of primitive types (and might perform
better than passing by reference). But passing by reference will be
useful for array and derived type reductions (e.g. to move allocation
inside of the init region).
Passing reductions by reference requires different LLVM-IR generation
when lowering from MLIR because some of the loads/stores/allocations
will now be moved inside of the init and combiner regions. This
alternate code generation is requested using a new attribute to
omp.wsloop and omp.parallel.
Existing lowerings from mlir are unaffected (these will continue to use
the by-value argument passing.
Flang will continue to pass by-value argument passing for trivial types
unless a (hidden) command line argument is supplied. Non-trivial types
will always use the by-ref lowering.
Array reductions are not ready yet (but are coming very soon). In the
meantime, this is tested by forcing existing reductions to use by-ref.
Commit series for by-ref OpenMP reductions 3/3
---------
Co-authored-by: Mats Petersson <mats.petersson@arm.com>
This debug log adds noise to a large fraction of *other* debug logs when
you run with -debug, because it prints "Verifying operation: blah blah\n"
whenever those other debug logs dump an op.
You can use -debug-only to get around this, but sometimes -debug really
is what's called for!