diff --git a/mlir/include/mlir/Dialect/GPU/GPUOps.td b/mlir/include/mlir/Dialect/GPU/GPUOps.td --- a/mlir/include/mlir/Dialect/GPU/GPUOps.td +++ b/mlir/include/mlir/Dialect/GPU/GPUOps.td @@ -834,6 +834,8 @@ custom(type($asyncToken), $asyncDependencies) ` ` `(` $dynamicSizes `)` (`` `[` $symbolOperands^ `]`)? attr-dict `:` type($memref) }]; + + let hasCanonicalizer = 1; } def GPU_DeallocOp : GPU_Op<"dealloc", [GPU_AsyncOpInterface]> { @@ -1040,7 +1042,7 @@ the same value. This op is meant to be used along with `gpu.subgroup_mma_compute`. - + Example: ```mlir diff --git a/mlir/lib/Dialect/GPU/CMakeLists.txt b/mlir/lib/Dialect/GPU/CMakeLists.txt --- a/mlir/lib/Dialect/GPU/CMakeLists.txt +++ b/mlir/lib/Dialect/GPU/CMakeLists.txt @@ -18,6 +18,7 @@ add_mlir_dialect_library(MLIRGPUOps IR/GPUDialect.cpp + IR/GPUOps.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/GPU diff --git a/mlir/lib/Dialect/GPU/IR/GPUOps.cpp b/mlir/lib/Dialect/GPU/IR/GPUOps.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/GPU/IR/GPUOps.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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/Dialect/GPU/GPUDialect.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/PatternMatch.h" + +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/MemRef/Utils/MemRefUtils.h" +#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/Dialect/StandardOps/Utils/Utils.h" +// #include "mlir/Dialect/Tensor/IR/Tensor.h" +#include "mlir/Dialect/Utils/StaticValueUtils.h" +// #include "mlir/IR/AffineMap.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Matchers.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/TypeUtilities.h" +#include "mlir/Interfaces/InferTypeOpInterface.h" +#include "mlir/Interfaces/ViewLikeInterface.h" +#include "llvm/ADT/STLExtras.h" + +using namespace mlir; +using namespace mlir::gpu; + +namespace { + +// Folding of memref.dim(gpu.alloca(%size), %idx) -> %size similar to +// `memref::AllocOp`. +struct SimplifyDimOfAllocOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(memref::DimOp dimOp, + PatternRewriter &rewriter) const override { + auto index = + dyn_cast_or_null(dimOp.getOperand(1).getDefiningOp()); + if (!index) + return failure(); + + auto memrefType = dimOp.source().getType().dyn_cast(); + if (!memrefType) + return failure(); + + Operation *definingOp = dimOp.source().getDefiningOp(); + if (auto alloc = dyn_cast_or_null(definingOp)) { + auto substituteOp = *(alloc.dynamicSizes().begin() + + memrefType.getDynamicDimIndex(index.getValue())); + rewriter.replaceOp(dimOp, substituteOp); + return success(); + } + + return failure(); + } +}; + +} // end anonymous namespace. + +void AllocOp::getCanonicalizationPatterns(RewritePatternSet &results, + MLIRContext *context) { + results.add(context); +} diff --git a/mlir/test/Dialect/GPU/canonicalize.mlir b/mlir/test/Dialect/GPU/canonicalize.mlir --- a/mlir/test/Dialect/GPU/canonicalize.mlir +++ b/mlir/test/Dialect/GPU/canonicalize.mlir @@ -9,3 +9,16 @@ gpu.memcpy %0,%1 : memref, memref return } + +// ----- + +// Test case: Folding of memref.dim(gpu.alloca(%size), %idx) -> %size +// CHECK-LABEL: func @gpu_dim_of_alloc( +// CHECK-SAME: %[[SIZE:[0-9a-z]+]]: index +// CHECK-NEXT: return %[[SIZE]] : index +func @gpu_dim_of_alloc(%size: index) -> index { + %0 = gpu.alloc(%size) : memref + %c0 = constant 0 : index + %1 = memref.dim %0, %c0 : memref + return %1 : index +} \ No newline at end of file