summaryrefslogtreecommitdiff
path: root/lib/Analysis/IPA/GlobalsModRef.cpp
blob: d08c2583b9fbb7c69017eef6830609c1a417703a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
//===- GlobalsModRef.cpp - Simple Mod/Ref Analysis for Globals ------------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This simple pass provides alias and mod/ref information for global values
// that do not have their address taken, and keeps track of whether functions
// read or write memory (are "pure").  For this simple (but very common) case,
// we can provide pretty accurate and useful information.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/Passes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/Constants.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SCCIterator.h"
#include <set>
using namespace llvm;

namespace {
  Statistic<>
  NumNonAddrTakenGlobalVars("globalsmodref-aa",
                            "Number of global vars without address taken");
  Statistic<>
  NumNonAddrTakenFunctions("globalsmodref-aa",
                           "Number of functions without address taken");
  Statistic<>
  NumNoMemFunctions("globalsmodref-aa",
                    "Number of functions that do not access memory");
  Statistic<>
  NumReadMemFunctions("globalsmodref-aa",
                      "Number of functions that only read memory");

  /// FunctionRecord - One instance of this structure is stored for every
  /// function in the program.  Later, the entries for these functions are
  /// removed if the function is found to call an external function (in which
  /// case we know nothing about it.
  struct FunctionRecord {
    /// GlobalInfo - Maintain mod/ref info for all of the globals without
    /// addresses taken that are read or written (transitively) by this
    /// function.
    std::map<GlobalValue*, unsigned> GlobalInfo;

    unsigned getInfoForGlobal(GlobalValue *GV) const {
      std::map<GlobalValue*, unsigned>::const_iterator I = GlobalInfo.find(GV);
      if (I != GlobalInfo.end())
        return I->second;
      return 0;
    }
    
    /// FunctionEffect - Capture whether or not this function reads or writes to
    /// ANY memory.  If not, we can do a lot of aggressive analysis on it.
    unsigned FunctionEffect;

    FunctionRecord() : FunctionEffect(0) {}
  };

  /// GlobalsModRef - The actual analysis pass.
  class GlobalsModRef : public ModulePass, public AliasAnalysis {
    /// NonAddressTakenGlobals - The globals that do not have their addresses
    /// taken.
    std::set<GlobalValue*> NonAddressTakenGlobals;

    /// FunctionInfo - For each function, keep track of what globals are
    /// modified or read.
    std::map<Function*, FunctionRecord> FunctionInfo;

  public:
    bool runOnModule(Module &M) {
      InitializeAliasAnalysis(this);                 // set up super class
      AnalyzeGlobals(M);                          // find non-addr taken globals
      AnalyzeCallGraph(getAnalysis<CallGraph>(), M); // Propagate on CG
      return false;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.addRequired<CallGraph>();
      AU.setPreservesAll();                         // Does not transform code
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //  
    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);
    ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
    ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
      return AliasAnalysis::getModRefInfo(CS1,CS2);
    }
    bool hasNoModRefInfoForCalls() const { return false; }

    /// getModRefBehavior - Return the behavior of the specified function if
    /// called from the specified call site.  The call site may be null in which
    /// case the most generic behavior of this function should be returned.
    virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS,
                                         std::vector<PointerAccessInfo> *Info) {
      if (FunctionRecord *FR = getFunctionInfo(F))
        if (FR->FunctionEffect == 0)
          return DoesNotAccessMemory;
	else if ((FR->FunctionEffect & Mod) == 0)
	  return OnlyReadsMemory;
      return AliasAnalysis::getModRefBehavior(F, CS, Info);    
    }

    virtual void deleteValue(Value *V);
    virtual void copyValue(Value *From, Value *To);

  private:
    /// getFunctionInfo - Return the function info for the function, or null if
    /// the function calls an external function (in which case we don't have
    /// anything useful to say about it).
    FunctionRecord *getFunctionInfo(Function *F) {
      std::map<Function*, FunctionRecord>::iterator I = FunctionInfo.find(F);
      if (I != FunctionInfo.end())
        return &I->second;
      return 0;
    }

    void AnalyzeGlobals(Module &M);
    void AnalyzeCallGraph(CallGraph &CG, Module &M);
    void AnalyzeSCC(std::vector<CallGraphNode *> &SCC);
    bool AnalyzeUsesOfGlobal(Value *V, std::vector<Function*> &Readers,
                             std::vector<Function*> &Writers);
  };
  
  RegisterOpt<GlobalsModRef> X("globalsmodref-aa",
                               "Simple mod/ref analysis for globals");
  RegisterAnalysisGroup<AliasAnalysis, GlobalsModRef> Y;
}

Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); }


