llvm.org GIT mirror llvm / 8db585a
Move the CapturesBefore tracker from AA into CaptureTracking There were two generally-useful CaptureTracker classes defined in LLVM: the simple tracker defined in CaptureTracking (and made available via the PointerMayBeCaptured utility function), and the CapturesBefore tracker available only inside of AA. This change moves the CapturesBefore tracker into CaptureTracking, generalizes it slightly (by adding a ReturnCaptures parameter), and makes it generally available via a PointerMayBeCapturedBefore utility function. This logic will be needed, for example, to perform noalias function parameter attribute inference. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213519 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 5 years ago
3 changed file(s) with 96 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
1717
1818 class Value;
1919 class Use;
20 class Instruction;
21 class DominatorTree;
2022
2123 /// PointerMayBeCaptured - Return true if this pointer value may be captured
2224 /// by the enclosing function (which is required to exist). This routine can
2830 bool PointerMayBeCaptured(const Value *V,
2931 bool ReturnCaptures,
3032 bool StoreCaptures);
33
34 /// PointerMayBeCapturedBefore - Return true if this pointer value may be
35 /// captured by the enclosing function (which is required to exist). If a
36 /// DominatorTree is provided, only captures which happen before the given
37 /// instruction are considered. This routine can be expensive, so consider
38 /// caching the results. The boolean ReturnCaptures specifies whether
39 /// returning the value (or part of it) from the function counts as capturing
40 /// it or not. The boolean StoreCaptures specified whether storing the value
41 /// (or part of it) into memory anywhere automatically counts as capturing it
42 /// or not.
43 bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
44 bool StoreCaptures, const Instruction *I,
45 DominatorTree *DT);
3146
3247 /// This callback is used in conjunction with PointerMayBeCaptured. In
3348 /// addition to the interface here, you'll need to provide your own getters
387387 return ModRef;
388388 }
389389
390 namespace {
391 /// Only find pointer captures which happen before the given instruction. Uses
392 /// the dominator tree to determine whether one instruction is before another.
393 /// Only support the case where the Value is defined in the same basic block
394 /// as the given instruction and the use.
395 struct CapturesBefore : public CaptureTracker {
396 CapturesBefore(const Instruction *I, DominatorTree *DT)
397 : BeforeHere(I), DT(DT), Captured(false) {}
398
399 void tooManyUses() override { Captured = true; }
400
401 bool shouldExplore(const Use *U) override {
402 Instruction *I = cast(U->getUser());
403 BasicBlock *BB = I->getParent();
404 // We explore this usage only if the usage can reach "BeforeHere".
405 // If use is not reachable from entry, there is no need to explore.
406 if (BeforeHere != I && !DT->isReachableFromEntry(BB))
407 return false;
408 // If the value is defined in the same basic block as use and BeforeHere,
409 // there is no need to explore the use if BeforeHere dominates use.
410 // Check whether there is a path from I to BeforeHere.
411 if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
412 !isPotentiallyReachable(I, BeforeHere, DT))
413 return false;
414 return true;
415 }
416
417 bool captured(const Use *U) override {
418 Instruction *I = cast(U->getUser());
419 BasicBlock *BB = I->getParent();
420 // Same logic as in shouldExplore.
421 if (BeforeHere != I && !DT->isReachableFromEntry(BB))
422 return false;
423 if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
424 !isPotentiallyReachable(I, BeforeHere, DT))
425 return false;
426 Captured = true;
427 return true;
428 }
429
430 const Instruction *BeforeHere;
431 DominatorTree *DT;
432
433 bool Captured;
434 };
435 }
436
437390 // FIXME: this is really just shoring-up a deficiency in alias analysis.
438391 // BasicAA isn't willing to spend linear time determining whether an alloca
439392 // was captured before or after this particular call, while we are. However,
453406 if (!CS.getInstruction() || CS.getInstruction() == Object)
454407 return AliasAnalysis::ModRef;
455408
456 CapturesBefore CB(I, DT);
457 llvm::PointerMayBeCaptured(Object, &CB);
458 if (CB.Captured)
409 if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
410 /* StoreCaptures */ true, I, DT))
459411 return AliasAnalysis::ModRef;
460412
461413 unsigned ArgNo = 0;
1919 #include "llvm/ADT/SmallVector.h"
2020 #include "llvm/Analysis/AliasAnalysis.h"
2121 #include "llvm/Analysis/CaptureTracking.h"
22 #include "llvm/Analysis/CFG.h"
2223 #include "llvm/IR/CallSite.h"
2324 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/Dominators.h"
2426 #include "llvm/IR/Instructions.h"
2527
2628 using namespace llvm;
4345 Captured = true;
4446 return true;
4547 }
48
49 bool ReturnCaptures;
50
51 bool Captured;
52 };
53
54 /// Only find pointer captures which happen before the given instruction. Uses
55 /// the dominator tree to determine whether one instruction is before another.
56 /// Only support the case where the Value is defined in the same basic block
57 /// as the given instruction and the use.
58 struct CapturesBefore : public CaptureTracker {
59 CapturesBefore(bool ReturnCaptures, const Instruction *I, DominatorTree *DT)
60 : BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures),
61 Captured(false) {}
62
63 void tooManyUses() override { Captured = true; }
64
65 bool shouldExplore(const Use *U) override {
66 Instruction *I = cast(U->getUser());
67 BasicBlock *BB = I->getParent();
68 // We explore this usage only if the usage can reach "BeforeHere".
69 // If use is not reachable from entry, there is no need to explore.
70 if (BeforeHere != I && !DT->isReachableFromEntry(BB))
71 return false;
72 // If the value is defined in the same basic block as use and BeforeHere,
73 // there is no need to explore the use if BeforeHere dominates use.
74 // Check whether there is a path from I to BeforeHere.
75 if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
76 !isPotentiallyReachable(I, BeforeHere, DT))
77 return false;
78 return true;
79 }
80
81 bool captured(const Use *U) override {
82 if (isa(U->getUser()) && !ReturnCaptures)
83 return false;
84
85 Instruction *I = cast(U->getUser());
86 BasicBlock *BB = I->getParent();
87 // Same logic as in shouldExplore.
88 if (BeforeHere != I && !DT->isReachableFromEntry(BB))
89 return false;
90 if (BeforeHere != I && DT->dominates(BeforeHere, I) &&
91 !isPotentiallyReachable(I, BeforeHere, DT))
92 return false;
93 Captured = true;
94 return true;
95 }
96
97 const Instruction *BeforeHere;
98 DominatorTree *DT;
4699
47100 bool ReturnCaptures;
48101
71124 SimpleCaptureTracker SCT(ReturnCaptures);
72125 PointerMayBeCaptured(V, &SCT);
73126 return SCT.Captured;
127 }
128
129 /// PointerMayBeCapturedBefore - Return true if this pointer value may be
130 /// captured by the enclosing function (which is required to exist). If a
131 /// DominatorTree is provided, only captures which happen before the given
132 /// instruction are considered. This routine can be expensive, so consider
133 /// caching the results. The boolean ReturnCaptures specifies whether
134 /// returning the value (or part of it) from the function counts as capturing
135 /// it or not. The boolean StoreCaptures specified whether storing the value
136 /// (or part of it) into memory anywhere automatically counts as capturing it
137 /// or not.
138 bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
139 bool StoreCaptures, const Instruction *I,
140 DominatorTree *DT) {
141 assert(!isa(V) &&
142 "It doesn't make sense to ask whether a global is captured.");
143
144 if (!DT)
145 return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures);
146
147 // TODO: See comment in PointerMayBeCaptured regarding what could be done
148 // with StoreCaptures.
149
150 CapturesBefore CB(ReturnCaptures, I, DT);
151 PointerMayBeCaptured(V, &CB);
152 return CB.Captured;
74153 }
75154
76155 /// TODO: Write a new FunctionPass AliasAnalysis so that it can keep