Skip to content

[MLIR] Fix crash in AffineMap::replace for zero result maps #80930

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 1 commit into from
Feb 8, 2024
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
3 changes: 2 additions & 1 deletion mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def AffineApplyOp : Affine_Op<"apply", [Pure]> {
OpBuilder<(ins "ArrayRef<AffineExpr> ":$exprList,"ValueRange":$mapOperands),
[{
build($_builder, $_state, $_builder.getIndexType(),
AffineMap::inferFromExprList(exprList).front(), mapOperands);
AffineMap::inferFromExprList(exprList, $_builder.getContext())
.front(), mapOperands);
}]>
];

Expand Down
4 changes: 3 additions & 1 deletion mlir/include/mlir/Dialect/Utils/StructuredOpsUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ class StructuredGenerator {
}

bool layout(MapList l) {
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, ctx);
};
return maps == infer(l);
}

Expand Down
6 changes: 4 additions & 2 deletions mlir/include/mlir/IR/AffineMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ class AffineMap {
/// `exprs.size()`, as many dims as the largest dim in `exprs` and as many
/// symbols as the largest symbol in `exprs`.
static SmallVector<AffineMap, 4>
inferFromExprList(ArrayRef<ArrayRef<AffineExpr>> exprsList);
inferFromExprList(ArrayRef<ArrayRef<AffineExpr>> exprsList,
MLIRContext *context);
static SmallVector<AffineMap, 4>
inferFromExprList(ArrayRef<SmallVector<AffineExpr, 4>> exprsList);
inferFromExprList(ArrayRef<SmallVector<AffineExpr, 4>> exprsList,
MLIRContext *context);

MLIRContext *getContext() const;

Expand Down
14 changes: 9 additions & 5 deletions mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,8 @@ class ArgMaxConverter : public OpRewritePattern<tosa::ArgMaxOp> {
}

bool didEncounterError = false;
auto maps = AffineMap::inferFromExprList({srcExprs, dstExprs, dstExprs});
auto maps = AffineMap::inferFromExprList({srcExprs, dstExprs, dstExprs},
rewriter.getContext());
auto linalgOp = rewriter.create<linalg::GenericOp>(
loc, ArrayRef<Type>({resultTy, resultMaxTy}), input,
ValueRange({filledTensorIdx, filledTensorMax}), maps, iteratorTypes,
Expand Down Expand Up @@ -2351,9 +2352,11 @@ struct RFFT2dConverter final : public OpRewritePattern<RFFT2dOp> {
createZeroTensor(rewriter, loc, outputType, dynamicSizes)};

// Indexing maps for input and output tensors
auto indexingMaps = AffineMap::inferFromExprList(llvm::ArrayRef{
affineDimsExpr(rewriter, 0, 3, 4), affineDimsExpr(rewriter, 0, 1, 2),
affineDimsExpr(rewriter, 0, 1, 2)});
auto indexingMaps = AffineMap::inferFromExprList(
llvm::ArrayRef{affineDimsExpr(rewriter, 0, 3, 4),
affineDimsExpr(rewriter, 0, 1, 2),
affineDimsExpr(rewriter, 0, 1, 2)},
rewriter.getContext());

// Width and height dimensions of the original input.
auto dimH = rewriter.createOrFold<tensor::DimOp>(loc, input, 1);
Expand Down Expand Up @@ -2463,7 +2466,8 @@ struct FFT2dConverter final : OpRewritePattern<FFT2dOp> {
ArrayRef{RFFT2dConverter::affineDimsExpr(rewriter, 0, 3, 4),
RFFT2dConverter::affineDimsExpr(rewriter, 0, 3, 4),
RFFT2dConverter::affineDimsExpr(rewriter, 0, 1, 2),
RFFT2dConverter::affineDimsExpr(rewriter, 0, 1, 2)});
RFFT2dConverter::affineDimsExpr(rewriter, 0, 1, 2)},
rewriter.getContext());

