#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/OpDefinition.h"
+#include "mlir/IR/SymbolTable.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallString.h"
"::mlir::LogicalResult", "verifyType">,
];
+ let extraClassDeclaration = [{
+ //===------------------------------------------------------------------===//
+ // Name
+ //===------------------------------------------------------------------===//
+
+ /// Return the name of the function.
+ StringRef getName() { return SymbolTable::getSymbolName(*this); }
+ }];
let extraSharedClassDeclaration = [{
/// Block list iterator types.
using BlockListType = Region::BlockListType;
-// RUN: mlir-opt %s -test-print-dominance -split-input-file 2>&1 | FileCheck %s
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-print-dominance)" -split-input-file 2>&1 | FileCheck %s
// CHECK-LABEL: Testing : func_condBranch
func @func_condBranch(%cond : i1) {
-// RUN: mlir-opt %s -test-print-liveness -split-input-file 2>&1 | FileCheck %s
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-print-liveness)" -split-input-file 2>&1 | FileCheck %s
// CHECK-LABEL: Testing : func_empty
func @func_empty() {
-// RUN: mlir-opt %s -test-match-reduction -verify-diagnostics -split-input-file
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-match-reduction)" -verify-diagnostics -split-input-file
// Verify that the generic reduction detection utility works on different
// dialects.
-// RUN: mlir-opt %s -test-print-topological-sort 2>&1 | FileCheck %s
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-print-topological-sort)" 2>&1 | FileCheck %s
// CHECK-LABEL: Testing : region
// CHECK: arith.addi {{.*}} : index
-// RUN: mlir-opt %s -split-input-file -test-affine-loop-unswitch | FileCheck %s
+// RUN: mlir-opt %s -split-input-file -pass-pipeline="builtin.func(test-affine-loop-unswitch)" | FileCheck %s
// CHECK-DAG: #[[$SET:.*]] = affine_set<(d0) : (d0 - 2 >= 0)>
-// RUN: mlir-opt %s -test-memref-stride-calculation -o /dev/null | FileCheck %s
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-memref-stride-calculation)" -o /dev/null | FileCheck %s
func @f(%0: index) {
// CHECK-LABEL: Testing: f
-// RUN: mlir-opt %s -test-diagnostic-filter='filters=mysource1' -split-input-file -o - 2>&1 | FileCheck %s
+// RUN: mlir-opt %s -pass-pipeline="builtin.func(test-diagnostic-filter{filters=mysource1})" -split-input-file -o - 2>&1 | FileCheck %s
// This test verifies that diagnostic handler can emit the call stack successfully.
// CHECK-LABEL: Test 'test1'
-// RUN: mlir-opt %s -mlir-disable-threading=true -test-matchers -o /dev/null 2>&1 | FileCheck %s
+// RUN: mlir-opt %s -mlir-disable-threading=true -pass-pipeline="builtin.func(test-matchers)" -o /dev/null 2>&1 | FileCheck %s
func @test1(%a: f32, %b: f32, %c: f32) {
%0 = arith.addf %a, %b: f32
-// RUN: mlir-opt -allow-unregistered-dialect -test-mapping-to-processing-elements %s | FileCheck %s
+// RUN: mlir-opt -allow-unregistered-dialect -pass-pipeline="builtin.func(test-mapping-to-processing-elements)" %s | FileCheck %s
// CHECK: #[[mul_map:.+]] = affine_map<()[s0, s1] -> (s0 * s1)>
// CHECK: #[[add_map:.+]] = affine_map<()[s0, s1] -> (s0 + s1)>
-//===- TestLiveness.cpp - Test liveness construction and information
-//-------===//
+//===- TestLiveness.cpp - Test liveness construction and information ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
namespace {
struct TestLivenessPass
- : public PassWrapper<TestLivenessPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestLivenessPass, InterfacePass<SymbolOpInterface>> {
StringRef getArgument() const final { return "test-print-liveness"; }
StringRef getDescription() const final {
return "Print the contents of a constructed liveness information.";
//===----------------------------------------------------------------------===//
#include "mlir/Analysis/SliceAnalysis.h"
+#include "mlir/IR/FunctionInterfaces.h"
#include "mlir/Pass/Pass.h"
using namespace mlir;
}
struct TestMatchReductionPass
- : public PassWrapper<TestMatchReductionPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestMatchReductionPass,
+ InterfacePass<FunctionOpInterface>> {
StringRef getArgument() const final { return "test-match-reduction"; }
StringRef getDescription() const final {
return "Test the match reduction utility.";
}
void runOnOperation() override {
- FuncOp func = getOperation();
+ FunctionOpInterface func = getOperation();
func->emitRemark("Testing function");
func.walk<WalkOrder::PreOrder>([](Operation *op) {
- if (isa<FuncOp>(op))
+ if (isa<FunctionOpInterface>(op))
return;
// Limit testing to ops with only one region.
/// Checks for out of bound memref access subscripts..
struct TestMemRefBoundCheck
- : public PassWrapper<TestMemRefBoundCheck, OperationPass<FuncOp>> {
+ : public PassWrapper<TestMemRefBoundCheck, OperationPass<>> {
StringRef getArgument() const final { return "test-memref-bound-check"; }
StringRef getDescription() const final {
- return "Check memref access bounds in a Function";
+ return "Check memref access bounds";
}
void runOnOperation() override;
};
} // namespace
void TestMemRefBoundCheck::runOnOperation() {
- getOperation().walk([](Operation *opInst) {
+ getOperation()->walk([](Operation *opInst) {
TypeSwitch<Operation *>(opInst)
.Case<AffineReadOpInterface, AffineWriteOpInterface>(
[](auto op) { (void)boundCheckLoadOrStoreOp(op); });
// TODO: Add common surrounding loop depth-wise dependence checks.
/// Checks dependences between all pairs of memref accesses in a Function.
struct TestMemRefDependenceCheck
- : public PassWrapper<TestMemRefDependenceCheck, OperationPass<FuncOp>> {
+ : public PassWrapper<TestMemRefDependenceCheck, OperationPass<>> {
StringRef getArgument() const final { return "test-memref-dependence-check"; }
StringRef getDescription() const final {
return "Checks dependences between all pairs of memref accesses.";
}
}
-// Walks the Function 'f' adding load and store ops to 'loadsAndStores'.
-// Runs pair-wise dependence checks.
+/// Walks the operation adding load and store ops to 'loadsAndStores'. Runs
+/// pair-wise dependence checks.
void TestMemRefDependenceCheck::runOnOperation() {
// Collect the loads and stores within the function.
loadsAndStores.clear();
- getOperation().walk([&](Operation *op) {
+ getOperation()->walk([&](Operation *op) {
if (isa<AffineLoadOp, AffineStoreOp>(op))
loadsAndStores.push_back(op);
});
namespace {
struct TestMemRefStrideCalculation
- : public PassWrapper<TestMemRefStrideCalculation, OperationPass<FuncOp>> {
+ : public PassWrapper<TestMemRefStrideCalculation,
+ InterfacePass<SymbolOpInterface>> {
StringRef getArgument() const final {
return "test-memref-stride-calculation";
}
namespace {
struct TestTopologicalSortPass
- : public PassWrapper<TestTopologicalSortPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestTopologicalSortPass,
+ InterfacePass<SymbolOpInterface>> {
StringRef getArgument() const final { return "test-print-topological-sort"; }
StringRef getDescription() const final {
return "Print operations in topological order";
/// This pass applies the permutation on the first maximal perfect nest.
struct TestAffineLoopUnswitching
- : public PassWrapper<TestAffineLoopUnswitching, OperationPass<FuncOp>> {
+ : public PassWrapper<TestAffineLoopUnswitching, OperationPass<>> {
StringRef getArgument() const final { return PASS_NAME; }
StringRef getDescription() const final {
return "Tests affine loop unswitching / if/else hoisting";
// Each hoisting invalidates a lot of IR around. Just stop the walk after the
// first if/else hoisting, and repeat until no more hoisting can be done, or
// the maximum number of iterations have been run.
- auto func = getOperation();
+ Operation *op = getOperation();
unsigned i = 0;
do {
auto walkFn = [](AffineIfOp op) {
return succeeded(hoistAffineIfOp(op)) ? WalkResult::interrupt()
: WalkResult::advance();
};
- if (func.walk(walkFn).wasInterrupted())
+ if (op->walk(walkFn).wasInterrupted())
break;
} while (++i < kMaxIterations);
}
namespace {
class TestLoopMappingPass
- : public PassWrapper<TestLoopMappingPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestLoopMappingPass, OperationPass<>> {
public:
StringRef getArgument() const final {
return "test-mapping-to-processing-elements";
}
void runOnOperation() override {
- FuncOp func = getOperation();
-
// SSA values for the transformation are created out of thin air by
// unregistered "new_processor_id_and_range" operations. This is enough to
// emulate mapping conditions.
SmallVector<Value, 8> processorIds, numProcessors;
- func.walk([&processorIds, &numProcessors](Operation *op) {
+ getOperation()->walk([&processorIds, &numProcessors](Operation *op) {
if (op->getName().getStringRef() != "new_processor_id_and_range")
return;
processorIds.push_back(op->getResult(0));
numProcessors.push_back(op->getResult(1));
});
- func.walk([&processorIds, &numProcessors](scf::ForOp op) {
+ getOperation()->walk([&processorIds, &numProcessors](scf::ForOp op) {
// Ignore nested loops.
if (op->getParentRegion()->getParentOfType<scf::ForOp>())
return;
using namespace mlir;
-static llvm::cl::OptionCategory clOptionsCategory(PASS_NAME " options");
-
namespace {
/// This pass applies the permutation on the first maximal perfect nest.
struct TestLoopPermutation
- : public PassWrapper<TestLoopPermutation, OperationPass<FuncOp>> {
+ : public PassWrapper<TestLoopPermutation, OperationPass<>> {
StringRef getArgument() const final { return PASS_NAME; }
StringRef getDescription() const final {
return "Tests affine loop permutation utility";
SmallVector<unsigned, 4> permMap(permList.begin(), permList.end());
SmallVector<AffineForOp, 2> forOps;
- getOperation().walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
+ getOperation()->walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
for (auto forOp : forOps) {
SmallVector<AffineForOp, 6> nest;
/// a greedy mapping strategy.
class TestGpuGreedyParallelLoopMappingPass
: public PassWrapper<TestGpuGreedyParallelLoopMappingPass,
- OperationPass<FuncOp>> {
+ OperationPass<>> {
StringRef getArgument() const final {
return "test-gpu-greedy-parallel-loop-mapping";
}
return "Greedily maps all parallel loops to gpu hardware ids.";
}
void runOnOperation() override {
- Operation *op = getOperation();
- for (Region ®ion : op->getRegions())
+ for (Region ®ion : getOperation()->getRegions())
greedilyMapParallelSCFToGPU(region);
}
};
namespace {
struct TestPadFusionPass
- : public PassWrapper<TestPadFusionPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestPadFusionPass, OperationPass<>> {
void getDependentDialects(DialectRegistry ®istry) const override {
registry
void runOnOperation() override {
MLIRContext *context = &getContext();
- FuncOp funcOp = getOperation();
RewritePatternSet patterns(context);
linalg::populateFuseTensorPadWithProducerLinalgOpPatterns(patterns);
- if (failed(applyPatternsAndFoldGreedily(funcOp.getBody(),
- std::move(patterns))))
+ if (failed(
+ applyPatternsAndFoldGreedily(getOperation(), std::move(patterns))))
return signalPassFailure();
}
};
namespace {
struct TestMathAlgebraicSimplificationPass
- : public PassWrapper<TestMathAlgebraicSimplificationPass,
- OperationPass<FuncOp>> {
+ : public PassWrapper<TestMathAlgebraicSimplificationPass, OperationPass<>> {
void runOnOperation() override;
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<vector::VectorDialect, math::MathDialect>();
namespace {
struct TestExpandTanhPass
- : public PassWrapper<TestExpandTanhPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestExpandTanhPass, OperationPass<>> {
void runOnOperation() override;
StringRef getArgument() const final { return "test-expand-tanh"; }
StringRef getDescription() const final { return "Test expanding tanh"; }
namespace {
struct TestMathPolynomialApproximationPass
- : public PassWrapper<TestMathPolynomialApproximationPass,
- OperationPass<FuncOp>> {
+ : public PassWrapper<TestMathPolynomialApproximationPass, OperationPass<>> {
TestMathPolynomialApproximationPass() = default;
TestMathPolynomialApproximationPass(
const TestMathPolynomialApproximationPass &pass)
namespace {
struct TestComposeSubViewPass
- : public PassWrapper<TestComposeSubViewPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestComposeSubViewPass, OperationPass<>> {
StringRef getArgument() const final { return "test-compose-subview"; }
StringRef getDescription() const final {
return "Test combining composed subviews";
namespace {
struct TestMultiBufferingPass
- : public PassWrapper<TestMultiBufferingPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestMultiBufferingPass, OperationPass<>> {
TestMultiBufferingPass() = default;
TestMultiBufferingPass(const TestMultiBufferingPass &pass)
: PassWrapper(pass) {}
void TestMultiBufferingPass::runOnOperation() {
SmallVector<memref::AllocOp> allocs;
- getOperation().walk(
+ getOperation()->walk(
[&allocs](memref::AllocOp alloc) { allocs.push_back(alloc); });
for (memref::AllocOp alloc : allocs)
(void)multiBuffer(alloc, multiplier);
// Extracts fixed-range loops for top-level loop nests with ranges defined in
// the pass constructor. Assumes loops are permutable.
class SimpleParametricLoopTilingPass
- : public PassWrapper<SimpleParametricLoopTilingPass,
- OperationPass<FuncOp>> {
+ : public PassWrapper<SimpleParametricLoopTilingPass, OperationPass<>> {
public:
StringRef getArgument() const final {
return "test-extract-fixed-outer-loops";
}
void runOnOperation() override {
- FuncOp func = getOperation();
- func.walk([this](scf::ForOp op) {
+ getOperation()->walk([this](scf::ForOp op) {
// Ignore nested loops.
if (op->getParentRegion()->getParentOfType<scf::ForOp>())
return;
}
class TestLoopUnrollingPass
- : public PassWrapper<TestLoopUnrollingPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestLoopUnrollingPass, OperationPass<>> {
public:
StringRef getArgument() const final { return "test-loop-unrolling"; }
StringRef getDescription() const final {
}
void runOnOperation() override {
- FuncOp func = getOperation();
SmallVector<scf::ForOp, 4> loops;
- func.walk([&](scf::ForOp forOp) {
+ getOperation()->walk([&](scf::ForOp forOp) {
if (getNestingDepth(forOp) == loopDepth)
loops.push_back(forOp);
});
namespace {
struct TestTensorTransforms
- : public PassWrapper<TestTensorTransforms, OperationPass<FuncOp>> {
+ : public PassWrapper<TestTensorTransforms, OperationPass<>> {
TestTensorTransforms() = default;
TestTensorTransforms(const TestTensorTransforms &pass) : PassWrapper(pass) {}
};
} // namespace
-static void applySplitPaddingPatterns(FuncOp funcOp) {
- RewritePatternSet patterns(funcOp.getContext());
+static void applySplitPaddingPatterns(Operation *rootOp) {
+ RewritePatternSet patterns(rootOp->getContext());
tensor::populateSplitPaddingPatterns(patterns);
- (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
+ (void)applyPatternsAndFoldGreedily(rootOp, std::move(patterns));
}
-static void applyFoldConstantExtractSlicePatterns(FuncOp funcOp) {
- RewritePatternSet patterns(funcOp.getContext());
+static void applyFoldConstantExtractSlicePatterns(Operation *rootOp) {
+ RewritePatternSet patterns(rootOp->getContext());
tensor::ControlConstantExtractSliceFusionFn controlFn =
[](tensor::ExtractSliceOp op) {
if (!op.source().hasOneUse())
};
tensor::populateFoldConstantExtractSlicePatterns(patterns, controlFn);
- (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
+ (void)applyPatternsAndFoldGreedily(rootOp, std::move(patterns));
}
void TestTensorTransforms::runOnOperation() {
- FuncOp func = getOperation();
+ Operation *rootOp = getOperation();
if (testSplitPaddingPatterns)
- applySplitPaddingPatterns(func);
+ applySplitPaddingPatterns(rootOp);
if (testFoldConstantExtractSlice)
- applyFoldConstantExtractSlicePatterns(func);
+ applyFoldConstantExtractSlicePatterns(rootOp);
}
namespace mlir {
namespace {
struct TestDiagnosticFilterPass
- : public PassWrapper<TestDiagnosticFilterPass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestDiagnosticFilterPass,
+ InterfacePass<SymbolOpInterface>> {
StringRef getArgument() const final { return "test-diagnostic-filter"; }
StringRef getDescription() const final {
return "Test diagnostic filtering support.";
};
struct TestDominancePass
- : public PassWrapper<TestDominancePass, OperationPass<FuncOp>> {
+ : public PassWrapper<TestDominancePass, InterfacePass<SymbolOpInterface>> {
StringRef getArgument() const final { return "test-print-dominance"; }
StringRef getDescription() const final {
return "Print the dominance information for multiple regions.";
//===----------------------------------------------------------------------===//
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/FunctionInterfaces.h"
#include "mlir/Pass/Pass.h"
using namespace mlir;
namespace {
-/// This is a test pass for verifying FuncOp's insertArgument method.
+/// This is a test pass for verifying FunctionOpInterface's insertArgument
+/// method.
struct TestFuncInsertArg
: public PassWrapper<TestFuncInsertArg, OperationPass<ModuleOp>> {
StringRef getArgument() const final { return "test-func-insert-arg"; }
auto module = getOperation();
UnknownLoc unknownLoc = UnknownLoc::get(module.getContext());
- for (FuncOp func : module.getOps<FuncOp>()) {
+ for (auto func : module.getOps<FunctionOpInterface>()) {
auto inserts = func->getAttrOfType<ArrayAttr>("test.insert_args");
if (!inserts || inserts.empty())
continue;
}
};
-/// This is a test pass for verifying FuncOp's insertResult method.
+/// This is a test pass for verifying FunctionOpInterface's insertResult method.
struct TestFuncInsertResult
: public PassWrapper<TestFuncInsertResult, OperationPass<ModuleOp>> {
StringRef getArgument() const final { return "test-func-insert-result"; }
void runOnOperation() override {
auto module = getOperation();
- for (FuncOp func : module.getOps<FuncOp>()) {
+ for (auto func : module.getOps<FunctionOpInterface>()) {
auto inserts = func->getAttrOfType<ArrayAttr>("test.insert_results");
if (!inserts || inserts.empty())
continue;
}
};
-/// This is a test pass for verifying FuncOp's eraseArgument method.
+/// This is a test pass for verifying FunctionOpInterface's eraseArgument
+/// method.
struct TestFuncEraseArg
: public PassWrapper<TestFuncEraseArg, OperationPass<ModuleOp>> {
StringRef getArgument() const final { return "test-func-erase-arg"; }
void runOnOperation() override {
auto module = getOperation();
- for (FuncOp func : module.getOps<FuncOp>()) {
+ for (auto func : module.getOps<FunctionOpInterface>()) {
BitVector indicesToErase(func.getNumArguments());
for (auto argIndex : llvm::seq<int>(0, func.getNumArguments()))
if (func.getArgAttr(argIndex, "test.erase_this_arg"))
}
};
-/// This is a test pass for verifying FuncOp's eraseResult method.
+/// This is a test pass for verifying FunctionOpInterface's eraseResult method.
struct TestFuncEraseResult
: public PassWrapper<TestFuncEraseResult, OperationPass<ModuleOp>> {
StringRef getArgument() const final { return "test-func-erase-result"; }
void runOnOperation() override {
auto module = getOperation();
- for (FuncOp func : module.getOps<FuncOp>()) {
+ for (auto func : module.getOps<FunctionOpInterface>()) {
BitVector indicesToErase(func.getNumResults());
for (auto resultIndex : llvm::seq<int>(0, func.getNumResults()))
if (func.getResultAttr(resultIndex, "test.erase_this_result"))
}
};
-/// This is a test pass for verifying FuncOp's setType method.
+/// This is a test pass for verifying FunctionOpInterface's setType method.
struct TestFuncSetType
: public PassWrapper<TestFuncSetType, OperationPass<ModuleOp>> {
StringRef getArgument() const final { return "test-func-set-type"; }
- StringRef getDescription() const final { return "Test FuncOp::setType."; }
+ StringRef getDescription() const final {
+ return "Test FunctionOpInterface::setType.";
+ }
void runOnOperation() override {
auto module = getOperation();
SymbolTable symbolTable(module);
- for (FuncOp func : module.getOps<FuncOp>()) {
+ for (auto func : module.getOps<FunctionOpInterface>()) {
auto sym = func->getAttrOfType<FlatSymbolRefAttr>("test.set_type_from");
if (!sym)
continue;
- func.setType(symbolTable.lookup<FuncOp>(sym.getValue()).getType());
+ func.setType(
+ symbolTable.lookup<FunctionOpInterface>(sym.getValue()).getType());
}
}
};
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/FunctionInterfaces.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Pass/Pass.h"
namespace {
/// This is a test pass for verifying matchers.
-struct TestMatchers : public PassWrapper<TestMatchers, OperationPass<FuncOp>> {
+struct TestMatchers
+ : public PassWrapper<TestMatchers, InterfacePass<FunctionOpInterface>> {
void runOnOperation() override;
StringRef getArgument() const final { return "test-matchers"; }
StringRef getDescription() const final {
// This could be done better but is not worth the variadic template trouble.
template <typename Matcher>
-static unsigned countMatches(FuncOp f, Matcher &matcher) {
+static unsigned countMatches(FunctionOpInterface f, Matcher &matcher) {
unsigned count = 0;
f.walk([&count, &matcher](Operation *op) {
if (matcher.match(op))
using mlir::matchers::m_Any;
using mlir::matchers::m_Val;
-static void test1(FuncOp f) {
+static void test1(FunctionOpInterface f) {
assert(f.getNumArguments() == 3 && "matcher test funcs must have 3 args");
auto a = m_Val(f.getArgument(0));
<< countMatches(f, p17) << " times\n";
}
-void test2(FuncOp f) {
+void test2(FunctionOpInterface f) {
auto a = m_Val(f.getArgument(0));
FloatAttr floatAttr;
auto p =
op->setLoc(
OpaqueLoc::get<MyLocation *>(myLocs.back().get(), &getContext()));
- if (isa<FuncOp>(op) || op->hasTrait<OpTrait::IsTerminator>())
+ if (isa<ModuleOp>(op->getParentOp()) ||
+ op->hasTrait<OpTrait::IsTerminator>())
return;
OpBuilder builder(op);
/// Tests erasure callbacks that skip the walk.
static void testSkipErasureCallbacks(Operation *op) {
auto skipOpErasure = [](Operation *op) {
- // Do not erase module and function op. Otherwise there wouldn't be too
- // much to test in pre-order.
- if (isa<ModuleOp>(op) || isa<FuncOp>(op))
+ // Do not erase module and module children operations. Otherwise, there
+ // wouldn't be too much to test in pre-order.
+ if (isa<ModuleOp>(op) || isa<ModuleOp>(op->getParentOp()))
return WalkResult::advance();
llvm::outs() << "Erasing ";
return WalkResult::skip();
};
auto skipBlockErasure = [](Block *block) {
- // Do not erase module and function blocks. Otherwise there wouldn't be
- // too much to test in pre-order.
+ // Do not erase module and module children blocks. Otherwise there wouldn't
+ // be too much to test in pre-order.
Operation *parentOp = block->getParentOp();
- if (isa<ModuleOp>(parentOp) || isa<FuncOp>(parentOp))
+ if (isa<ModuleOp>(parentOp) || isa<ModuleOp>(parentOp->getParentOp()))
return WalkResult::advance();
llvm::outs() << "Erasing ";
namespace {
/// Simple constant folding pass.
struct TestConstantFold
- : public PassWrapper<TestConstantFold, OperationPass<FuncOp>> {
+ : public PassWrapper<TestConstantFold, OperationPass<>> {
StringRef getArgument() const final { return "test-constant-fold"; }
StringRef getDescription() const final {
return "Test operation constant folding";
}
- // All constants in the function post folding.
- SmallVector<Operation *, 8> existingConstants;
+ // All constants in the operation post folding.
+ SmallVector<Operation *> existingConstants;
void foldOperation(Operation *op, OperationFolder &helper);
void runOnOperation() override;
(void)helper.tryToFold(op, processGeneratedConstants);
}
-// For now, we do a simple top-down pass over a function folding constants. We
-// don't handle conditional control flow, block arguments, folding conditional
-// branches, or anything else fancy.
void TestConstantFold::runOnOperation() {
existingConstants.clear();
- // Collect and fold the operations within the function.
+ // Collect and fold the operations within the operation.
SmallVector<Operation *, 8> ops;
- getOperation().walk([&](Operation *op) { ops.push_back(op); });
+ getOperation()->walk([&](Operation *op) { ops.push_back(op); });
// Fold the constants in reverse so that the last generated constants from
// folding are at the beginning. This creates somewhat of a linear ordering to
foldOperation(op, helper);
// By the time we are done, we may have simplified a bunch of code, leaving
- // around dead constants. Check for them now and remove them.
+ // around dead constants. Check for them now and remove them.
for (auto *cst : existingConstants) {
if (cst->use_empty())
cst->erase();