/// AnalyzeGlobalUses - Scan through the users of all of the internal
/// GlobalValue's in the program.  If none of them have their "Address taken"
/// (really, their address passed to something nontrivial), record this fact,
/// and record the functions that they are used directly in.
void GlobalsModRef::AnalyzeGlobals(Module &M) {
  std::vector<Function*> Readers, Writers;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (I->hasInternalLinkage()) {
      if (!AnalyzeUsesOfGlobal(I, Readers, Writers)) {
        // Remember that we are tracking this global.
        NonAddressTakenGlobals.insert(I);
        ++NumNonAddrTakenFunctions;
      }
      Readers.clear(); Writers.clear();
    }

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    if (I->hasInternalLinkage()) {
      if (!AnalyzeUsesOfGlobal(I, Readers, Writers)) {
        // Remember that we are tracking this global, and the mod/ref fns
        NonAddressTakenGlobals.insert(I);
        for (unsigned i = 0, e = Readers.size(); i != e; ++i)
          FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref;

        if (!I->isConstant())  // No need to keep track of writers to constants
          for (unsigned i = 0, e = Writers.size(); i != e; ++i)
            FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod;
        ++NumNonAddrTakenGlobalVars;
      }
      Readers.clear(); Writers.clear();
    }
}

/// AnalyzeUsesOfGlobal - Look at all of the users of the specified global value
/// derived pointer.  If this is used by anything complex (i.e., the address
/// escapes), return true.  Also, while we are at it, keep track of those
/// functions that read and write to the value.
bool GlobalsModRef::AnalyzeUsesOfGlobal(Value *V,
                                        std::vector<Function*> &Readers,
                                        std::vector<Function*> &Writers) {
  if (!isa<PointerType>(V->getType())) return true;

  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
    if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
      Readers.push_back(LI->getParent()->getParent());
    } else if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) {
      if (V == SI->getOperand(0)) return true;  // Storing the pointer
      Writers.push_back(SI->getParent()->getParent());
    } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*UI)) {
      if (AnalyzeUsesOfGlobal(GEP, Readers, Writers)) return true;
    } else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      // Make sure that this is just the function being called, not that it is
      // passing into the function.
      for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
        if (CI->getOperand(i) == V) return true;
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
      // Make sure that this is just the function being called, not that it is
      // passing into the function.
      for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i)
        if (II->getOperand(i) == V) return true;
    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) {
      if (CE->getOpcode() == Instruction::GetElementPtr ||
          CE->getOpcode() == Instruction::Cast) {
        if (AnalyzeUsesOfGlobal(CE, Readers, Writers))
          return true;
      } else {
        return true;
      }        
    } else if (GlobalValue *GV = dyn_cast<GlobalValue>(*UI)) {
      if (AnalyzeUsesOfGlobal(GV, Readers, Writers)) return true;
    } else {
      return true;
    }
  return false;
}

/// AnalyzeCallGraph - At this point, we know the functions where globals are
/// immediately stored to and read from.  Propagate this information up the call
/// graph to all callers and compute the mod/ref info for all memory for each
/// function.  
void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
  // We do a bottom-up SCC traversal of the call graph.  In other words, we
  // visit all callees before callers (leaf-first).
  for (scc_iterator<CallGraph*> I = scc_begin(&CG), E = scc_end(&CG); I!=E; ++I)
    if ((*I).size() != 1) {
      AnalyzeSCC(*I);
    } else if (Function *F = (*I)[0]->getFunction()) {
      if (!F->isExternal()) {
        // Nonexternal function.
        AnalyzeSCC(*I);
      } else {
        // Otherwise external function.  Handle intrinsics and other special
        // cases here.
        if (getAnalysis<AliasAnalysis>().doesNotAccessMemory(F))
          // If it does not access memory, process the function, causing us to
          // realize it doesn't do anything (the body is empty).
          AnalyzeSCC(*I);
        else {
          // Otherwise, don't process it.  This will cause us to conservatively
          // assume the worst.
        }
      }
    } else {
      // Do not process the external node, assume the worst.
    }
}

