1 //===- TestConstantFold.cpp - Pass to test constant folding ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "mlir/Dialect/Affine/IR/AffineOps.h" 10 #include "mlir/Dialect/StandardOps/IR/Ops.h" 11 #include "mlir/IR/Builders.h" 12 #include "mlir/IR/BuiltinOps.h" 13 #include "mlir/Pass/Pass.h" 14 #include "mlir/Transforms/FoldUtils.h" 15 #include "mlir/Transforms/Passes.h" 16 #include "mlir/Transforms/Utils.h" 17 18 using namespace mlir; 19 20 namespace { 21 /// Simple constant folding pass. 22 struct TestConstantFold : public PassWrapper<TestConstantFold, FunctionPass> { 23 // All constants in the function post folding. 24 SmallVector<Operation *, 8> existingConstants; 25 26 void foldOperation(Operation *op, OperationFolder &helper); 27 void runOnFunction() override; 28 }; 29 } // end anonymous namespace 30 31 void TestConstantFold::foldOperation(Operation *op, OperationFolder &helper) { 32 auto processGeneratedConstants = [this](Operation *op) { 33 existingConstants.push_back(op); 34 }; 35 36 // Attempt to fold the specified operation, including handling unused or 37 // duplicated constants. 38 (void)helper.tryToFold(op, processGeneratedConstants); 39 } 40 41 // For now, we do a simple top-down pass over a function folding constants. We 42 // don't handle conditional control flow, block arguments, folding conditional 43 // branches, or anything else fancy. 44 void TestConstantFold::runOnFunction() { 45 existingConstants.clear(); 46 47 // Collect and fold the operations within the function. 48 SmallVector<Operation *, 8> ops; 49 getFunction().walk([&](Operation *op) { ops.push_back(op); }); 50 51 // Fold the constants in reverse so that the last generated constants from 52 // folding are at the beginning. This creates somewhat of a linear ordering to 53 // the newly generated constants that matches the operation order and improves 54 // the readability of test cases. 55 OperationFolder helper(&getContext()); 56 for (Operation *op : llvm::reverse(ops)) 57 foldOperation(op, helper); 58 59 // By the time we are done, we may have simplified a bunch of code, leaving 60 // around dead constants. Check for them now and remove them. 61 for (auto *cst : existingConstants) { 62 if (cst->use_empty()) 63 cst->erase(); 64 } 65 } 66 67 namespace mlir { 68 namespace test { 69 void registerTestConstantFold() { 70 PassRegistration<TestConstantFold>("test-constant-fold", 71 "Test operation constant folding"); 72 } 73 } // namespace test 74 } // namespace mlir 75