Skip to content

Commit 5af7263

Browse files
authored
[mlir] add getViewDest method to viewLikeOpInterface (#154524)
The viewLikeOpInterface abstracts the behavior of an operation view one buffer as another. However, the current interface only includes a "getViewSource" method and lacks a "getViewDest" method. Previously, it was generally assumed that viewLikeOpInterface operations would have only one return value, which was the view dest. This assumption was broken by memref.extract_strided_metadata, and more operations may break these silent conventions in the future. Calling "viewLikeInterface->getResult(0)" may lead to a core dump at runtime. Therefore, we need 'getViewDest' method to standardize our behavior. This patch adds the getViewDest function to viewLikeOpInterface and modifies the usage points of viewLikeOpInterface to standardize its use.
1 parent 9ccdadd commit 5af7263

File tree

11 files changed

+58
-21
lines changed

11 files changed

+58
-21
lines changed

mlir/include/mlir/Interfaces/ViewLikeInterface.td

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,17 @@ def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> {
2626
let methods = [
2727
InterfaceMethod<
2828
"Returns the source buffer from which the view is created.",
29-
"::mlir::Value", "getViewSource">
29+
"::mlir::Value", "getViewSource">,
30+
InterfaceMethod<
31+
/*desc=*/[{ Returns the buffer which the view created. }],
32+
/*retTy=*/"::mlir::Value",
33+
/*methodName=*/"getViewDest",
34+
/*args=*/(ins),
35+
/*methodBody=*/"",
36+
/*defaultImplementation=*/[{
37+
return $_op->getResult(0);
38+
}]
39+
>
3040
];
3141
}
3242

mlir/lib/Analysis/AliasAnalysis/LocalAliasAnalysis.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,12 @@ static void collectUnderlyingAddressValues(OpResult result, unsigned maxDepth,
127127
Operation *op = result.getOwner();
128128

129129
// If this is a view, unwrap to the source.
130-
if (ViewLikeOpInterface view = dyn_cast<ViewLikeOpInterface>(op))
131-
return collectUnderlyingAddressValues(view.getViewSource(), maxDepth,
132-
visited, output);
130+
if (ViewLikeOpInterface view = dyn_cast<ViewLikeOpInterface>(op)) {
131+
if (result == view.getViewDest()) {
132+
return collectUnderlyingAddressValues(view.getViewSource(), maxDepth,
133+
visited, output);
134+
}
135+
}
133136
// Check to see if we can reason about the control flow of this op.
134137
if (auto branch = dyn_cast<RegionBranchOpInterface>(op)) {
135138
return collectUnderlyingAddressValues(branch, /*region=*/nullptr, result,

mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ static bool isEscapingMemref(Value memref, Block *block) {
190190

191191
// Check if this is defined to be an alias of another memref.
192192
if (auto viewOp = dyn_cast<mlir::ViewLikeOpInterface>(defOp))
193-
if (isEscapingMemref(viewOp.getViewSource(), block))
193+
if (memref == viewOp.getViewDest() &&
194+
isEscapingMemref(viewOp.getViewSource(), block))
194195
return true;
195196

196197
// Any op besides allocating ops wouldn't guarantee alias freedom

mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,12 @@ struct SimplifyClones : public OpRewritePattern<CloneOp> {
463463
// which otherwise could prevent removal of unnecessary allocs.
464464
Value canonicalSource = source;
465465
while (auto iface = dyn_cast_or_null<ViewLikeOpInterface>(
466-
canonicalSource.getDefiningOp()))
466+
canonicalSource.getDefiningOp())) {
467+
if (canonicalSource != iface.getViewDest()) {
468+
break;
469+
}
467470
canonicalSource = iface.getViewSource();
471+
}
468472

469473
std::optional<Operation *> maybeCloneDeallocOp =
470474
memref::findDealloc(cloneOp.getOutput());

mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocationSimplification.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ using namespace mlir::bufferization;
3737
/// Given a memref value, return the "base" value by skipping over all
3838
/// ViewLikeOpInterface ops (if any) in the reverse use-def chain.
3939
static Value getViewBase(Value value) {
40-
while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>())
40+
while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>()) {
41+
if (value != viewLikeOp.getViewDest()) {
42+
break;
43+
}
4144
value = viewLikeOp.getViewSource();
45+
}
4246
return value;
4347
}
4448

mlir/lib/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void BufferViewFlowAnalysis::build(Operation *op) {
121121
// Add additional dependencies created by view changes to the alias list.
122122
if (auto viewInterface = dyn_cast<ViewLikeOpInterface>(op)) {
123123
registerDependencies(viewInterface.getViewSource(),
124-
viewInterface->getResult(0));
124+
viewInterface.getViewDest());
125125
return WalkResult::advance();
126126
}
127127

@@ -231,8 +231,12 @@ static bool isFunctionArgument(Value v) {
231231
/// Given a memref value, return the "base" value by skipping over all
232232
/// ViewLikeOpInterface ops (if any) in the reverse use-def chain.
233233
static Value getViewBase(Value value) {
234-
while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>())
234+
while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>()) {
235+
if (value != viewLikeOp.getViewDest()) {
236+
break;
237+
}
235238
value = viewLikeOp.getViewSource();
239+
}
236240
return value;
237241
}
238242

mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,10 @@ getUnderlyingObjectSet(Value pointerValue) {
235235
WalkContinuation walkResult = walkSlice(pointerValue, [&](Value val) {
236236
// Attempt to advance to the source of the underlying view-like operation.
237237
// Examples of view-like operations include GEPOp and AddrSpaceCastOp.
238-
if (auto viewOp = val.getDefiningOp<ViewLikeOpInterface>())
239-
return WalkContinuation::advanceTo(viewOp.getViewSource());
238+
if (auto viewOp = val.getDefiningOp<ViewLikeOpInterface>()) {
239+
if (val == viewOp.getViewDest())
240+
return WalkContinuation::advanceTo(viewOp.getViewSource());
241+
}
240242

241243
// Attempt to advance to control flow predecessors.
242244
std::optional<SmallVector<Value>> controlFlowPredecessors =

mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,12 @@ static bool noAliasingUseInLoop(vector::TransferReadOp transferRead,
166166
Value source = transferRead.getBase();
167167

168168
// Skip view-like Ops and retrive the actual soruce Operation
169-
while (auto srcOp = source.getDefiningOp<ViewLikeOpInterface>())
170-
source = srcOp.getViewSource();
169+
while (auto viewLike = source.getDefiningOp<ViewLikeOpInterface>()) {
170+
if (viewLike.getViewDest() != source) {
171+
break;
172+
}
173+
source = viewLike.getViewSource();
174+
}
171175

172176
llvm::SmallVector<Operation *, 32> users(source.getUsers().begin(),
173177
source.getUsers().end());
@@ -178,7 +182,8 @@ static bool noAliasingUseInLoop(vector::TransferReadOp transferRead,
178182
if (!processed.insert(user).second)
179183
continue;
180184
if (auto viewLike = dyn_cast<ViewLikeOpInterface>(user)) {
181-
users.append(viewLike->getUsers().begin(), viewLike->getUsers().end());
185+
Value viewDest = viewLike.getViewDest();
186+
users.append(viewDest.getUsers().begin(), viewDest.getUsers().end());
182187
continue;
183188
}
184189
if (isMemoryEffectFree(user) || isa<vector::TransferReadOp>(user))

mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ class RewriteExtractAlignedPointerAsIndexOfViewLikeOp
959959
PatternRewriter &rewriter) const override {
960960
auto viewLikeOp =
961961
extractOp.getSource().getDefiningOp<ViewLikeOpInterface>();
962-
if (!viewLikeOp)
962+
if (!viewLikeOp || extractOp.getSource() != viewLikeOp.getViewDest())
963963
return rewriter.notifyMatchFailure(extractOp, "not a ViewLike source");
964964
rewriter.modifyOpInPlace(extractOp, [&]() {
965965
extractOp.getSourceMutable().assign(viewLikeOp.getViewSource());

mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,10 @@ MemrefValue skipFullyAliasingOperations(MemrefValue source) {
210210
MemrefValue skipViewLikeOps(MemrefValue source) {
211211
while (auto op = source.getDefiningOp()) {
212212
if (auto viewLike = dyn_cast<ViewLikeOpInterface>(op)) {
213-
source = cast<MemrefValue>(viewLike.getViewSource());
214-
continue;
213+
if (source == viewLike.getViewDest()) {
214+
source = cast<MemrefValue>(viewLike.getViewSource());
215+
continue;
216+
}
215217
}
216218
return source;
217219
}

0 commit comments

Comments
 (0)