Skip to content

[mlir][NFC] Simplify constant checks with isOneInteger and renamed isZeroInteger. #139340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions mlir/include/mlir/Dialect/Utils/StaticValueUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

namespace mlir {

/// Return true if `v` is an IntegerAttr with value `0` of a ConstantIndexOp
/// with attribute with value `0`.
bool isZeroIndex(OpFoldResult v);
/// Return true if `v` is an IntegerAttr with value `0`.
bool isZeroInteger(OpFoldResult v);

/// Return true if `v` is an IntegerAttr with value `1`.
bool isOneInteger(OpFoldResult v);

/// Represents a range (offset, size, and stride) where each element of the
/// triple may be dynamic or static.
Expand Down
2 changes: 1 addition & 1 deletion mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ LogicalResult ReinterpretCastPattern::matchAndRewrite(
OpFoldResult offset =
getMixedValues(adaptor.getStaticOffsets(), adaptor.getOffsets(), rewriter)
.front();
if (isConstantIntValue(offset, 0)) {
if (isZeroInteger(offset)) {
rewriter.replaceOp(op, src);
return success();
}
Expand Down
3 changes: 1 addition & 2 deletions mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4488,8 +4488,7 @@ static LogicalResult commonVerifierPackAndUnPackOp(OpTy packOrUnPack) {

// Return true if we have a zero-value tile.
auto hasZeros = [&](ArrayRef<OpFoldResult> tiles) {
return llvm::any_of(
tiles, [](OpFoldResult tile) { return isConstantIntValue(tile, 0); });
return llvm::any_of(tiles, isZeroInteger);
};

// Verify tiles. Do not allow zero tiles.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3401,10 +3401,7 @@ static scf::ForallOp normalizeForallLoopOp(RewriterBase &rewriter,
SmallVector<OpFoldResult> ubs = loop.getMixedUpperBound();
SmallVector<OpFoldResult> steps = loop.getMixedStep();

if (llvm::all_of(
lbs, [](OpFoldResult ofr) { return isConstantIntValue(ofr, 0); }) &&
llvm::all_of(
steps, [](OpFoldResult ofr) { return isConstantIntValue(ofr, 1); })) {
if (llvm::all_of(lbs, isZeroInteger) && llvm::all_of(steps, isOneInteger)) {
return loop;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ mlir::linalg::rewriteInDestinationPassingStyle(RewriterBase &rewriter,
// If the `padOp` has a nofold attribute and all paddings are known to be 0,
// explicitly insert a `linalg.copy`.
if (padOp.getNofoldAttr() &&
llvm::all_of(padOp.getMixedLowPad(), isZeroIndex) &&
llvm::all_of(padOp.getMixedHighPad(), isZeroIndex)) {
llvm::all_of(padOp.getMixedLowPad(), isZeroInteger) &&
llvm::all_of(padOp.getMixedHighPad(), isZeroInteger)) {
using bufferization::AllocTensorOp;
Value allocated =
rewriter.create<AllocTensorOp>(loc, resultType, dynamicSizes);
Expand Down
9 changes: 5 additions & 4 deletions mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Utils/IndexingUtils.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/BuiltinOps.h"
Expand Down Expand Up @@ -376,13 +377,13 @@ static void calculateTileOffsetsAndSizes(

SmallVector<Value> threadIds = forallOp.getInductionVars();
SmallVector<OpFoldResult> nonZeroNumThreads = llvm::filter_to_vector(
numThreads, [](OpFoldResult ofr) { return !isConstantIntValue(ofr, 0); });
numThreads, [](OpFoldResult ofr) { return !isZeroInteger(ofr); });
int64_t nLoops = loopRanges.size();
tiledOffsets.reserve(nLoops);
tiledSizes.reserve(nLoops);
for (unsigned loopIdx = 0, threadIdIdx = 0; loopIdx < nLoops; ++loopIdx) {
bool overflow = loopIdx >= numThreads.size();
bool isZero = !overflow && isConstantIntValue(numThreads[loopIdx], 0);
bool isZero = !overflow && isZeroInteger(numThreads[loopIdx]);
// Degenerate case: take the whole domain.
if (overflow || isZero) {
tiledOffsets.push_back(loopRanges[loopIdx].offset);
Expand Down Expand Up @@ -413,7 +414,7 @@ static void calculateTileOffsetsAndSizes(
OpFoldResult residualTileSize = makeComposedFoldedAffineApply(
b, loc, i + j * m - n,
{offset, nonZeroNumThreads[threadIdIdx], tileSizePerThread, size});
if (!isConstantIntValue(residualTileSize, 0)) {
if (!isZeroInteger(residualTileSize)) {
OpFoldResult sizeMinusOffsetPerThread = makeComposedFoldedAffineApply(
b, loc, -i + m, {offsetPerThread, size});
tileSizePerThread =
Expand Down Expand Up @@ -655,7 +656,7 @@ FailureOr<linalg::ForallReductionTilingResult> linalg::tileReductionUsingForall(
Operation *tiledOp = nullptr;

SmallVector<OpFoldResult> nonZeroNumThreads = llvm::filter_to_vector(
numThreads, [](OpFoldResult ofr) { return !isConstantIntValue(ofr, 0); });
numThreads, [](OpFoldResult ofr) { return !isZeroInteger(ofr); });
SmallVector<Value> materializedNonZeroNumThreads =
getValueOrCreateConstantIndexOp(b, loc, nonZeroNumThreads);

Expand Down
4 changes: 2 additions & 2 deletions mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ struct LinalgOpPartialReductionInterface

SmallVector<OpFoldResult> tiledShape;
for (auto [tileSize, dimSize] : llvm::zip_equal(sizes, shape)) {
if (isZeroIndex(tileSize)) {
if (isZeroInteger(tileSize)) {
tiledShape.push_back(dimSize);
} else {
tiledShape.push_back(tileSize);
Expand Down Expand Up @@ -732,7 +732,7 @@ struct PackOpTiling
// iterated or inner dims are not tiled. Otherwise, it will generate a
// sequence of non-trivial ops (for partial tiles).
for (auto offset : offsets.take_back(numTiles))
if (!isConstantIntValue(offset, 0))
if (!isZeroInteger(offset))
return failure();

for (auto iter :
Expand Down
8 changes: 4 additions & 4 deletions mlir/lib/Dialect/Linalg/Utils/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct TileCheck : public AffineExprVisitor<TileCheck> {
TileCheck(ArrayRef<OpFoldResult> tileSizes) : tileSizes(tileSizes) {}

void visitDimExpr(AffineDimExpr expr) {
isTiled |= !isZeroIndex(tileSizes[expr.getPosition()]);
isTiled |= !isZeroInteger(tileSizes[expr.getPosition()]);
}
void visitAffineBinaryOpExpr(AffineBinaryOpExpr expr) {
visit(expr.getLHS());
Expand Down Expand Up @@ -741,7 +741,7 @@ SmallVector<OpFoldResult> computeTileOffsets(OpBuilder &b, Location loc,
SmallVector<OpFoldResult> offsets;
for (unsigned idx = 0, idxIvs = 0, e = tileSizes.size(); idx < e; ++idx) {
LLVM_DEBUG(llvm::dbgs() << "makeTiledShapes: for loop#" << idx << "\n");
bool isTiled = !isZeroIndex(tileSizes[idx]);
bool isTiled = !isZeroInteger(tileSizes[idx]);
offsets.push_back(isTiled ? ivs[idxIvs++] : b.getIndexAttr(0));
LLVM_DEBUG(llvm::dbgs()
<< "computeTileOffsets: " << offsets.back() << "\n");
Expand All @@ -754,7 +754,7 @@ SmallVector<OpFoldResult> computeTileSizes(OpBuilder &b, Location loc,
ArrayRef<OpFoldResult> sizeBounds) {
SmallVector<OpFoldResult> sizes;
for (unsigned idx = 0, e = tileSizes.size(); idx < e; ++idx) {
bool isTiled = !isZeroIndex(tileSizes[idx]);
bool isTiled = !isZeroInteger(tileSizes[idx]);
// Before composing, we need to make range a closed interval.
OpFoldResult size = isTiled ? tileSizes[idx] : sizeBounds[idx];
AffineExpr d0 = getAffineDimExpr(0, b.getContext());
Expand Down Expand Up @@ -810,7 +810,7 @@ computeAllSliceParameters(OpBuilder &builder, Location loc, LinalgOp linalgOp,
bool omitPartialTileCheck) {
assert(ivs.size() == static_cast<size_t>(llvm::count_if(
llvm::make_range(tileSizes.begin(), tileSizes.end()),
[](OpFoldResult v) { return !isZeroIndex(v); })) &&
[](OpFoldResult v) { return !isZeroInteger(v); })) &&
"expected as many ivs as non-zero sizes");

// Construct (potentially temporary) mins and maxes on which to apply maps
Expand Down
10 changes: 3 additions & 7 deletions mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,9 +1894,7 @@ OpFoldResult ReinterpretCastOp::fold(FoldAdaptor /*operands*/) {
// reinterpret_cast(subview(x)) -> reinterpret_cast(x) if subview offsets
// are 0.
if (auto prev = src.getDefiningOp<SubViewOp>())
if (llvm::all_of(prev.getMixedOffsets(), [](OpFoldResult val) {
return isConstantIntValue(val, 0);
}))
if (llvm::all_of(prev.getMixedOffsets(), isZeroInteger))
return prev.getSource();

return nullptr;
Expand Down Expand Up @@ -3290,11 +3288,9 @@ OpFoldResult SubViewOp::fold(FoldAdaptor adaptor) {
auto srcSizes = srcSubview.getMixedSizes();
auto sizes = getMixedSizes();
auto offsets = getMixedOffsets();
bool allOffsetsZero = llvm::all_of(
offsets, [](OpFoldResult ofr) { return isConstantIntValue(ofr, 0); });
bool allOffsetsZero = llvm::all_of(offsets, isZeroInteger);
auto strides = getMixedStrides();
bool allStridesOne = llvm::all_of(
strides, [](OpFoldResult ofr) { return isConstantIntValue(ofr, 1); });
bool allStridesOne = llvm::all_of(strides, isOneInteger);
bool allSizesSame = llvm::equal(sizes, srcSizes);
if (allOffsetsZero && allStridesOne && allSizesSame &&
resultMemrefType == sourceMemrefType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,7 @@ struct LoadStoreLikeOpRewriter : public OpRewritePattern<LoadStoreLikeOp> {
// to do.
SmallVector<OpFoldResult> indices =
getAsOpFoldResult(loadStoreLikeOp.getIndices());
if (llvm::all_of(indices, [](const OpFoldResult &opFold) {
return isConstantIntValue(opFold, 0);
})) {
if (llvm::all_of(indices, isZeroInteger)) {
return rewriter.notifyMatchFailure(
loadStoreLikeOp, "no computation to extract: offsets are 0s");
}
Expand Down
24 changes: 10 additions & 14 deletions mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ getUserTileSizesAndNumThreads(RewriterBase &rewriter, TilingInterface op,
tileSizes.resize(numLoops, zero);
for (auto [index, range, nt] :
llvm::enumerate(iterationDomain, numThreads)) {
if (isConstantIntValue(nt, 0))
if (isZeroInteger(nt))
continue;

tileSizes[index] = affine::makeComposedFoldedAffineApply(
Expand Down Expand Up @@ -265,7 +265,7 @@ getTileOffsetAndSizes(RewriterBase &rewriter, Location loc, ValueRange ivs,

// Non-tiled cases, set the offset and size to the
// `loopRange.offset/size`.
if (isConstantIntValue(nt, 0)) {
if (isZeroInteger(nt)) {
offsets.push_back(loopRange.offset);
sizes.push_back(loopRange.size);
continue;
Expand All @@ -280,7 +280,7 @@ getTileOffsetAndSizes(RewriterBase &rewriter, Location loc, ValueRange ivs,
{loopRange.offset, nt, tileSize, loopRange.size});

OpFoldResult size = tileSize;
if (!isConstantIntValue(residualTileSize, 0)) {
if (!isZeroInteger(residualTileSize)) {
OpFoldResult sizeMinusOffsetPerThread =
affine::makeComposedFoldedAffineApply(rewriter, loc, s0 - d0,
{offset, loopRange.size});
Expand Down Expand Up @@ -316,7 +316,7 @@ getTileOffsetAndSizes(RewriterBase &rewriter, Location loc, ValueRange ivs,

// Non-tiled cases, set the offset and size to the
// `loopRange.offset/size`.
if (isConstantIntValue(tileSize, 0)) {
if (isZeroInteger(tileSize)) {
offsets.push_back(loopRange.offset);
sizes.push_back(loopRange.size);
continue;
Expand All @@ -341,7 +341,7 @@ getLoopBounds(RewriterBase &rewriter, Location loc, ArrayRef<Range> loopRanges,
SmallVector<OpFoldResult> lbs, ubs, steps;
for (auto [loopRange, tileSize] : llvm::zip_equal(loopRanges, tileSizes)) {
// No loop if the tile size is 0.
if (isConstantIntValue(tileSize, 0))
if (isZeroInteger(tileSize))
continue;
lbs.push_back(loopRange.offset);
ubs.push_back(loopRange.size);
Expand Down Expand Up @@ -495,7 +495,7 @@ static LogicalResult generateLoopNestUsingForallOp(
// Prune the zero numthreads.
SmallVector<OpFoldResult> nonZeroNumThreads;
for (auto nt : numThreads) {
if (isConstantIntValue(nt, 0))
if (isZeroInteger(nt))
continue;
nonZeroNumThreads.push_back(nt);
}
Expand Down Expand Up @@ -551,7 +551,7 @@ static LogicalResult generateLoopNest(
YieldTiledValuesFn tiledBodyFn, SmallVector<LoopLikeOpInterface> &loops) {
// If the tile sizes are all zero, no loops are generated. Just call the
// callback function to handle untiled case.
if (llvm::all_of(tileSizes, isZeroIndex)) {
if (llvm::all_of(tileSizes, isZeroInteger)) {
SmallVector<Value> tiledResults;
SmallVector<SmallVector<OpFoldResult>> resultOffsets, resultSizes;
return tiledBodyFn(rewriter, loc, ValueRange{}, destinationTensors,
Expand Down Expand Up @@ -999,7 +999,7 @@ mlir::scf::tileUsingSCF(RewriterBase &rewriter, TilingInterface op,
// 5b. Early return cloned op if tiling is not happening. We can not
// return the original op because it could lead to `rewriter.replaceOp(op,
// op->getResults())` and users would get crash.
if (llvm::all_of(tileSizes, isZeroIndex)) {
if (llvm::all_of(tileSizes, isZeroInteger)) {
tiledResults.append(clonedOp->result_begin(), clonedOp->result_end());
tilingResult =
TilingResult{/*tiledOps=*/{clonedOp}, clonedOp->getResults(),
Expand Down Expand Up @@ -1290,9 +1290,7 @@ FailureOr<SmallVector<Operation *>> mlir::scf::yieldReplacementForFusedProducer(
sliceSizes = sliceOp.getMixedSizes();

// expect all strides of sliceOp being 1
if (llvm::any_of(sliceOp.getMixedStrides(), [](OpFoldResult ofr) {
return !isConstantIntValue(ofr, 1);
}))
if (!llvm::all_of(sliceOp.getMixedStrides(), isOneInteger))
return failure();

unsigned sliceResultNumber =
Expand Down Expand Up @@ -2114,9 +2112,7 @@ mlir::scf::tileAndFuseConsumerOfSlice(
SmallVector<OpFoldResult> strides = ossSliceOp.getMixedStrides();

// 9. Check all insert stride is 1.
if (llvm::any_of(strides, [](OpFoldResult stride) {
return !isConstantIntValue(stride, 1);
})) {
if (!llvm::all_of(strides, isOneInteger)) {
return rewriter.notifyMatchFailure(
candidateSliceOp, "containingOp's result yield with stride");
}
Expand Down
6 changes: 3 additions & 3 deletions mlir/lib/Dialect/SCF/Utils/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ static void denormalizeInductionVariableForIndexType(RewriterBase &rewriter,
// If an `affine.apply` operation is generated for denormalization, the use
// of `origLb` in those ops must not be replaced. These arent not generated
// when `origLb == 0` and `origStep == 1`.
if (!isConstantIntValue(origLb, 0) || !isConstantIntValue(origStep, 1)) {
if (!isZeroInteger(origLb) || !isOneInteger(origStep)) {
if (Operation *preservedUse = denormalizedIvVal.getDefiningOp()) {
preservedUses.insert(preservedUse);
}
Expand All @@ -785,8 +785,8 @@ void mlir::denormalizeInductionVariable(RewriterBase &rewriter, Location loc,
}
Value denormalizedIv;
SmallPtrSet<Operation *, 2> preserve;
bool isStepOne = isConstantIntValue(origStep, 1);
bool isZeroBased = isConstantIntValue(origLb, 0);
bool isStepOne = isOneInteger(origStep);
bool isZeroBased = isZeroInteger(origLb);

Value scaled = normalizedIv;
if (!isStepOne) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ struct ForOpRewriter : public OpRewritePattern<scf::ForOp> {
// Check for single block, unit-stride for-loop that is generated by
// sparsifier, which means no data dependence analysis is required,
// and its loop-body is very restricted in form.
if (!op.getRegion().hasOneBlock() || !isConstantIntValue(op.getStep(), 1) ||
if (!op.getRegion().hasOneBlock() || !isOneInteger(op.getStep()) ||
!op->hasAttr(LoopEmitter::getLoopEmitterLoopAttrName()))
return failure();
// Analyze (!codegen) and rewrite (codegen) loop-body.
Expand Down
3 changes: 1 addition & 2 deletions mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2839,8 +2839,7 @@ OpFoldResult InsertSliceOp::fold(FoldAdaptor) {
return getResult();
if (auto result = foldInsertAfterExtractSlice(*this))
return result;
if (llvm::any_of(getMixedSizes(),
[](OpFoldResult ofr) { return isConstantIntValue(ofr, 0); }))
if (llvm::any_of(getMixedSizes(), isZeroInteger))
return getDest();
return OpFoldResult();
}
Expand Down
6 changes: 3 additions & 3 deletions mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ FailureOr<TilingResult> tensor::bubbleUpPadSlice(OpBuilder &b,
SmallVector<OpFoldResult> newStrides(rank, b.getIndexAttr(1));
for (unsigned dim = 0; dim < rank; ++dim) {
auto low = padOp.getMixedLowPad()[dim];
bool hasLowPad = !isConstantIntValue(low, 0);
bool hasLowPad = !isZeroInteger(low);
auto high = padOp.getMixedHighPad()[dim];
bool hasHighPad = !isConstantIntValue(high, 0);
bool hasHighPad = !isZeroInteger(high);
auto offset = offsets[dim];
auto length = sizes[dim];
// If the dim has no padding, we dont need to calculate new values for that
Expand Down Expand Up @@ -208,7 +208,7 @@ FailureOr<TilingResult> tensor::bubbleUpPadSlice(OpBuilder &b,

// Check if newLength is zero. In that case, no SubTensorOp should be
// executed.
if (isConstantIntValue(newLength, 0)) {
if (isZeroInteger(newLength)) {
hasZeroLen = true;
} else if (!hasZeroLen) {
Value check = b.create<arith::CmpIOp>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ static bool insertSliceOpRequiresRead(InsertOpTy insertSliceOp,
// Dest is not read if it is entirely overwritten. E.g.:
// tensor.insert_slice %a into %t[0][10][1] : ... into tensor<10xf32>
bool allOffsetsZero =
llvm::all_of(insertSliceOp.getMixedOffsets(), isZeroIndex);
llvm::all_of(insertSliceOp.getMixedOffsets(), isZeroInteger);
RankedTensorType destType = insertSliceOp.getDestType();
bool sizesMatchDestSizes =
areConstantIntValues(insertSliceOp.getMixedSizes(), destType.getShape());
Expand Down
4 changes: 2 additions & 2 deletions mlir/lib/Dialect/Tensor/Transforms/ReshapePatterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ struct BubbleUpExpandShapeThroughExtractSlice
std::function<bool(OpFoldResult, OpFoldResult, OpFoldResult)>
isZeroOffsetAndFullSize =
[](OpFoldResult offset, OpFoldResult sliceSize, OpFoldResult size) {
if (!isConstantIntValue(offset, 0))
if (!isZeroInteger(offset))
return false;
FailureOr<bool> maybeEqual =
ValueBoundsConstraintSet::areEqual(sliceSize, size);
Expand All @@ -476,7 +476,7 @@ struct BubbleUpExpandShapeThroughExtractSlice
// Find the first expanded dim after the first dim with non-unit extracted
// size.
for (; i < e; ++i) {
if (!isConstantIntValue(sizes[indices[i]], 1)) {
if (!isOneInteger(sizes[indices[i]])) {
// +1 to skip the first non-unit size dim.
i++;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ FailureOr<TilingResult> tensor::replaceExtractSliceWithTiledProducer(
return failure();

// `TilingInterface` currently only supports strides being 1.
if (llvm::any_of(sliceOp.getMixedStrides(), [](OpFoldResult ofr) {
return !isConstantIntValue(ofr, 1);
}))
if (!llvm::all_of(sliceOp.getMixedStrides(), isOneInteger))
return failure();

FailureOr<TilingResult> tiledResult = producerOp.generateResultTileValue(
Expand All @@ -49,9 +47,7 @@ FailureOr<TilingResult> tensor::replaceInsertSliceWithTiledConsumer(
return failure();

// `TilingInterface` currently only supports strides being 1.
if (llvm::any_of(sliceOp.getMixedStrides(), [](OpFoldResult ofr) {
return !isConstantIntValue(ofr, 1);
}))
if (!llvm::all_of(sliceOp.getMixedStrides(), isOneInteger))
return failure();

FailureOr<TilingResult> tiledResult =
Expand Down
Loading