blob: c1168eccaad6587f57d3afff571dc586b0d4322b [file] [log] [blame]
Andreas Bolka306b5b22009-06-24 21:29:13 +00001//===- LoopDependenceAnalysis.cpp - LDA Implementation ----------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This is the (beginning) of an implementation of a loop dependence analysis
11// framework, which is used to detect dependences in memory accesses in loops.
12//
13// Please note that this is work in progress and the interface is subject to
14// change.
15//
16// TODO: adapt as implementation progresses.
17//
18//===----------------------------------------------------------------------===//
19
20#define DEBUG_TYPE "lda"
21#include "llvm/Analysis/LoopDependenceAnalysis.h"
22#include "llvm/Analysis/LoopPass.h"
23#include "llvm/Analysis/ScalarEvolution.h"
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +000024#include "llvm/Instructions.h"
Andreas Bolka5771ed92009-06-30 02:12:10 +000025#include "llvm/Support/Debug.h"
Andreas Bolka306b5b22009-06-24 21:29:13 +000026using namespace llvm;
27
28LoopPass *llvm::createLoopDependenceAnalysisPass() {
29 return new LoopDependenceAnalysis();
30}
31
32static RegisterPass<LoopDependenceAnalysis>
33R("lda", "Loop Dependence Analysis", false, true);
34char LoopDependenceAnalysis::ID = 0;
35
36//===----------------------------------------------------------------------===//
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +000037// Utility Functions
38//===----------------------------------------------------------------------===//
39
Andreas Bolkafc8a04a2009-06-29 18:51:11 +000040static inline bool IsMemRefInstr(const Value *V) {
41 const Instruction *I = dyn_cast<const Instruction>(V);
42 return I && (I->mayReadFromMemory() || I->mayWriteToMemory());
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +000043}
44
Andreas Bolka88a17f02009-06-29 00:50:26 +000045static void GetMemRefInstrs(
Andreas Bolka158c5902009-06-28 00:35:22 +000046 const Loop *L, SmallVectorImpl<Instruction*> &memrefs) {
47 for (Loop::block_iterator b = L->block_begin(), be = L->block_end();
48 b != be; ++b)
49 for (BasicBlock::iterator i = (*b)->begin(), ie = (*b)->end();
50 i != ie; ++i)
Andreas Bolka88a17f02009-06-29 00:50:26 +000051 if (IsMemRefInstr(i))
Andreas Bolka158c5902009-06-28 00:35:22 +000052 memrefs.push_back(i);
53}
54
Andreas Bolka5771ed92009-06-30 02:12:10 +000055static bool IsLoadOrStoreInst(Value *I) {
56 return isa<LoadInst>(I) || isa<StoreInst>(I);
57}
58
59static Value *GetPointerOperand(Value *I) {
60 if (LoadInst *i = dyn_cast<LoadInst>(I))
61 return i->getPointerOperand();
62 if (StoreInst *i = dyn_cast<StoreInst>(I))
63 return i->getPointerOperand();
64 assert(0 && "Value is no load or store instruction!");
65 // Never reached.
66 return 0;
67}
68
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +000069//===----------------------------------------------------------------------===//
70// Dependence Testing
71//===----------------------------------------------------------------------===//
72
73bool LoopDependenceAnalysis::isDependencePair(const Value *x,
74 const Value *y) const {
Andreas Bolkafc8a04a2009-06-29 18:51:11 +000075 return IsMemRefInstr(x) &&
76 IsMemRefInstr(y) &&
77 (cast<const Instruction>(x)->mayWriteToMemory() ||
78 cast<const Instruction>(y)->mayWriteToMemory());
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +000079}
80
81bool LoopDependenceAnalysis::depends(Value *src, Value *dst) {
82 assert(isDependencePair(src, dst) && "Values form no dependence pair!");
Andreas Bolka5771ed92009-06-30 02:12:10 +000083 DOUT << "== LDA test ==\n" << *src << *dst;
84
85 // We only analyse loads and stores; for possible memory accesses by e.g.
86 // free, call, or invoke instructions we conservatively assume dependence.
87 if (!IsLoadOrStoreInst(src) || !IsLoadOrStoreInst(dst))
88 return true;
89
90 Value *srcPtr = GetPointerOperand(src);
91 Value *dstPtr = GetPointerOperand(dst);
92 const Value *srcObj = srcPtr->getUnderlyingObject();
93 const Value *dstObj = dstPtr->getUnderlyingObject();
94 const Type *srcTy = srcObj->getType();
95 const Type *dstTy = dstObj->getType();
96
97 // For now, we only work on (pointers to) global or stack-allocated array
98 // values, as we know that their underlying memory areas will not overlap.
99 // MAYBE: relax this and test for aliasing?
100 if (!((isa<GlobalVariable>(srcObj) || isa<AllocaInst>(srcObj)) &&
101 (isa<GlobalVariable>(dstObj) || isa<AllocaInst>(dstObj)) &&
102 isa<PointerType>(srcTy) &&
103 isa<PointerType>(dstTy) &&
104 isa<ArrayType>(cast<PointerType>(srcTy)->getElementType()) &&
105 isa<ArrayType>(cast<PointerType>(dstTy)->getElementType())))
106 return true;
107
108 // If the arrays are different, the underlying memory areas do not overlap
109 // and the memory accesses are therefore independent.
110 if (srcObj != dstObj)
111 return false;
112
113 // We couldn't establish a more precise result, so we have to conservatively
114 // assume full dependence.
Andreas Bolkaf17ab7f2009-06-28 00:21:21 +0000115 return true;
116}
117
118//===----------------------------------------------------------------------===//
Andreas Bolka306b5b22009-06-24 21:29:13 +0000119// LoopDependenceAnalysis Implementation
120//===----------------------------------------------------------------------===//
121
122bool LoopDependenceAnalysis::runOnLoop(Loop *L, LPPassManager &) {
123 this->L = L;
124 SE = &getAnalysis<ScalarEvolution>();
125 return false;
126}
127
128void LoopDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
129 AU.setPreservesAll();
Andreas Bolkab88ee912009-06-28 00:16:08 +0000130 AU.addRequiredTransitive<ScalarEvolution>();
131}
132
133static void PrintLoopInfo(
Andreas Bolka158c5902009-06-28 00:35:22 +0000134 raw_ostream &OS, LoopDependenceAnalysis *LDA, const Loop *L) {
Andreas Bolkab88ee912009-06-28 00:16:08 +0000135 if (!L->empty()) return; // ignore non-innermost loops
136
137 OS << "Loop at depth " << L->getLoopDepth() << ", header block: ";
138 WriteAsOperand(OS, L->getHeader(), false);
139 OS << "\n";
Andreas Bolka158c5902009-06-28 00:35:22 +0000140
141 SmallVector<Instruction*, 8> memrefs;
Andreas Bolkab2662e42009-06-29 00:53:49 +0000142 GetMemRefInstrs(L, memrefs);
Andreas Bolka158c5902009-06-28 00:35:22 +0000143 OS << " Load/store instructions: " << memrefs.size() << "\n";
144 OS << " Pairwise dependence results:\n";
145 for (SmallVector<Instruction*, 8>::const_iterator x = memrefs.begin(),
146 end = memrefs.end(); x != end; ++x)
147 for (SmallVector<Instruction*, 8>::const_iterator y = x + 1;
148 y != end; ++y)
149 if (LDA->isDependencePair(*x, *y))
150 OS << "\t" << (x - memrefs.begin()) << "," << (y - memrefs.begin())
151 << ": " << (LDA->depends(*x, *y) ? "dependent" : "independent")
152 << "\n";
Andreas Bolkab88ee912009-06-28 00:16:08 +0000153}
154
155void LoopDependenceAnalysis::print(raw_ostream &OS, const Module*) const {
Andreas Bolka158c5902009-06-28 00:35:22 +0000156 // TODO: doc why const_cast is safe
157 PrintLoopInfo(OS, const_cast<LoopDependenceAnalysis*>(this), this->L);
Andreas Bolkab88ee912009-06-28 00:16:08 +0000158}
159
160void LoopDependenceAnalysis::print(std::ostream &OS, const Module *M) const {
161 raw_os_ostream os(OS);
162 print(os, M);
Andreas Bolka306b5b22009-06-24 21:29:13 +0000163}