1ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//===- MemDepPrinter.cpp - Printer for MemoryDependenceAnalysis -----------===//
2ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//
3ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//                     The LLVM Compiler Infrastructure
4ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//
5ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman// This file is distributed under the University of Illinois Open Source
6ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman// License. See LICENSE.TXT for details.
7ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//
8ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//===----------------------------------------------------------------------===//
9ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//
10ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//
11ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman//===----------------------------------------------------------------------===//
12ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
13ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman#include "llvm/Analysis/Passes.h"
14d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SetVector.h"
15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Analysis/MemoryDependenceAnalysis.h"
1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/CallSite.h"
1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstIterator.h"
180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h"
19ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman#include "llvm/Support/ErrorHandling.h"
208945db73d198f912d6821975d9960ab1deb0a45fDan Gohman#include "llvm/Support/raw_ostream.h"
21ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohmanusing namespace llvm;
22ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
23ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohmannamespace {
24ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  struct MemDepPrinter : public FunctionPass {
25ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    const Function *F;
26ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
27b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    enum DepType {
28b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      Clobber = 0,
29b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      Def,
30b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      NonFuncLocal,
31b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      Unknown
32b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    };
33b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman
34e32981048244ecfa67d0bdc211af1bac2020a555Craig Topper    static const char *const DepTypeStr[];
35b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman
36b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    typedef PointerIntPair<const Instruction *, 2, DepType> InstTypePair;
37b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    typedef std::pair<InstTypePair, const BasicBlock *> Dep;
38ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    typedef SmallSetVector<Dep, 4> DepSet;
39ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    typedef DenseMap<const Instruction *, DepSet> DepSetMap;
40ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    DepSetMap Deps;
41ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
42ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    static char ID; // Pass identifcation, replacement for typeid
43081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    MemDepPrinter() : FunctionPass(ID) {
44081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeMemDepPrinterPass(*PassRegistry::getPassRegistry());
45081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
46ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override;
48ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void print(raw_ostream &OS, const Module * = nullptr) const override;
50ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
52cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      AU.addRequiredTransitive<AAResultsWrapperPass>();
53075fb5d68fcb55d26e44c48f07dfdbbfa21ccb2aDan Gohman      AU.addRequiredTransitive<MemoryDependenceAnalysis>();
54ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      AU.setPreservesAll();
55ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    }
56ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void releaseMemory() override {
58ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      Deps.clear();
59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      F = nullptr;
60ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    }
61b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman
62b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman  private:
63b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    static InstTypePair getInstTypePair(MemDepResult dep) {
64b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      if (dep.isClobber())
65b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        return InstTypePair(dep.getInst(), Clobber);
66b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      if (dep.isDef())
67b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        return InstTypePair(dep.getInst(), Def);
68b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      if (dep.isNonFuncLocal())
69b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        return InstTypePair(dep.getInst(), NonFuncLocal);
7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      assert(dep.isUnknown() && "unexpected dependence type");
71b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      return InstTypePair(dep.getInst(), Unknown);
72b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    }
73b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    static InstTypePair getInstTypePair(const Instruction* inst, DepType type) {
74b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      return InstTypePair(inst, type);
75b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman    }
76ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  };
77ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman}
78ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
79ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohmanchar MemDepPrinter::ID = 0;
802ab36d350293c77fc8941ce1023e4899df7e3a82Owen AndersonINITIALIZE_PASS_BEGIN(MemDepPrinter, "print-memdeps",
812ab36d350293c77fc8941ce1023e4899df7e3a82Owen Anderson                      "Print MemDeps of function", false, true)
822ab36d350293c77fc8941ce1023e4899df7e3a82Owen AndersonINITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
832ab36d350293c77fc8941ce1023e4899df7e3a82Owen AndersonINITIALIZE_PASS_END(MemDepPrinter, "print-memdeps",
842ab36d350293c77fc8941ce1023e4899df7e3a82Owen Anderson                      "Print MemDeps of function", false, true)
85ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
86ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan GohmanFunctionPass *llvm::createMemDepPrinter() {
87ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  return new MemDepPrinter();
88ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman}
89ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
90e32981048244ecfa67d0bdc211af1bac2020a555Craig Topperconst char *const MemDepPrinter::DepTypeStr[]
91b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman  = {"Clobber", "Def", "NonFuncLocal", "Unknown"};
92b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman
93ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohmanbool MemDepPrinter::runOnFunction(Function &F) {
94ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  this->F = &F;
95ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  MemoryDependenceAnalysis &MDA = getAnalysis<MemoryDependenceAnalysis>();
96ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
97ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  // All this code uses non-const interfaces because MemDep is not
98ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  // const-friendly, though nothing is actually modified.
99cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (auto &I : instructions(F)) {
100ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    Instruction *Inst = &I;
101ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
102ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory())
103ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      continue;
104ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
105ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    MemDepResult Res = MDA.getDependency(Inst);
106ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    if (!Res.isNonLocal()) {
107b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                       static_cast<BasicBlock *>(nullptr)));
1090c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    } else if (auto CS = CallSite(Inst)) {
110ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI =
111ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman        MDA.getNonLocalCallDependency(CS);
112ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
113ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      DepSet &InstDeps = Deps[Inst];
114ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator
115ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
116ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman        const MemDepResult &Res = I->getResult();
117b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
118ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      }
119ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    } else {
120ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      SmallVector<NonLocalDepResult, 4> NLDI;
121ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      assert( (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
122ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines               isa<VAArgInst>(Inst)) && "Unknown memory instruction!");
123ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      MDA.getNonLocalPointerDependency(Inst, NLDI);
124ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
125ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      DepSet &InstDeps = Deps[Inst];
126ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      for (SmallVectorImpl<NonLocalDepResult>::const_iterator
127ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
128ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman        const MemDepResult &Res = I->getResult();
129b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
130ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      }
131ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    }
132ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  }
133ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
134ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  return false;
135ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman}
136ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
137ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohmanvoid MemDepPrinter::print(raw_ostream &OS, const Module *M) const {
138cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (const auto &I : instructions(*F)) {
139ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    const Instruction *Inst = &I;
140ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
141a627e9bfcdd40454c6942228ab9614dc4154d974Dan Gohman    DepSetMap::const_iterator DI = Deps.find(Inst);
142a627e9bfcdd40454c6942228ab9614dc4154d974Dan Gohman    if (DI == Deps.end())
143ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      continue;
144ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
145a627e9bfcdd40454c6942228ab9614dc4154d974Dan Gohman    const DepSet &InstDeps = DI->second;
146ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
147ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    for (const auto &I : InstDeps) {
148ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      const Instruction *DepInst = I.first.getPointer();
149ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      DepType type = I.first.getInt();
150ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      const BasicBlock *DepBB = I.second;
151ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
152a990e071f2f29ba326b97a4288207a2c406c5b66Eli Friedman      OS << "    ";
153b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman      OS << DepTypeStr[type];
154ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      if (DepBB) {
155ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman        OS << " in block ";
15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        DepBB->printAsOperand(OS, /*PrintType=*/false, M);
157ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      }
158a990e071f2f29ba326b97a4288207a2c406c5b66Eli Friedman      if (DepInst) {
159a990e071f2f29ba326b97a4288207a2c406c5b66Eli Friedman        OS << " from: ";
160b414142036012dd9432c4e8c5fef09d4d49fcc22Eli Friedman        DepInst->print(OS);
161a990e071f2f29ba326b97a4288207a2c406c5b66Eli Friedman      }
162ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman      OS << "\n";
163ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    }
164ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman
165ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    Inst->print(OS);
166ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman    OS << "\n\n";
167ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman  }
168ead0109f5bc010af837d0fa7c9bb2401b34fb29dDan Gohman}
169