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