1 //===- SimplifyAffineStructures.cpp ---------------------------------------===// 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 // This file implements a pass to simplify affine structures. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "mlir/Analysis/Utils.h" 14 #include "mlir/Dialect/Affine/Passes.h" 15 #include "mlir/IR/IntegerSet.h" 16 #include "mlir/Pass/Pass.h" 17 #include "mlir/Transforms/Utils.h" 18 19 #define DEBUG_TYPE "simplify-affine-structure" 20 21 using namespace mlir; 22 23 namespace { 24 25 /// Simplifies affine maps and sets appearing in the operations of the Function. 26 /// This part is mainly to test the simplifyAffineExpr method. In addition, 27 /// all memrefs with non-trivial layout maps are converted to ones with trivial 28 /// identity layout ones. 29 struct SimplifyAffineStructures 30 : public FunctionPass<SimplifyAffineStructures> { 31 /// Include the generated pass utilities. 32 #define GEN_PASS_SimplifyAffineStructures 33 #include "mlir/Dialect/Affine/Passes.h.inc" 34 35 void runOnFunction() override; 36 37 /// Utility to simplify an affine attribute and update its entry in the parent 38 /// operation if necessary. 39 template <typename AttributeT> 40 void simplifyAndUpdateAttribute(Operation *op, Identifier name, 41 AttributeT attr) { 42 auto &simplified = simplifiedAttributes[attr]; 43 if (simplified == attr) 44 return; 45 46 // This is a newly encountered attribute. 47 if (!simplified) { 48 // Try to simplify the value of the attribute. 49 auto value = attr.getValue(); 50 auto simplifiedValue = simplify(value); 51 if (simplifiedValue == value) { 52 simplified = attr; 53 return; 54 } 55 simplified = AttributeT::get(simplifiedValue); 56 } 57 58 // Simplification was successful, so update the attribute. 59 op->setAttr(name, simplified); 60 } 61 62 IntegerSet simplify(IntegerSet set) { return simplifyIntegerSet(set); } 63 64 /// Performs basic affine map simplifications. 65 AffineMap simplify(AffineMap map) { 66 MutableAffineMap mMap(map); 67 mMap.simplify(); 68 return mMap.getAffineMap(); 69 } 70 71 DenseMap<Attribute, Attribute> simplifiedAttributes; 72 }; 73 74 } // end anonymous namespace 75 76 std::unique_ptr<OpPassBase<FuncOp>> mlir::createSimplifyAffineStructuresPass() { 77 return std::make_unique<SimplifyAffineStructures>(); 78 } 79 80 void SimplifyAffineStructures::runOnFunction() { 81 auto func = getFunction(); 82 simplifiedAttributes.clear(); 83 func.walk([&](Operation *opInst) { 84 for (auto attr : opInst->getAttrs()) { 85 if (auto mapAttr = attr.second.dyn_cast<AffineMapAttr>()) 86 simplifyAndUpdateAttribute(opInst, attr.first, mapAttr); 87 else if (auto setAttr = attr.second.dyn_cast<IntegerSetAttr>()) 88 simplifyAndUpdateAttribute(opInst, attr.first, setAttr); 89 } 90 }); 91 92 // Turn memrefs' non-identity layouts maps into ones with identity. Collect 93 // alloc ops first and then process since normalizeMemRef replaces/erases ops 94 // during memref rewriting. 95 SmallVector<AllocOp, 4> allocOps; 96 func.walk([&](AllocOp op) { allocOps.push_back(op); }); 97 for (auto allocOp : allocOps) { 98 normalizeMemRef(allocOp); 99 } 100 } 101