10a391c60SMaheshRavishankar //===- TestSlicing.cpp - Testing slice functionality ----------------------===// 20a391c60SMaheshRavishankar // 30a391c60SMaheshRavishankar // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40a391c60SMaheshRavishankar // See https://llvm.org/LICENSE.txt for license information. 50a391c60SMaheshRavishankar // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60a391c60SMaheshRavishankar // 70a391c60SMaheshRavishankar //===----------------------------------------------------------------------===// 80a391c60SMaheshRavishankar // 90a391c60SMaheshRavishankar // This file implements a simple testing pass for slicing. 100a391c60SMaheshRavishankar // 110a391c60SMaheshRavishankar //===----------------------------------------------------------------------===// 120a391c60SMaheshRavishankar 130a391c60SMaheshRavishankar #include "mlir/Analysis/SliceAnalysis.h" 140a391c60SMaheshRavishankar #include "mlir/Dialect/Linalg/IR/LinalgOps.h" 150a391c60SMaheshRavishankar #include "mlir/Dialect/StandardOps/IR/Ops.h" 160a391c60SMaheshRavishankar #include "mlir/IR/BlockAndValueMapping.h" 1765fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h" 180a391c60SMaheshRavishankar #include "mlir/IR/PatternMatch.h" 190a391c60SMaheshRavishankar #include "mlir/Pass/Pass.h" 200a391c60SMaheshRavishankar #include "mlir/Support/LLVM.h" 210a391c60SMaheshRavishankar 220a391c60SMaheshRavishankar using namespace mlir; 230a391c60SMaheshRavishankar 240a391c60SMaheshRavishankar /// Create a function with the same signature as the parent function of `op` 250a391c60SMaheshRavishankar /// with name being the function name and a `suffix`. 260a391c60SMaheshRavishankar static LogicalResult createBackwardSliceFunction(Operation *op, 270a391c60SMaheshRavishankar StringRef suffix) { 280a391c60SMaheshRavishankar FuncOp parentFuncOp = op->getParentOfType<FuncOp>(); 290a391c60SMaheshRavishankar OpBuilder builder(parentFuncOp); 300a391c60SMaheshRavishankar Location loc = op->getLoc(); 310a391c60SMaheshRavishankar std::string clonedFuncOpName = parentFuncOp.getName().str() + suffix.str(); 320a391c60SMaheshRavishankar FuncOp clonedFuncOp = 330a391c60SMaheshRavishankar builder.create<FuncOp>(loc, clonedFuncOpName, parentFuncOp.getType()); 340a391c60SMaheshRavishankar BlockAndValueMapping mapper; 350a391c60SMaheshRavishankar builder.setInsertionPointToEnd(clonedFuncOp.addEntryBlock()); 360a391c60SMaheshRavishankar for (auto arg : enumerate(parentFuncOp.getArguments())) 370a391c60SMaheshRavishankar mapper.map(arg.value(), clonedFuncOp.getArgument(arg.index())); 384efb7754SRiver Riddle SetVector<Operation *> slice; 390a391c60SMaheshRavishankar getBackwardSlice(op, &slice); 400a391c60SMaheshRavishankar for (Operation *slicedOp : slice) 410a391c60SMaheshRavishankar builder.clone(*slicedOp, mapper); 420a391c60SMaheshRavishankar builder.create<ReturnOp>(loc); 430a391c60SMaheshRavishankar return success(); 440a391c60SMaheshRavishankar } 450a391c60SMaheshRavishankar 460a391c60SMaheshRavishankar namespace { 470a391c60SMaheshRavishankar /// Pass to test slice generated from slice analysis. 480a391c60SMaheshRavishankar struct SliceAnalysisTestPass 490a391c60SMaheshRavishankar : public PassWrapper<SliceAnalysisTestPass, OperationPass<ModuleOp>> { 50*b5e22e6dSMehdi Amini StringRef getArgument() const final { return "slice-analysis-test"; } 51*b5e22e6dSMehdi Amini StringRef getDescription() const final { 52*b5e22e6dSMehdi Amini return "Test Slice analysis functionality."; 53*b5e22e6dSMehdi Amini } 540a391c60SMaheshRavishankar void runOnOperation() override; 550a391c60SMaheshRavishankar SliceAnalysisTestPass() = default; 560a391c60SMaheshRavishankar SliceAnalysisTestPass(const SliceAnalysisTestPass &) {} 570a391c60SMaheshRavishankar }; 580a391c60SMaheshRavishankar } // namespace 590a391c60SMaheshRavishankar 600a391c60SMaheshRavishankar void SliceAnalysisTestPass::runOnOperation() { 610a391c60SMaheshRavishankar ModuleOp module = getOperation(); 620a391c60SMaheshRavishankar auto funcOps = module.getOps<FuncOp>(); 630a391c60SMaheshRavishankar unsigned opNum = 0; 640a391c60SMaheshRavishankar for (auto funcOp : funcOps) { 650a391c60SMaheshRavishankar // TODO: For now this is just looking for Linalg ops. It can be generalized 660a391c60SMaheshRavishankar // to look for other ops using flags. 670a391c60SMaheshRavishankar funcOp.walk([&](Operation *op) { 680a391c60SMaheshRavishankar if (!isa<linalg::LinalgOp>(op)) 690a391c60SMaheshRavishankar return WalkResult::advance(); 700a391c60SMaheshRavishankar std::string append = 710a391c60SMaheshRavishankar std::string("__backward_slice__") + std::to_string(opNum); 72e21adfa3SRiver Riddle (void)createBackwardSliceFunction(op, append); 730a391c60SMaheshRavishankar opNum++; 740a391c60SMaheshRavishankar return WalkResult::advance(); 750a391c60SMaheshRavishankar }); 760a391c60SMaheshRavishankar } 770a391c60SMaheshRavishankar } 780a391c60SMaheshRavishankar 790a391c60SMaheshRavishankar namespace mlir { 800a391c60SMaheshRavishankar void registerSliceAnalysisTestPass() { 81*b5e22e6dSMehdi Amini PassRegistration<SliceAnalysisTestPass>(); 820a391c60SMaheshRavishankar } 830a391c60SMaheshRavishankar } // namespace mlir 84