199ef9eebSMatthias Springer //===- VectorInsertExtractStridedSliceRewritePatterns.cpp - Rewrites ------===// 299ef9eebSMatthias Springer // 399ef9eebSMatthias Springer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 499ef9eebSMatthias Springer // See https://llvm.org/LICENSE.txt for license information. 599ef9eebSMatthias Springer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 699ef9eebSMatthias Springer // 799ef9eebSMatthias Springer //===----------------------------------------------------------------------===// 899ef9eebSMatthias Springer 9abc362a1SJakub Kuderski #include "mlir/Dialect/Arith/IR/Arith.h" 1099ef9eebSMatthias Springer #include "mlir/Dialect/MemRef/IR/MemRef.h" 1199ef9eebSMatthias Springer #include "mlir/Dialect/Utils/IndexingUtils.h" 1299ef9eebSMatthias Springer #include "mlir/Dialect/Vector/IR/VectorOps.h" 1399ef9eebSMatthias Springer #include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h" 1499ef9eebSMatthias Springer #include "mlir/Dialect/Vector/Utils/VectorUtils.h" 1599ef9eebSMatthias Springer #include "mlir/IR/BuiltinTypes.h" 1639c80656SLei Zhang #include "mlir/IR/PatternMatch.h" 1799ef9eebSMatthias Springer 1899ef9eebSMatthias Springer using namespace mlir; 1999ef9eebSMatthias Springer using namespace mlir::vector; 2099ef9eebSMatthias Springer 2199ef9eebSMatthias Springer /// RewritePattern for InsertStridedSliceOp where source and destination vectors 2299ef9eebSMatthias Springer /// have different ranks. 2399ef9eebSMatthias Springer /// 2499ef9eebSMatthias Springer /// When ranks are different, InsertStridedSlice needs to extract a properly 2599ef9eebSMatthias Springer /// ranked vector from the destination vector into which to insert. This pattern 2699ef9eebSMatthias Springer /// only takes care of this extraction part and forwards the rest to 2759d3a9e0SLei Zhang /// [ConvertSameRankInsertStridedSliceIntoShuffle]. 2899ef9eebSMatthias Springer /// 2999ef9eebSMatthias Springer /// For a k-D source and n-D destination vector (k < n), we emit: 3099ef9eebSMatthias Springer /// 1. ExtractOp to extract the (unique) (n-1)-D subvector into which to 3199ef9eebSMatthias Springer /// insert the k-D source. 3299ef9eebSMatthias Springer /// 2. k-D -> (n-1)-D InsertStridedSlice op 3399ef9eebSMatthias Springer /// 3. InsertOp that is the reverse of 1. 3459d3a9e0SLei Zhang class DecomposeDifferentRankInsertStridedSlice 3599ef9eebSMatthias Springer : public OpRewritePattern<InsertStridedSliceOp> { 3699ef9eebSMatthias Springer public: 3799ef9eebSMatthias Springer using OpRewritePattern<InsertStridedSliceOp>::OpRewritePattern; 3899ef9eebSMatthias Springer 3999ef9eebSMatthias Springer LogicalResult matchAndRewrite(InsertStridedSliceOp op, 4099ef9eebSMatthias Springer PatternRewriter &rewriter) const override { 4199ef9eebSMatthias Springer auto srcType = op.getSourceVectorType(); 4299ef9eebSMatthias Springer auto dstType = op.getDestVectorType(); 4399ef9eebSMatthias Springer 447c38fd60SJacques Pienaar if (op.getOffsets().getValue().empty()) 4599ef9eebSMatthias Springer return failure(); 4699ef9eebSMatthias Springer 4799ef9eebSMatthias Springer auto loc = op.getLoc(); 4899ef9eebSMatthias Springer int64_t rankDiff = dstType.getRank() - srcType.getRank(); 4999ef9eebSMatthias Springer assert(rankDiff >= 0); 5099ef9eebSMatthias Springer if (rankDiff == 0) 5199ef9eebSMatthias Springer return failure(); 5299ef9eebSMatthias Springer 5399ef9eebSMatthias Springer int64_t rankRest = dstType.getRank() - rankDiff; 5499ef9eebSMatthias Springer // Extract / insert the subvector of matching rank and InsertStridedSlice 5599ef9eebSMatthias Springer // on it. 567c38fd60SJacques Pienaar Value extracted = rewriter.create<ExtractOp>( 577c38fd60SJacques Pienaar loc, op.getDest(), 587c38fd60SJacques Pienaar getI64SubArray(op.getOffsets(), /*dropFront=*/0, 5999ef9eebSMatthias Springer /*dropBack=*/rankRest)); 6099ef9eebSMatthias Springer 6199ef9eebSMatthias Springer // A different pattern will kick in for InsertStridedSlice with matching 6299ef9eebSMatthias Springer // ranks. 6399ef9eebSMatthias Springer auto stridedSliceInnerOp = rewriter.create<InsertStridedSliceOp>( 647c38fd60SJacques Pienaar loc, op.getSource(), extracted, 657c38fd60SJacques Pienaar getI64SubArray(op.getOffsets(), /*dropFront=*/rankDiff), 667c38fd60SJacques Pienaar getI64SubArray(op.getStrides(), /*dropFront=*/0)); 6799ef9eebSMatthias Springer 6899ef9eebSMatthias Springer rewriter.replaceOpWithNewOp<InsertOp>( 697c38fd60SJacques Pienaar op, stridedSliceInnerOp.getResult(), op.getDest(), 707c38fd60SJacques Pienaar getI64SubArray(op.getOffsets(), /*dropFront=*/0, 7199ef9eebSMatthias Springer /*dropBack=*/rankRest)); 7299ef9eebSMatthias Springer return success(); 7399ef9eebSMatthias Springer } 7499ef9eebSMatthias Springer }; 7599ef9eebSMatthias Springer 7699ef9eebSMatthias Springer /// RewritePattern for InsertStridedSliceOp where source and destination vectors 7799ef9eebSMatthias Springer /// have the same rank. For each outermost index in the slice: 7899ef9eebSMatthias Springer /// begin end stride 7999ef9eebSMatthias Springer /// [offset : offset+size*stride : stride] 8099ef9eebSMatthias Springer /// 1. ExtractOp one (k-1)-D source subvector and one (n-1)-D dest subvector. 8199ef9eebSMatthias Springer /// 2. InsertStridedSlice (k-1)-D into (n-1)-D 8299ef9eebSMatthias Springer /// 3. the destination subvector is inserted back in the proper place 8399ef9eebSMatthias Springer /// 3. InsertOp that is the reverse of 1. 8459d3a9e0SLei Zhang class ConvertSameRankInsertStridedSliceIntoShuffle 8599ef9eebSMatthias Springer : public OpRewritePattern<InsertStridedSliceOp> { 8699ef9eebSMatthias Springer public: 8799ef9eebSMatthias Springer using OpRewritePattern<InsertStridedSliceOp>::OpRewritePattern; 8899ef9eebSMatthias Springer 8999ef9eebSMatthias Springer void initialize() { 9099ef9eebSMatthias Springer // This pattern creates recursive InsertStridedSliceOp, but the recursion is 9199ef9eebSMatthias Springer // bounded as the rank is strictly decreasing. 9299ef9eebSMatthias Springer setHasBoundedRewriteRecursion(); 9399ef9eebSMatthias Springer } 9499ef9eebSMatthias Springer 9599ef9eebSMatthias Springer LogicalResult matchAndRewrite(InsertStridedSliceOp op, 9699ef9eebSMatthias Springer PatternRewriter &rewriter) const override { 9799ef9eebSMatthias Springer auto srcType = op.getSourceVectorType(); 9899ef9eebSMatthias Springer auto dstType = op.getDestVectorType(); 9999ef9eebSMatthias Springer 1007c38fd60SJacques Pienaar if (op.getOffsets().getValue().empty()) 10199ef9eebSMatthias Springer return failure(); 10299ef9eebSMatthias Springer 10399ef9eebSMatthias Springer int64_t srcRank = srcType.getRank(); 10499ef9eebSMatthias Springer int64_t dstRank = dstType.getRank(); 10599ef9eebSMatthias Springer assert(dstRank >= srcRank); 10699ef9eebSMatthias Springer if (dstRank != srcRank) 10799ef9eebSMatthias Springer return failure(); 10899ef9eebSMatthias Springer 10999ef9eebSMatthias Springer if (srcType == dstType) { 1107c38fd60SJacques Pienaar rewriter.replaceOp(op, op.getSource()); 11199ef9eebSMatthias Springer return success(); 11299ef9eebSMatthias Springer } 11399ef9eebSMatthias Springer 11499ef9eebSMatthias Springer int64_t offset = 1155550c821STres Popp cast<IntegerAttr>(op.getOffsets().getValue().front()).getInt(); 11699ef9eebSMatthias Springer int64_t size = srcType.getShape().front(); 11799ef9eebSMatthias Springer int64_t stride = 1185550c821STres Popp cast<IntegerAttr>(op.getStrides().getValue().front()).getInt(); 11999ef9eebSMatthias Springer 12099ef9eebSMatthias Springer auto loc = op.getLoc(); 1217c38fd60SJacques Pienaar Value res = op.getDest(); 12299ef9eebSMatthias Springer 12399ef9eebSMatthias Springer if (srcRank == 1) { 12499ef9eebSMatthias Springer int nSrc = srcType.getShape().front(); 12599ef9eebSMatthias Springer int nDest = dstType.getShape().front(); 12699ef9eebSMatthias Springer // 1. Scale source to destType so we can shufflevector them together. 12799ef9eebSMatthias Springer SmallVector<int64_t> offsets(nDest, 0); 12899ef9eebSMatthias Springer for (int64_t i = 0; i < nSrc; ++i) 12999ef9eebSMatthias Springer offsets[i] = i; 1307c38fd60SJacques Pienaar Value scaledSource = rewriter.create<ShuffleOp>(loc, op.getSource(), 1317c38fd60SJacques Pienaar op.getSource(), offsets); 13299ef9eebSMatthias Springer 13399ef9eebSMatthias Springer // 2. Create a mask where we take the value from scaledSource of dest 13499ef9eebSMatthias Springer // depending on the offset. 13599ef9eebSMatthias Springer offsets.clear(); 13699ef9eebSMatthias Springer for (int64_t i = 0, e = offset + size * stride; i < nDest; ++i) { 13799ef9eebSMatthias Springer if (i < offset || i >= e || (i - offset) % stride != 0) 13899ef9eebSMatthias Springer offsets.push_back(nDest + i); 13999ef9eebSMatthias Springer else 14099ef9eebSMatthias Springer offsets.push_back((i - offset) / stride); 14199ef9eebSMatthias Springer } 14299ef9eebSMatthias Springer 14399ef9eebSMatthias Springer // 3. Replace with a ShuffleOp. 1447c38fd60SJacques Pienaar rewriter.replaceOpWithNewOp<ShuffleOp>(op, scaledSource, op.getDest(), 14599ef9eebSMatthias Springer offsets); 14699ef9eebSMatthias Springer 14799ef9eebSMatthias Springer return success(); 14899ef9eebSMatthias Springer } 14999ef9eebSMatthias Springer 15099ef9eebSMatthias Springer // For each slice of the source vector along the most major dimension. 15199ef9eebSMatthias Springer for (int64_t off = offset, e = offset + size * stride, idx = 0; off < e; 15299ef9eebSMatthias Springer off += stride, ++idx) { 15399ef9eebSMatthias Springer // 1. extract the proper subvector (or element) from source 154*8e663039SKunwar Grover Value extractedSource = 155*8e663039SKunwar Grover rewriter.create<ExtractOp>(loc, op.getSource(), idx); 1565550c821STres Popp if (isa<VectorType>(extractedSource.getType())) { 15799ef9eebSMatthias Springer // 2. If we have a vector, extract the proper subvector from destination 15899ef9eebSMatthias Springer // Otherwise we are at the element level and no need to recurse. 159*8e663039SKunwar Grover Value extractedDest = 160*8e663039SKunwar Grover rewriter.create<ExtractOp>(loc, op.getDest(), off); 16199ef9eebSMatthias Springer // 3. Reduce the problem to lowering a new InsertStridedSlice op with 16299ef9eebSMatthias Springer // smaller rank. 16399ef9eebSMatthias Springer extractedSource = rewriter.create<InsertStridedSliceOp>( 16499ef9eebSMatthias Springer loc, extractedSource, extractedDest, 1657c38fd60SJacques Pienaar getI64SubArray(op.getOffsets(), /* dropFront=*/1), 1667c38fd60SJacques Pienaar getI64SubArray(op.getStrides(), /* dropFront=*/1)); 16799ef9eebSMatthias Springer } 16899ef9eebSMatthias Springer // 4. Insert the extractedSource into the res vector. 169*8e663039SKunwar Grover res = rewriter.create<InsertOp>(loc, extractedSource, res, off); 17099ef9eebSMatthias Springer } 17199ef9eebSMatthias Springer 17299ef9eebSMatthias Springer rewriter.replaceOp(op, res); 17399ef9eebSMatthias Springer return success(); 17499ef9eebSMatthias Springer } 17599ef9eebSMatthias Springer }; 17699ef9eebSMatthias Springer 17759d3a9e0SLei Zhang /// RewritePattern for ExtractStridedSliceOp where source and destination 17859d3a9e0SLei Zhang /// vectors are 1-D. For such cases, we can lower it to a ShuffleOp. 17959d3a9e0SLei Zhang class Convert1DExtractStridedSliceIntoShuffle 18059d3a9e0SLei Zhang : public OpRewritePattern<ExtractStridedSliceOp> { 18159d3a9e0SLei Zhang public: 18259d3a9e0SLei Zhang using OpRewritePattern<ExtractStridedSliceOp>::OpRewritePattern; 18359d3a9e0SLei Zhang 18459d3a9e0SLei Zhang LogicalResult matchAndRewrite(ExtractStridedSliceOp op, 18559d3a9e0SLei Zhang PatternRewriter &rewriter) const override { 18659d3a9e0SLei Zhang auto dstType = op.getType(); 18759d3a9e0SLei Zhang 18859d3a9e0SLei Zhang assert(!op.getOffsets().getValue().empty() && "Unexpected empty offsets"); 18959d3a9e0SLei Zhang 19059d3a9e0SLei Zhang int64_t offset = 1915550c821STres Popp cast<IntegerAttr>(op.getOffsets().getValue().front()).getInt(); 1925550c821STres Popp int64_t size = cast<IntegerAttr>(op.getSizes().getValue().front()).getInt(); 19359d3a9e0SLei Zhang int64_t stride = 1945550c821STres Popp cast<IntegerAttr>(op.getStrides().getValue().front()).getInt(); 19559d3a9e0SLei Zhang 196e7f05526SBenjamin Kramer assert(dstType.getElementType().isSignlessIntOrIndexOrFloat()); 19759d3a9e0SLei Zhang 19859d3a9e0SLei Zhang // Single offset can be more efficiently shuffled. 19959d3a9e0SLei Zhang if (op.getOffsets().getValue().size() != 1) 20059d3a9e0SLei Zhang return failure(); 20159d3a9e0SLei Zhang 20259d3a9e0SLei Zhang SmallVector<int64_t, 4> offsets; 20359d3a9e0SLei Zhang offsets.reserve(size); 20459d3a9e0SLei Zhang for (int64_t off = offset, e = offset + size * stride; off < e; 20559d3a9e0SLei Zhang off += stride) 20659d3a9e0SLei Zhang offsets.push_back(off); 20759d3a9e0SLei Zhang rewriter.replaceOpWithNewOp<ShuffleOp>(op, dstType, op.getVector(), 208b4444dcaSBenjamin Maxwell op.getVector(), offsets); 20959d3a9e0SLei Zhang return success(); 21059d3a9e0SLei Zhang } 21159d3a9e0SLei Zhang }; 21259d3a9e0SLei Zhang 21339c80656SLei Zhang /// For a 1-D ExtractStridedSlice, breaks it down into a chain of Extract ops 21439c80656SLei Zhang /// to extract each element from the source, and then a chain of Insert ops 21539c80656SLei Zhang /// to insert to the target vector. 21639c80656SLei Zhang class Convert1DExtractStridedSliceIntoExtractInsertChain final 21739c80656SLei Zhang : public OpRewritePattern<ExtractStridedSliceOp> { 21839c80656SLei Zhang public: 21939c80656SLei Zhang Convert1DExtractStridedSliceIntoExtractInsertChain( 22039c80656SLei Zhang MLIRContext *context, 22139c80656SLei Zhang std::function<bool(ExtractStridedSliceOp)> controlFn, 22239c80656SLei Zhang PatternBenefit benefit) 22339c80656SLei Zhang : OpRewritePattern(context, benefit), controlFn(std::move(controlFn)) {} 22439c80656SLei Zhang 22539c80656SLei Zhang LogicalResult matchAndRewrite(ExtractStridedSliceOp op, 22639c80656SLei Zhang PatternRewriter &rewriter) const override { 22739c80656SLei Zhang if (controlFn && !controlFn(op)) 22839c80656SLei Zhang return failure(); 22939c80656SLei Zhang 23039c80656SLei Zhang // Only handle 1-D cases. 23139c80656SLei Zhang if (op.getOffsets().getValue().size() != 1) 23239c80656SLei Zhang return failure(); 23339c80656SLei Zhang 23439c80656SLei Zhang int64_t offset = 2355550c821STres Popp cast<IntegerAttr>(op.getOffsets().getValue().front()).getInt(); 2365550c821STres Popp int64_t size = cast<IntegerAttr>(op.getSizes().getValue().front()).getInt(); 23739c80656SLei Zhang int64_t stride = 2385550c821STres Popp cast<IntegerAttr>(op.getStrides().getValue().front()).getInt(); 23939c80656SLei Zhang 24039c80656SLei Zhang Location loc = op.getLoc(); 24139c80656SLei Zhang SmallVector<Value> elements; 24239c80656SLei Zhang elements.reserve(size); 24339c80656SLei Zhang for (int64_t i = offset, e = offset + size * stride; i < e; i += stride) 24439c80656SLei Zhang elements.push_back(rewriter.create<ExtractOp>(loc, op.getVector(), i)); 24539c80656SLei Zhang 24639c80656SLei Zhang Value result = rewriter.create<arith::ConstantOp>( 24739c80656SLei Zhang loc, rewriter.getZeroAttr(op.getType())); 24839c80656SLei Zhang for (int64_t i = 0; i < size; ++i) 24939c80656SLei Zhang result = rewriter.create<InsertOp>(loc, elements[i], result, i); 25039c80656SLei Zhang 25139c80656SLei Zhang rewriter.replaceOp(op, result); 25239c80656SLei Zhang return success(); 25339c80656SLei Zhang } 25439c80656SLei Zhang 25539c80656SLei Zhang private: 25639c80656SLei Zhang std::function<bool(ExtractStridedSliceOp)> controlFn; 25739c80656SLei Zhang }; 25839c80656SLei Zhang 25959d3a9e0SLei Zhang /// RewritePattern for ExtractStridedSliceOp where the source vector is n-D. 260*8e663039SKunwar Grover /// For such cases, we can rewrite it to ExtractOp + lower rank 261*8e663039SKunwar Grover /// ExtractStridedSliceOp + InsertOp for the n-D case. 26259d3a9e0SLei Zhang class DecomposeNDExtractStridedSlice 26399ef9eebSMatthias Springer : public OpRewritePattern<ExtractStridedSliceOp> { 26499ef9eebSMatthias Springer public: 26599ef9eebSMatthias Springer using OpRewritePattern<ExtractStridedSliceOp>::OpRewritePattern; 26699ef9eebSMatthias Springer 26799ef9eebSMatthias Springer void initialize() { 26899ef9eebSMatthias Springer // This pattern creates recursive ExtractStridedSliceOp, but the recursion 26999ef9eebSMatthias Springer // is bounded as the rank is strictly decreasing. 27099ef9eebSMatthias Springer setHasBoundedRewriteRecursion(); 27199ef9eebSMatthias Springer } 27299ef9eebSMatthias Springer 27399ef9eebSMatthias Springer LogicalResult matchAndRewrite(ExtractStridedSliceOp op, 27499ef9eebSMatthias Springer PatternRewriter &rewriter) const override { 27599ef9eebSMatthias Springer auto dstType = op.getType(); 27699ef9eebSMatthias Springer 2777c38fd60SJacques Pienaar assert(!op.getOffsets().getValue().empty() && "Unexpected empty offsets"); 27899ef9eebSMatthias Springer 27999ef9eebSMatthias Springer int64_t offset = 2805550c821STres Popp cast<IntegerAttr>(op.getOffsets().getValue().front()).getInt(); 2815550c821STres Popp int64_t size = cast<IntegerAttr>(op.getSizes().getValue().front()).getInt(); 28299ef9eebSMatthias Springer int64_t stride = 2835550c821STres Popp cast<IntegerAttr>(op.getStrides().getValue().front()).getInt(); 28499ef9eebSMatthias Springer 2851acba8a4SBill Wendling auto loc = op.getLoc(); 28699ef9eebSMatthias Springer auto elemType = dstType.getElementType(); 28799ef9eebSMatthias Springer assert(elemType.isSignlessIntOrIndexOrFloat()); 28899ef9eebSMatthias Springer 28959d3a9e0SLei Zhang // Single offset can be more efficiently shuffled. It's handled in 29059d3a9e0SLei Zhang // Convert1DExtractStridedSliceIntoShuffle. 29159d3a9e0SLei Zhang if (op.getOffsets().getValue().size() == 1) 29259d3a9e0SLei Zhang return failure(); 29399ef9eebSMatthias Springer 29499ef9eebSMatthias Springer // Extract/insert on a lower ranked extract strided slice op. 29599ef9eebSMatthias Springer Value zero = rewriter.create<arith::ConstantOp>( 29699ef9eebSMatthias Springer loc, elemType, rewriter.getZeroAttr(elemType)); 29799ef9eebSMatthias Springer Value res = rewriter.create<SplatOp>(loc, dstType, zero); 29899ef9eebSMatthias Springer for (int64_t off = offset, e = offset + size * stride, idx = 0; off < e; 29999ef9eebSMatthias Springer off += stride, ++idx) { 300*8e663039SKunwar Grover Value one = rewriter.create<ExtractOp>(loc, op.getVector(), off); 30199ef9eebSMatthias Springer Value extracted = rewriter.create<ExtractStridedSliceOp>( 3027c38fd60SJacques Pienaar loc, one, getI64SubArray(op.getOffsets(), /* dropFront=*/1), 3037c38fd60SJacques Pienaar getI64SubArray(op.getSizes(), /* dropFront=*/1), 3047c38fd60SJacques Pienaar getI64SubArray(op.getStrides(), /* dropFront=*/1)); 305*8e663039SKunwar Grover res = rewriter.create<InsertOp>(loc, extracted, res, idx); 30699ef9eebSMatthias Springer } 30799ef9eebSMatthias Springer rewriter.replaceOp(op, res); 30899ef9eebSMatthias Springer return success(); 30999ef9eebSMatthias Springer } 31099ef9eebSMatthias Springer }; 31199ef9eebSMatthias Springer 31239c80656SLei Zhang void vector::populateVectorInsertExtractStridedSliceDecompositionPatterns( 31327cc31b6SNicolas Vasilache RewritePatternSet &patterns, PatternBenefit benefit) { 31459d3a9e0SLei Zhang patterns.add<DecomposeDifferentRankInsertStridedSlice, 31527cc31b6SNicolas Vasilache DecomposeNDExtractStridedSlice>(patterns.getContext(), benefit); 31659d3a9e0SLei Zhang } 31759d3a9e0SLei Zhang 31839c80656SLei Zhang void vector::populateVectorExtractStridedSliceToExtractInsertChainPatterns( 31939c80656SLei Zhang RewritePatternSet &patterns, 32039c80656SLei Zhang std::function<bool(ExtractStridedSliceOp)> controlFn, 32139c80656SLei Zhang PatternBenefit benefit) { 32239c80656SLei Zhang patterns.add<Convert1DExtractStridedSliceIntoExtractInsertChain>( 32339c80656SLei Zhang patterns.getContext(), std::move(controlFn), benefit); 32439c80656SLei Zhang } 32539c80656SLei Zhang 32699ef9eebSMatthias Springer /// Populate the given list with patterns that convert from Vector to LLVM. 32739c80656SLei Zhang void vector::populateVectorInsertExtractStridedSliceTransforms( 32827cc31b6SNicolas Vasilache RewritePatternSet &patterns, PatternBenefit benefit) { 32927cc31b6SNicolas Vasilache populateVectorInsertExtractStridedSliceDecompositionPatterns(patterns, 33027cc31b6SNicolas Vasilache benefit); 33159d3a9e0SLei Zhang patterns.add<ConvertSameRankInsertStridedSliceIntoShuffle, 33227cc31b6SNicolas Vasilache Convert1DExtractStridedSliceIntoShuffle>(patterns.getContext(), 33327cc31b6SNicolas Vasilache benefit); 33499ef9eebSMatthias Springer } 335