void GlobalsModRef::AnalyzeSCC(std::vector<CallGraphNode *> &SCC) {
  assert(!SCC.empty() && "SCC with no functions?");
  FunctionRecord &FR = FunctionInfo[SCC[0]->getFunction()];

  bool CallsExternal = false;
  unsigned FunctionEffect = 0;

  // Collect the mod/ref properties due to called functions.  We only compute
  // one mod-ref set
  for (unsigned i = 0, e = SCC.size(); i != e && !CallsExternal; ++i)
    for (CallGraphNode::iterator CI = SCC[i]->begin(), E = SCC[i]->end();
         CI != E; ++CI)
      if (Function *Callee = (*CI)->getFunction()) {
        if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) {
          // Propagate function effect up.
          FunctionEffect |= CalleeFR->FunctionEffect;

          // Incorporate callee's effects on globals into our info.
          for (std::map<GlobalValue*, unsigned>::iterator GI =
                 CalleeFR->GlobalInfo.begin(), E = CalleeFR->GlobalInfo.end();
               GI != E; ++GI)
            FR.GlobalInfo[GI->first] |= GI->second;

        } else {
          // Okay, if we can't say anything about it, maybe some other alias
          // analysis can.
          ModRefBehavior MRB =
            AliasAnalysis::getModRefBehavior(Callee, CallSite());
          if (MRB != DoesNotAccessMemory) {
            if (MRB == OnlyReadsMemory) {
              // This reads memory, but we don't know what, just say that it
              // reads all globals.
              for (std::map<GlobalValue*, unsigned>::iterator
                     GI = CalleeFR->GlobalInfo.begin(),
                     E = CalleeFR->GlobalInfo.end();
                   GI != E; ++GI)
                FR.GlobalInfo[GI->first] |= Ref;

            } else {
              CallsExternal = true;
              break;
            }
          }
        }
      } else {
        CallsExternal = true;
        break;
      }

  // If this SCC calls an external function, we can't say anything about it, so
  // remove all SCC functions from the FunctionInfo map.
  if (CallsExternal) {
    for (unsigned i = 0, e = SCC.size(); i != e; ++i)
      FunctionInfo.erase(SCC[i]->getFunction());
    return;
  }
  
  // Otherwise, unless we already know that this function mod/refs memory, scan
  // the function bodies to see if there are any explicit loads or stores.
  if (FunctionEffect != ModRef) {
    for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i)
      for (inst_iterator II = inst_begin(SCC[i]->getFunction()),
             E = inst_end(SCC[i]->getFunction()); 
           II != E && FunctionEffect != ModRef; ++II)
        if (isa<LoadInst>(*II))
          FunctionEffect |= Ref;
        else if (isa<StoreInst>(*II))
          FunctionEffect |= Mod;
  }

  if ((FunctionEffect & Mod) == 0)
    ++NumReadMemFunctions;
  if (FunctionEffect == 0)
    ++NumNoMemFunctions;
  FR.FunctionEffect = FunctionEffect;

  // Finally, now that we know the full effect on this SCC, clone the
  // information to each function in the SCC.
  for (unsigned i = 1, e = SCC.size(); i != e; ++i)
    FunctionInfo[SCC[i]->getFunction()] = FR;
}



/// getUnderlyingObject - This traverses the use chain to figure out what object
/// the specified value points to.  If the value points to, or is derived from,
/// a global object, return it.
static const GlobalValue *getUnderlyingObject(const Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;

  // If we are at some type of object... return it.
  if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) return GV;
  
  // Traverse through different addressing mechanisms...
  if (const Instruction *I = dyn_cast<Instruction>(V)) {
    if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
      return getUnderlyingObject(I->getOperand(0));
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
    if (CE->getOpcode() == Instruction::Cast ||
        CE->getOpcode() == Instruction::GetElementPtr)
      return getUnderlyingObject(CE->getOperand(0));
  }
  return 0;
}

/// alias - If one of the pointers is to a global that we are tracking, and the
/// other is some random pointer, we know there cannot be an alias, because the
/// address of the global isn't taken.
AliasAnalysis::AliasResult
GlobalsModRef::alias(const Value *V1, unsigned V1Size,
                     const Value *V2, unsigned V2Size) {
  GlobalValue *GV1 = const_cast<GlobalValue*>(getUnderlyingObject(V1));
  GlobalValue *GV2 = const_cast<GlobalValue*>(getUnderlyingObject(V2));

  // If the global's address is taken, pretend we don't know it's a pointer to
  // the global.
  if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0;
  if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0;

  if ((GV1 || GV2) && GV1 != GV2)
    return NoAlias;

  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}

AliasAnalysis::ModRefResult
GlobalsModRef::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  unsigned Known = ModRef;

  // If we are asking for mod/ref info of a direct call with a pointer to a
  // global we are tracking, return information if we have it.
  if (GlobalValue *GV = const_cast<GlobalValue*>(getUnderlyingObject(P)))
    if (GV->hasInternalLinkage())
      if (Function *F = CS.getCalledFunction())
        if (NonAddressTakenGlobals.count(GV))
          if (FunctionRecord *FR = getFunctionInfo(F))
            Known = FR->getInfoForGlobal(GV);

  if (Known == NoModRef)
    return NoModRef; // No need to query other mod/ref analyses
  return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, P, Size));
}


//===----------------------------------------------------------------------===//
// Methods to update the analysis as a result of the client transformation.
//
void GlobalsModRef::deleteValue(Value *V) {
  if (GlobalValue *GV = dyn_cast<GlobalValue>(V))
    NonAddressTakenGlobals.erase(GV);
}

void GlobalsModRef::copyValue(Value *From, Value *To) {
}