diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -129,14 +129,12 @@ // // %0 = alloclike(%m)[%s] : memref<8x?xf32, (d0, d1)[s0] -> ((d0 + s0), d1)> // -class AllocLikeOp resultDecorators = [], - list traits = []> : - Std_Op { +class AllocLikeOp traits = []> : + Std_Op])> { let arguments = (ins Variadic:$value, Confined, [IntMinValue<0>]>:$alignment); - let results = (outs Arg); + let results = (outs Res); let builders = [OpBuilder< "OpBuilder &builder, OperationState &result, MemRefType memrefType", [{ @@ -278,7 +276,7 @@ // AllocOp //===----------------------------------------------------------------------===// -def AllocOp : AllocLikeOp<"alloc", [MemAlloc], [MemoryEffects<[MemAlloc]>]> { +def AllocOp : AllocLikeOp<"alloc"> { let summary = "memory allocation operation"; let description = [{ The `alloc` operation allocates a region of memory, as specified by its diff --git a/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp b/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp --- a/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp +++ b/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp @@ -37,12 +37,26 @@ while (true) { if (v.isa()) return v; + Operation *defOp = v.getDefiningOp(); - if (auto alloc = dyn_cast_or_null(defOp)) { - if (isStrided(alloc.getType())) - return alloc.getResult(); + if (!defOp) + return v; + + if (auto memEffect = dyn_cast(defOp)) { + // Collect all memory effects on `v`. + SmallVector effects; + memEffect.getEffectsOnValue(v, effects); + + // If we have the 'Allocate' memory effect on `v`, then `v` should be the + // original buffer. + if (llvm::any_of( + effects, [](const MemoryEffects::EffectInstance &instance) { + return isa(instance.getEffect()); + })) + return v; } - if (auto viewLikeOp = dyn_cast_or_null(defOp)) { + + if (auto viewLikeOp = dyn_cast(defOp)) { auto it = aliases.insert(std::make_pair(v, find(viewLikeOp.getViewSource()))); return it.first->second; diff --git a/mlir/test/Dialect/Linalg/fusion.mlir b/mlir/test/Dialect/Linalg/fusion.mlir --- a/mlir/test/Dialect/Linalg/fusion.mlir +++ b/mlir/test/Dialect/Linalg/fusion.mlir @@ -727,3 +727,48 @@ // CHECK: loop.for // CHECK: linalg.fill // CHECK: linalg.conv + +// ----- + +// Test that different allocation-like ops are recognized and properly handled. +func @accept_different_alloc_ops(%dim: index, %s0 : index, %s1: index) { + %c0 = constant 0 : index + %c1 = constant 1 : index + %c2 = constant 2 : index + %c3 = constant 3 : index + %c4 = constant 4 : index + + %A = alloca(%dim, %dim)[%s0, %s1] : memref + %B = alloca(%dim, %dim)[%s0, %s1] : memref + %C = alloc(%dim, %dim)[%s0, %s1] : memref + + linalg.matmul(%A, %B, %C) : + memref, + memref, + memref + + loop.for %i = %c0 to %dim step %c2 { + loop.for %j = %c0 to %dim step %c3 { + loop.for %k = %c0 to %dim step %c4 { + %0 = std.subview %A[%i, %k][%c2, %c4][%c1, %c1] : + memref to + memref + %1 = std.subview %B[%k, %j][%c4, %c3][%c1, %c1] : + memref to + memref + %2 = std.subview %C[%i, %j][%c2, %c3][%c1, %c1] : + memref to + memref + linalg.matmul(%0, %1, %2) : + memref, + memref, + memref + } + } + } + return +} + +// CHECK-LABEL: func @accept_different_alloc_ops +// CHECK-COUNT-3: loop.for +// CHECK-COUNT-2: linalg.matmul