| //===- LowerVectorStep.cpp - Lower 'vector.step' operation ----------------===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements target-independent rewrites and utilities to lower the | |
| // 'vector.step' operation. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "mlir/Dialect/Arith/IR/Arith.h" | |
| #include "mlir/Dialect/Vector/IR/VectorOps.h" | |
| #include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h" | |
| #include "mlir/IR/PatternMatch.h" | |
| #define DEBUG_TYPE "vector-step-lowering" | |
| using namespace mlir; | |
| using namespace mlir::vector; | |
| namespace { | |
| struct StepToArithConstantOpRewrite final : OpRewritePattern<vector::StepOp> { | |
| StepToArithConstantOpRewrite(MLIRContext *context, unsigned indexBitwidth, | |
| PatternBenefit benefit) | |
| : OpRewritePattern(context, benefit), indexBitwidth(indexBitwidth) { | |
| assert(indexBitwidth <= IndexType::kInternalStorageBitWidth && | |
| "indexBitwidth cannot exceed the index storage bitwidth"); | |
| } | |
| LogicalResult matchAndRewrite(vector::StepOp stepOp, | |
| PatternRewriter &rewriter) const override { | |
| auto resultType = cast<VectorType>(stepOp.getType()); | |
| if (resultType.isScalable()) { | |
| return failure(); | |
| } | |
| Type elementType = resultType.getElementType(); | |
| // An `indexBitwidth` of 0 means "leave `index`-typed steps alone": the | |
| // index bitwidth is target-dependent, so callers that don't know it (and | |
| // defer to a later lowering, e.g. to `llvm.intr.stepvector`) opt out. | |
| if (elementType.isIndex() && indexBitwidth == 0) { | |
| return failure(); | |
| } | |
| // Values wrap around at `computeWidth`. `index` elements are stored in a | |
| // `DenseElementsAttr` using the internal storage bitwidth, so the wrapped | |
| // value is widened to it; integer elements use their own bitwidth. | |
| unsigned computeWidth = elementType.isIndex() | |
| ? indexBitwidth | |
| : elementType.getIntOrFloatBitWidth(); | |
| unsigned storageWidth = elementType.isIndex() | |
| ? IndexType::kInternalStorageBitWidth | |
| : computeWidth; | |
| int64_t elementCount = resultType.getNumElements(); | |
| SmallVector<APInt> indices = llvm::map_to_vector( | |
| llvm::seq(elementCount), [computeWidth, storageWidth](int64_t i) { | |
| return APInt(computeWidth, i, /*isSigned=*/false, | |
| /*implicitTrunc=*/true) | |
| .zext(storageWidth); | |
| }); | |
| rewriter.replaceOpWithNewOp<arith::ConstantOp>( | |
| stepOp, DenseElementsAttr::get(resultType, indices)); | |
| return success(); | |
| } | |
| unsigned indexBitwidth; | |
| }; | |
| } // namespace | |
| void mlir::vector::populateVectorStepLoweringPatterns( | |
| RewritePatternSet &patterns, unsigned indexBitwidth, | |
| PatternBenefit benefit) { | |
| patterns.add<StepToArithConstantOpRewrite>(patterns.getContext(), | |
| indexBitwidth, benefit); | |
| } |