[Mlir-commits] [mlir] [mlir][vector] Add mask elimination transform (PR #99314)
Benjamin Maxwell
llvmlistbot at llvm.org
Fri Aug 2 14:11:09 PDT 2024
MacDue wrote:
> Does it make more sense now or am I missing something?
I think you are misunderstanding how this patch works. There are no lightweight canonicalizations added here (or any patterns really). Such lightweight canonicalizations already exist, and this code does not re-implement them, I was simply saying this code follows a similar idea.
Let's look at the actual code here:
```c++
// Check for any dims that could be (partially) false before doing the more
// expensive value bounds computations.
SmallVector<UnknownMaskDim> unknownDims;
for (auto [i, dimSize] : llvm::enumerate(createMaskOp.getOperands())) {
if (auto intSize = getConstantIntValue(dimSize)) {
// Mask not all-true for this dim.
if (maskTypeDimScalableFlags[i] || intSize < maskTypeDimSizes[i])
return failure();
} else if (auto vscaleMultiplier = getConstantVscaleMultiplier(dimSize)) {
// Mask not all-true for this dim.
if (vscaleMultiplier < maskTypeDimSizes[i])
return failure();
} else {
// Unknown (without further analysis).
unknownDims.push_back(UnknownMaskDim{i, dimSize});
}
}
```
This is the part likened to canonicalization, but it's not a canonicalization. It's looking at all the operations of the `create_mask` and finding the unknown dimensions. Those are the dimensions that need to be solved via value-bounds analysis. The trick here is if any dimension is constant and not all-true, then we can exit early as that means the mask won't be all-true.
This prevents us from pointlessly doing value-bounds analysis is in cases like:
```mlir
%mask = vector.create_mask %dynamicValue, %c2 : vector<8x4xi1>
```
>From looking at `%c2` we can tell this is not going to be an all-true mask, so we don't need to run the value-bounds analysis for
`%dynamicValue` (and will exit the transform early). Note that this `create_mask` still is not a `constant_mask` or an all-true/false mask, so no canonicalization will remove it before the "heavyweight" mask removal.
After that we go over the unknown dimensions and solve for them using value-bounds:
```c++
for (auto [i, dimSize] : unknownDims) {
// Compute the lower bound for the unknown dimension (i.e. the smallest
// value it could be).
FailureOr<ConstantOrScalableBound> dimLowerBound =
vector::ScalableValueBoundsConstraintSet::computeScalableBound(
dimSize, {}, vscaleRange.vscaleMin, vscaleRange.vscaleMax,
presburger::BoundType::LB);
if (failed(dimLowerBound))
return failure();
auto dimLowerBoundSize = dimLowerBound->getSize();
if (failed(dimLowerBoundSize))
return failure();
if (dimLowerBoundSize->scalable) {
// If the lower bound is scalable and < the mask dim size then this dim is
// not all-true.
if (dimLowerBoundSize->baseSize < maskTypeDimSizes[i])
return failure();
} else {
// If the lower bound is a constant:
// - If the mask dim size is scalable then this dim is not all-true.
if (maskTypeDimScalableFlags[i])
return failure();
// - If the lower bound is < the _fixed-size_ mask dim size then this dim
// is not all-true.
if (dimLowerBoundSize->baseSize < maskTypeDimSizes[i])
return failure();
}
}
```
The TLDR is this is just the "heavyweight" mask removal with a check to avoid doing pointless work.
https://github.com/llvm/llvm-project/pull/99314
More information about the Mlir-commits
mailing list