X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FCaptureTracking.cpp;h=42a54d9d1eb3adba766363cf2ef38765a12055b9;hb=ff10341183adf74760e6118a55cbd1debf50f90f;hp=e86ad96e4a15e821852f997c8ff876aa16766130;hpb=76c638a14c1e2927e5e20040b347bc3d7ae8fb82;p=oota-llvm.git diff --git a/lib/Analysis/CaptureTracking.cpp b/lib/Analysis/CaptureTracking.cpp index e86ad96e4a1..42a54d9d1eb 100644 --- a/lib/Analysis/CaptureTracking.cpp +++ b/lib/Analysis/CaptureTracking.cpp @@ -25,6 +25,16 @@ #include "llvm/Support/CallSite.h" using namespace llvm; +/// As its comment mentions, PointerMayBeCaptured can be expensive. +/// However, it's not easy for BasicAA to cache the result, because +/// it's an ImmutablePass. To work around this, bound queries at a +/// fixed number of uses. +/// +/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep +/// a cache. Then we can move the code from BasicAliasAnalysis into +/// that path, and remove this threshold. +static int const Threshold = 20; + /// PointerMayBeCaptured - Return true if this pointer value may be captured /// by the enclosing function (which is required to exist). This routine can /// be expensive, so consider caching the results. The boolean ReturnCaptures @@ -34,12 +44,18 @@ using namespace llvm; /// counts as capturing it or not. bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures) { - assert(isa(V->getType()) && "Capture is for pointers only!"); - SmallVector Worklist; - SmallSet Visited; + assert(V->getType()->isPointerTy() && "Capture is for pointers only!"); + SmallVector Worklist; + SmallSet Visited; + int Count = 0; - for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end(); + for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE; ++UI) { + // If there are lots of uses, conservatively say that the value + // is captured to avoid taking too much compile time. + if (Count++ >= Threshold) + return true; + Use *U = &UI.getUse(); Visited.insert(U); Worklist.push_back(U); @@ -53,7 +69,7 @@ bool llvm::PointerMayBeCaptured(const Value *V, switch (I->getOpcode()) { case Instruction::Call: case Instruction::Invoke: { - CallSite CS = CallSite::get(I); + CallSite CS(I); // Not captured if the callee is readonly, doesn't return a copy through // its return value and doesn't unwind (a readonly function can leak bits // by throwing an exception or not depending on the input value). @@ -79,6 +95,9 @@ bool llvm::PointerMayBeCaptured(const Value *V, case Instruction::Load: // Loading from a pointer does not cause it to be captured. break; + case Instruction::VAArg: + // "va-arg" from a pointer does not cause it to be captured. + break; case Instruction::Ret: if (ReturnCaptures) return true; @@ -105,25 +124,18 @@ bool llvm::PointerMayBeCaptured(const Value *V, Worklist.push_back(U); } break; - case Instruction::ICmp: { - // Don't count comparisons of the original value against null as captures. - // This allows us to ignore comparisons of malloc results with null, - // for example. - if (isIdentifiedObject(V)) + case Instruction::ICmp: + // Don't count comparisons of a no-alias return value against null as + // captures. This allows us to ignore comparisons of malloc results + // with null, for example. + if (isNoAliasCall(V->stripPointerCasts())) if (ConstantPointerNull *CPN = dyn_cast(I->getOperand(1))) if (CPN->getType()->getAddressSpace() == 0) break; - // Don't count comparisons of two pointers within the same identified - // object as captures. - Value *O0 = I->getOperand(0)->getUnderlyingObject(); - if (isIdentifiedObject(O0) && - O0 == I->getOperand(1)->getUnderlyingObject()) - break; // Otherwise, be conservative. There are crazy ways to capture pointers // using comparisons. return true; - } default: // Something else - be conservative and say it is captured. return true;