// Width and height dimensions of the original input.
auto dimH = rewriter.createOrFold<tensor::DimOp>(loc, input_real, 1);
Expand Down
8 changes: 6 additions & 2 deletions mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ static void getXferIndices(RewriterBase &rewriter, TransferOpType xferOp,
static bool contractSupportsMMAMatrixType(vector::ContractionOp contract,
bool useNvGpu) {
using MapList = ArrayRef<ArrayRef<AffineExpr>>;
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, contract.getContext());
};
AffineExpr m, n, k;
bindDims(contract.getContext(), m, n, k);
auto iteratorTypes = contract.getIteratorTypes().getValue();
Expand Down Expand Up @@ -394,7 +396,9 @@ struct PrepareContractToGPUMMA

// Set up the parallel/reduction structure in right form.
using MapList = ArrayRef<ArrayRef<AffineExpr>>;
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, op.getContext());
};
AffineExpr m, n, k;
bindDims(rewriter.getContext(), m, n, k);
static constexpr std::array<int64_t, 2> perm = {1, 0};
Expand Down
8 changes: 6 additions & 2 deletions mlir/lib/Dialect/Affine/IR/AffineOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,9 @@ AffineApplyOp
mlir::affine::makeComposedAffineApply(OpBuilder &b, Location loc, AffineExpr e,
ArrayRef<OpFoldResult> operands) {
return makeComposedAffineApply(
b, loc, AffineMap::inferFromExprList(ArrayRef<AffineExpr>{e}).front(),
b, loc,
AffineMap::inferFromExprList(ArrayRef<AffineExpr>{e}, b.getContext())
.front(),
operands);
}

Expand Down Expand Up @@ -1220,7 +1222,9 @@ mlir::affine::makeComposedFoldedAffineApply(OpBuilder &b, Location loc,
AffineExpr expr,
ArrayRef<OpFoldResult> operands) {
return makeComposedFoldedAffineApply(
b, loc, AffineMap::inferFromExprList(ArrayRef<AffineExpr>{expr}).front(),
b, loc,
AffineMap::inferFromExprList(ArrayRef<AffineExpr>{expr}, b.getContext())
.front(),
operands);
}

