github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Analysis/TestMemRefDependenceCheck.cpp (about) 1 //===- TestMemRefDependenceCheck.cpp - Test dep analysis ------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 // 18 // This file implements a pass to run pair-wise memref access dependence checks. 19 // 20 //===----------------------------------------------------------------------===// 21 22 #include "mlir/Analysis/AffineAnalysis.h" 23 #include "mlir/Analysis/AffineStructures.h" 24 #include "mlir/Analysis/Passes.h" 25 #include "mlir/Analysis/Utils.h" 26 #include "mlir/Dialect/AffineOps/AffineOps.h" 27 #include "mlir/Dialect/StandardOps/Ops.h" 28 #include "mlir/IR/Builders.h" 29 #include "mlir/Pass/Pass.h" 30 #include "llvm/Support/Debug.h" 31 32 #define DEBUG_TYPE "test-memref-dependence-check" 33 34 using namespace mlir; 35 36 namespace { 37 38 // TODO(andydavis) Add common surrounding loop depth-wise dependence checks. 39 /// Checks dependences between all pairs of memref accesses in a Function. 40 struct TestMemRefDependenceCheck 41 : public FunctionPass<TestMemRefDependenceCheck> { 42 SmallVector<Operation *, 4> loadsAndStores; 43 void runOnFunction() override; 44 }; 45 46 } // end anonymous namespace 47 48 FunctionPassBase *mlir::createTestMemRefDependenceCheckPass() { 49 return new TestMemRefDependenceCheck(); 50 } 51 52 // Returns a result string which represents the direction vector (if there was 53 // a dependence), returns the string "false" otherwise. 54 static std::string 55 getDirectionVectorStr(bool ret, unsigned numCommonLoops, unsigned loopNestDepth, 56 ArrayRef<DependenceComponent> dependenceComponents) { 57 if (!ret) 58 return "false"; 59 if (dependenceComponents.empty() || loopNestDepth > numCommonLoops) 60 return "true"; 61 std::string result; 62 for (unsigned i = 0, e = dependenceComponents.size(); i < e; ++i) { 63 std::string lbStr = "-inf"; 64 if (dependenceComponents[i].lb.hasValue() && 65 dependenceComponents[i].lb.getValue() != 66 std::numeric_limits<int64_t>::min()) 67 lbStr = std::to_string(dependenceComponents[i].lb.getValue()); 68 69 std::string ubStr = "+inf"; 70 if (dependenceComponents[i].ub.hasValue() && 71 dependenceComponents[i].ub.getValue() != 72 std::numeric_limits<int64_t>::max()) 73 ubStr = std::to_string(dependenceComponents[i].ub.getValue()); 74 75 result += "[" + lbStr + ", " + ubStr + "]"; 76 } 77 return result; 78 } 79 80 // For each access in 'loadsAndStores', runs a depence check between this 81 // "source" access and all subsequent "destination" accesses in 82 // 'loadsAndStores'. Emits the result of the dependence check as a note with 83 // the source access. 84 static void checkDependences(ArrayRef<Operation *> loadsAndStores) { 85 for (unsigned i = 0, e = loadsAndStores.size(); i < e; ++i) { 86 auto *srcOpInst = loadsAndStores[i]; 87 MemRefAccess srcAccess(srcOpInst); 88 for (unsigned j = 0; j < e; ++j) { 89 auto *dstOpInst = loadsAndStores[j]; 90 MemRefAccess dstAccess(dstOpInst); 91 92 unsigned numCommonLoops = 93 getNumCommonSurroundingLoops(*srcOpInst, *dstOpInst); 94 for (unsigned d = 1; d <= numCommonLoops + 1; ++d) { 95 FlatAffineConstraints dependenceConstraints; 96 llvm::SmallVector<DependenceComponent, 2> dependenceComponents; 97 DependenceResult result = checkMemrefAccessDependence( 98 srcAccess, dstAccess, d, &dependenceConstraints, 99 &dependenceComponents); 100 assert(result.value != DependenceResult::Failure); 101 bool ret = hasDependence(result); 102 // TODO(andydavis) Print dependence type (i.e. RAW, etc) and print 103 // distance vectors as: ([2, 3], [0, 10]). Also, shorten distance 104 // vectors from ([1, 1], [3, 3]) to (1, 3). 105 srcOpInst->emitRemark("dependence from ") 106 << i << " to " << j << " at depth " << d << " = " 107 << getDirectionVectorStr(ret, numCommonLoops, d, 108 dependenceComponents); 109 } 110 } 111 } 112 } 113 114 // Walks the Function 'f' adding load and store ops to 'loadsAndStores'. 115 // Runs pair-wise dependence checks. 116 void TestMemRefDependenceCheck::runOnFunction() { 117 // Collect the loads and stores within the function. 118 loadsAndStores.clear(); 119 getFunction().walk([&](Operation *op) { 120 if (isa<AffineLoadOp>(op) || isa<AffineStoreOp>(op)) 121 loadsAndStores.push_back(op); 122 }); 123 124 checkDependences(loadsAndStores); 125 } 126 127 static PassRegistration<TestMemRefDependenceCheck> 128 pass("test-memref-dependence-check", 129 "Checks dependences between all pairs of memref accesses.");