Skip to content

Commit 33b5b66

Browse files
committed
LocalAliasAnalysis
1 parent 4a2f29d commit 33b5b66

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def AssumeAlignmentOp : MemRef_Op<"assume_alignment", [
184184

185185
def DistinctObjectsOp : MemRef_Op<"distinct_objects", [
186186
Pure,
187+
DistinctObjectsInterface,
187188
DeclareOpInterfaceMethods<InferTypeOpInterface>
188189
// ViewLikeOpInterface TODO: ViewLikeOpInterface only supports a single argument
189190
]> {

mlir/include/mlir/Interfaces/ViewLikeInterface.td

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,44 @@ def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface
414414
}];
415415
}
416416

417+
def DistinctObjectsInterface : OpInterface<"DistinctObjectsInterface"> {
418+
let description = [{
419+
This intefaces indicates that pointer-like objects (such as memrefs) returned
420+
from this operation will never alias with each other. This provides a
421+
guarantee to optimization passes that accesses through different results
422+
of this operation can be safely reordered, as they will never reference
423+
overlapping memory locations.
424+
425+
Operations with this interface take multiple pointer-like operands
426+
and return the same operands with additional non-aliasing guarantees.
427+
If the access to the results of this operation aliases at runtime, the
428+
behavior of such access is undefined.
429+
}];
430+
let cppNamespace = "::mlir";
431+
432+
let methods = [
433+
InterfaceMethod<
434+
/*desc=*/[{ Return input pointer-like objects. }],
435+
/*retTy=*/"::mlir::ValueRange",
436+
/*methodName=*/"getDistinctOperands",
437+
/*args=*/(ins),
438+
/*methodBody=*/"",
439+
/*defaultImplementation=*/[{
440+
return $_op->getOperands();
441+
}]
442+
>,
443+
InterfaceMethod<
444+
/*desc=*/[{ Return result pointer-like objects. }],
445+
/*retTy=*/"::mlir::ValueRange",
446+
/*methodName=*/"getDistinctResults",
447+
/*args=*/(ins),
448+
/*methodBody=*/"",
449+
/*defaultImplementation=*/[{
450+
return $_op->getResults();
451+
}]
452+
>
453+
];
454+
}
455+
456+
417457
#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE

mlir/lib/Analysis/AliasAnalysis/LocalAliasAnalysis.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,33 @@ getAllocEffectFor(Value value,
258258
return success();
259259
}
260260

261+
static Value getDistinctObjectsOperand(DistinctObjectsInterface op,
262+
Value value) {
263+
unsigned argNumber = cast<OpResult>(value).getResultNumber();
264+
return op.getDistinctOperands()[argNumber];
265+
}
266+
267+
static std::optional<AliasResult> checkDistinctObjects(Value lhs, Value rhs) {
268+
// We should already checked that lhs and rhs are different.
269+
assert(lhs != rhs && "lhs and rhs must be different");
270+
271+
// Result and corresponding operand must alias.
272+
auto lhsOp = lhs.getDefiningOp<DistinctObjectsInterface>();
273+
if (lhsOp && getDistinctObjectsOperand(lhsOp, lhs) == rhs)
274+
return AliasResult::MustAlias;
275+
276+
auto rhsOp = rhs.getDefiningOp<DistinctObjectsInterface>();
277+
if (rhsOp && getDistinctObjectsOperand(rhsOp, rhs) == lhs)
278+
return AliasResult::MustAlias;
279+
280+
// If two different values come from the same `DistinctObjects` operation,
281+
// they don't alias.
282+
if (lhsOp && lhsOp == rhsOp)
283+
return AliasResult::NoAlias;
284+
285+
return std::nullopt;
286+
}
287+
261288
/// Given the two values, return their aliasing behavior.
262289
AliasResult LocalAliasAnalysis::aliasImpl(Value lhs, Value rhs) {
263290
if (lhs == rhs)
@@ -289,6 +316,9 @@ AliasResult LocalAliasAnalysis::aliasImpl(Value lhs, Value rhs) {
289316
: AliasResult::MayAlias;
290317
}
291318

319+
if (std::optional<AliasResult> result = checkDistinctObjects(lhs, rhs))
320+
return *result;
321+
292322
// Otherwise, neither of the values are constant so check to see if either has
293323
// an allocation effect.
294324
bool lhsHasAlloc = succeeded(getAllocEffectFor(lhs, lhsAlloc, lhsAllocScope));

mlir/test/Analysis/test-alias-analysis.mlir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,19 @@ func.func @constants(%arg: memref<2xf32>) attributes {test.ptr = "func"} {
256256

257257
return
258258
}
259+
260+
// -----
261+
262+
// CHECK-LABEL: Testing : "distinct_objects"
263+
// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias
264+
265+
// CHECK-DAG: distinct#0 <-> distinct#1: NoAlias
266+
// CHECK-DAG: distinct#0 <-> func.region0#0: MustAlias
267+
// CHECK-DAG: distinct#1 <-> func.region0#0: MayAlias
268+
// CHECK-DAG: distinct#0 <-> func.region0#1: MayAlias
269+
// CHECK-DAG: distinct#1 <-> func.region0#1: MustAlias
270+
271+
func.func @distinct_objects(%arg: memref<?xf32>, %arg1: memref<?xf32>) attributes {test.ptr = "func"} {
272+
%0, %1 = memref.distinct_objects %arg, %arg1 {test.ptr = "distinct"} : memref<?xf32>, memref<?xf32>
273+
return
274+
}

0 commit comments

Comments
 (0)