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 void runOnFunction() override; 32 33 /// Utility to simplify an affine attribute and update its entry in the parent 34 /// operation if necessary. 35 template <typename AttributeT> 36 void simplifyAndUpdateAttribute(Operation *op, Identifier name, 37 AttributeT attr) { 38 auto &simplified = simplifiedAttributes[attr]; 39 if (simplified == attr) 40 return; 41 42 // This is a newly encountered attribute. 43 if (!simplified) { 44 // Try to simplify the value of the attribute. 45 auto value = attr.getValue(); 46 auto simplifiedValue = simplify(value); 47 if (simplifiedValue == value) { 48 simplified = attr; 49 return; 50 } 51 simplified = AttributeT::get(simplifiedValue); 52 } 53 54 // Simplification was successful, so update the attribute. 55 op->setAttr(name, simplified); 56 } 57 58 IntegerSet simplify(IntegerSet set) { return simplifyIntegerSet(set); } 59 60 /// Performs basic affine map simplifications. 61 AffineMap simplify(AffineMap map) { 62 MutableAffineMap mMap(map); 63 mMap.simplify(); 64 return mMap.getAffineMap(); 65 } 66 67 DenseMap<Attribute, Attribute> simplifiedAttributes; 68 }; 69 70 } // end anonymous namespace 71 72 std::unique_ptr<OpPassBase<FuncOp>> mlir::createSimplifyAffineStructuresPass() { 73 return std::make_unique<SimplifyAffineStructures>(); 74 } 75 76 void SimplifyAffineStructures::runOnFunction() { 77 auto func = getFunction(); 78 simplifiedAttributes.clear(); 79 func.walk([&](Operation *opInst) { 80 for (auto attr : opInst->getAttrs()) { 81 if (auto mapAttr = attr.second.dyn_cast<AffineMapAttr>()) 82 simplifyAndUpdateAttribute(opInst, attr.first, mapAttr); 83 else if (auto setAttr = attr.second.dyn_cast<IntegerSetAttr>()) 84 simplifyAndUpdateAttribute(opInst, attr.first, setAttr); 85 } 86 }); 87 88 // Turn memrefs' non-identity layouts maps into ones with identity. Collect 89 // alloc ops first and then process since normalizeMemRef replaces/erases ops 90 // during memref rewriting. 91 SmallVector<AllocOp, 4> allocOps; 92 func.walk([&](AllocOp op) { allocOps.push_back(op); }); 93 for (auto allocOp : allocOps) { 94 normalizeMemRef(allocOp); 95 } 96 } 97 98 static PassRegistration<SimplifyAffineStructures> 99 pass("simplify-affine-structures", 100 "Simplify affine expressions in maps/sets and normalize memrefs"); 101