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