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.");