Expand Down
4 changes: 3 additions & 1 deletion mlir/lib/Dialect/Linalg/Transforms/Split.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ linalg::splitOp(RewriterBase &rewriter, TilingInterface op, unsigned dimension,
bindDims(rewriter.getContext(), d0, d1, d2);
OpFoldResult minSplitPoint = affine::makeComposedFoldedAffineMin(
rewriter, op.getLoc(),
AffineMap::inferFromExprList(ArrayRef<AffineExpr>{d0, d1 + d2}).front(),
AffineMap::inferFromExprList(ArrayRef<AffineExpr>{d0, d1 + d2},
rewriter.getContext())
.front(),
{splitPoint, offsets[dimension], sizes[dimension]});

// Compute the size of the second part. Return early if the second part would
Expand Down
17 changes: 9 additions & 8 deletions mlir/lib/Dialect/Linalg/Utils/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,20 +670,21 @@ computeSliceParameters(OpBuilder &builder, Location loc, Value valueToTile,
<< ": make sure in bound with affine.min\n");

AffineExpr dim0, dim1, dim2;
bindDims(builder.getContext(), dim0, dim1, dim2);
MLIRContext *context = builder.getContext();
bindDims(context, dim0, dim1, dim2);

// Get the dimension size for this dimension. We need to first calculate
// the max index and then plus one. This is important because for
// convolution ops, we have its input window dimension's affine map of the
// form `(d0 * s0 + d1)`, where `d0`/`d1 is an output/filter window
// dimension and `s0` is stride. Directly use the dimension size of
// output/filer window dimensions will cause incorrect calculation.
AffineMap minusOneMap =
AffineMap::inferFromExprList({ArrayRef<AffineExpr>{dim0 - 1}})
.front();
AffineMap plusOneMap =
AffineMap::inferFromExprList({ArrayRef<AffineExpr>{dim0 + 1}})
.front();
AffineMap minusOneMap = AffineMap::inferFromExprList(
{ArrayRef<AffineExpr>{dim0 - 1}}, context)
.front();
AffineMap plusOneMap = AffineMap::inferFromExprList(
{ArrayRef<AffineExpr>{dim0 + 1}}, context)
.front();
SmallVector<OpFoldResult> maxIndices =
llvm::to_vector(llvm::map_range(ubs, [&](OpFoldResult ub) {
return makeComposedFoldedAffineApply(rewriter, loc, minusOneMap,
Expand All @@ -696,7 +697,7 @@ computeSliceParameters(OpBuilder &builder, Location loc, Value valueToTile,

// Compute min(dim - offset, size) to avoid out-of-bounds accesses.
AffineMap minMap = AffineMap::inferFromExprList(
{ArrayRef<AffineExpr>{dim1 - dim2, dim0}})
{ArrayRef<AffineExpr>{dim1 - dim2, dim0}}, context)
.front();
size =
makeComposedFoldedAffineMin(rewriter, loc, minMap, {size, d, offset});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,9 @@ struct LinalgOpRewriter : public OpRewritePattern<linalg::GenericOp> {
SmallVector<AffineMap, 4> maps = op.getIndexingMapsArray();

using MapList = ArrayRef<ArrayRef<AffineExpr>>;
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, op.getContext());
};
AffineExpr i, j, k;
bindDims(getContext(), i, j, k);

Expand Down
7 changes: 4 additions & 3 deletions mlir/lib/Dialect/Vector/IR/VectorOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,10 @@ void vector::ContractionOp::build(OpBuilder &builder, OperationState &result,
ArrayRef<IteratorType> iteratorTypes) {
result.addOperands({lhs, rhs, acc});
result.addTypes(acc.getType());
result.addAttribute(getIndexingMapsAttrName(result.name),
builder.getAffineMapArrayAttr(
AffineMap::inferFromExprList(indexingExprs)));
result.addAttribute(
getIndexingMapsAttrName(result.name),
builder.getAffineMapArrayAttr(
AffineMap::inferFromExprList(indexingExprs, builder.getContext())));
result.addAttribute(
getIteratorTypesAttrName(result.name),
builder.getArrayAttr(llvm::to_vector(llvm::map_range(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@ ContractionOpToDotLowering::matchAndRewrite(vector::ContractionOp op,
Value lhs = op.getLhs(), rhs = op.getRhs();

using MapList = ArrayRef<ArrayRef<AffineExpr>>;
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, op.getContext());
};
AffineExpr m, n, k;
bindDims(rewriter.getContext(), m, n, k);
SmallVector<AffineMap> maps = op.getIndexingMapsArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ createSubViewIntersection(RewriterBase &b, VectorTransferOpInterface xferOp,
AffineExpr i, j, k;
bindDims(xferOp.getContext(), i, j, k);
SmallVector<AffineMap, 4> maps =
AffineMap::inferFromExprList(MapList{{i - j, k}});
AffineMap::inferFromExprList(MapList{{i - j, k}}, b.getContext());
// affine_min(%dimMemRef - %index, %dimAlloc)
Value affineMin = b.create<affine::AffineMinOp>(
loc, index.getType(), maps[0], ValueRange{dimMemRef, index, dimAlloc});
Expand Down
9 changes: 6 additions & 3 deletions mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ struct MultiReduceToContract
iteratorTypes.push_back(vector::IteratorType::reduction);
}
}
auto dstMap = AffineMap::get(/*dimCount=*/reductionMask.size(),
/*symCount=*/0, exprs, reduceOp.getContext());
auto dstMap =
AffineMap::get(/*dimCount=*/reductionMask.size(),
/*symbolCount=*/0, exprs, reduceOp.getContext());
rewriter.replaceOpWithNewOp<mlir::vector::ContractionOp>(
reduceOp, mulOp->getOperand(0), mulOp->getOperand(1), reduceOp.getAcc(),
rewriter.getAffineMapArrayAttr({srcMap, srcMap, dstMap}),
Expand Down Expand Up @@ -1399,7 +1400,9 @@ struct CanonicalizeContractMatmulToMMT final

// Set up the parallel/reduction structure in right form.
using MapList = ArrayRef<ArrayRef<AffineExpr>>;
auto infer = [](MapList m) { return AffineMap::inferFromExprList(m); };
auto infer = [&](MapList m) {
return AffineMap::inferFromExprList(m, op.getContext());
};
AffineExpr m;
AffineExpr n;
AffineExpr k;
Expand Down
24 changes: 15 additions & 9 deletions mlir/lib/IR/AffineMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,16 @@ AffineMap AffineMap::getMultiDimMapWithTargets(unsigned numDims,
return result;
}

/// Creates an affine map each for each list of AffineExpr's in `exprsList`
/// while inferring the right number of dimensional and symbolic inputs needed
/// based on the maximum dimensional and symbolic identifier appearing in the
/// expressions.
template <typename AffineExprContainer>
static SmallVector<AffineMap, 4>
inferFromExprList(ArrayRef<AffineExprContainer> exprsList) {
assert(!exprsList.empty());
assert(!exprsList[0].empty());
auto context = exprsList[0][0].getContext();
inferFromExprList(ArrayRef<AffineExprContainer> exprsList,
MLIRContext *context) {
if (exprsList.empty())
return {};
int64_t maxDim = -1, maxSym = -1;
getMaxDimAndSymbol(exprsList, maxDim, maxSym);
SmallVector<AffineMap, 4> maps;
Expand All @@ -289,13 +293,15 @@ inferFromExprList(ArrayRef<AffineExprContainer> exprsList) {
}

SmallVector<AffineMap, 4>
AffineMap::inferFromExprList(ArrayRef<ArrayRef<AffineExpr>> exprsList) {
return ::inferFromExprList(exprsList);
AffineMap::inferFromExprList(ArrayRef<ArrayRef<AffineExpr>> exprsList,
MLIRContext *context) {
return ::inferFromExprList(exprsList, context);
}

SmallVector<AffineMap, 4>
AffineMap::inferFromExprList(ArrayRef<SmallVector<AffineExpr, 4>> exprsList) {
return ::inferFromExprList(exprsList);
AffineMap::inferFromExprList(ArrayRef<SmallVector<AffineExpr, 4>> exprsList,
MLIRContext *context) {
return ::inferFromExprList(exprsList, context);
}

uint64_t AffineMap::getLargestKnownDivisorOfMapExprs() {
Expand Down Expand Up @@ -521,7 +527,7 @@ AffineMap::replace(const DenseMap<AffineExpr, AffineExpr> &map) const {
newResults.reserve(getNumResults());
for (AffineExpr e : getResults())
newResults.push_back(e.replace(map));
return AffineMap::inferFromExprList(newResults).front();
return AffineMap::inferFromExprList(newResults, getContext()).front();
}

AffineMap AffineMap::dropResults(const llvm::SmallBitVector &positions) const {
Expand Down
2 changes: 1 addition & 1 deletion mlir/lib/IR/BuiltinTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ AffineExpr mlir::makeCanonicalStridedLayoutExpr(ArrayRef<int64_t> sizes,
return getAffineConstantExpr(0, context);

assert(!exprs.empty() && "expected exprs");
auto maps = AffineMap::inferFromExprList(exprs);
auto maps = AffineMap::inferFromExprList(exprs, context);
assert(!maps.empty() && "Expected one non-empty map");
unsigned numDims = maps[0].getNumDims(), nSymbols = maps[0].getNumSymbols();

Expand Down
23 changes: 23 additions & 0 deletions mlir/unittests/IR/AffineMapTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===- AffineMapTest.cpp - unit tests for affine map API ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "gtest/gtest.h"

using namespace mlir;

// Test AffineMap replace API for the zero result case.
TEST(AffineMapTest, inferMapFromAffineExprs) {
MLIRContext ctx;
OpBuilder b(&ctx);
AffineMap map = b.getEmptyAffineMap();
DenseMap<AffineExpr, AffineExpr> replacements;
map.replace(replacements);
EXPECT_EQ(map, map);
}
1 change: 1 addition & 0 deletions mlir/unittests/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_mlir_unittest(MLIRIRTests
AdaptorTest.cpp
AffineMapTest.cpp
AttributeTest.cpp
DialectTest.cpp
InterfaceTest.cpp
Expand Down