Index: include/llvm/Analysis/BasicAliasAnalysis.h =================================================================== --- include/llvm/Analysis/BasicAliasAnalysis.h +++ include/llvm/Analysis/BasicAliasAnalysis.h @@ -81,20 +81,7 @@ /// By definition, this result is stateless and so remains valid. bool invalidate(Function &, const PreservedAnalyses &) { return false; } - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { - assert(AliasCache.empty() && "AliasCache must be cleared after use!"); - assert(notDifferentParent(LocA.Ptr, LocB.Ptr) && - "BasicAliasAnalysis doesn't support interprocedural queries."); - AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, LocB.Ptr, - LocB.Size, LocB.AATags); - // AliasCache rarely has more than 1 or 2 elements, always use - // shrink_and_clear so it quickly returns to the inline capacity of the - // SmallDenseMap if it ever grows larger. - // FIXME: This should really be shrink_to_inline_capacity_and_clear(). - AliasCache.shrink_and_clear(); - VisitedPhiBBs.clear(); - return Alias; - } + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); Index: lib/Analysis/AliasAnalysis.cpp =================================================================== --- lib/Analysis/AliasAnalysis.cpp +++ lib/Analysis/AliasAnalysis.cpp @@ -25,6 +25,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CFLAliasAnalysis.h" @@ -47,11 +48,27 @@ #include "llvm/Pass.h" using namespace llvm; +#define DEBUG_TYPE "aa" + /// Allow disabling BasicAA from the AA results. This is particularly useful /// when testing to isolate a single AA implementation. static cl::opt DisableBasicAA("disable-basicaa", cl::Hidden, cl::init(false)); +STATISTIC(NumAliasQueries, "AA 'alias' queries"); +STATISTIC(NumNoAliasResults, "AA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumMayAliasResults, "AA 'alias' queries resulting in 'MayAlias'"); +STATISTIC(NumMustAliasResults, "AA 'alias' queries resulting in 'MustAlias'"); +STATISTIC(NumPartialAliasResults, "AA 'alias' queries resulting in 'PartialAlias'"); +STATISTIC(NumPointsToConstQueries, "AA 'pointsToConstantMemory' queries"); +STATISTIC(NumArgModRefInfoQueries, "AA argument 'ModRefInfo' queries"); +STATISTIC(NumModRefInfoQueries, "AA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, "AA 'ModRefInfo' queries resulting in 'NoModRef'"); +STATISTIC(NumRefResults, "AA 'ModRefInfo' queries resulting in 'Ref'"); +STATISTIC(NumModResults, "AA 'ModRefInfo' queries resulting in 'Mod'"); +STATISTIC(NumModRefResults, "AA 'ModRefInfo' queries resulting in 'ModRef'"); +STATISTIC(NumModRefBehaviorQueries, "AA 'ModRefBehavior' queries"); + FunctionAAResults::FunctionAAResults(FunctionAAResults &&Arg) : AAs(std::move(Arg.AAs)) { for (auto &AA : AAs) @@ -82,16 +99,33 @@ AliasResult FunctionAAResults::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + ++NumAliasQueries; for (const auto &AA : AAs) { auto Result = AA->alias(LocA, LocB); - if (Result != MayAlias) + if (Result != MayAlias) { + switch (Result) { + case NoAlias: + ++NumNoAliasResults; + break; + case MayAlias: + ++NumMayAliasResults; + break; + case MustAlias: + ++NumMustAliasResults; + break; + case PartialAlias: + ++NumPartialAliasResults; + break; + } return Result; + } } return MayAlias; } bool FunctionAAResults::pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) { + ++NumPointsToConstQueries; for (const auto &AA : AAs) if (AA->pointsToConstantMemory(Loc, OrLocal)) return true; @@ -103,6 +137,7 @@ unsigned ArgIdx) { ModRefInfo Result = MRI_ModRef; + ++NumArgModRefInfoQueries; for (const auto &AA : AAs) { Result = ModRefInfo(Result & AA->getArgModRefInfo(CS, ArgIdx)); @@ -132,18 +167,37 @@ return MRI_NoModRef; } +static void countModRefInfoResult(ModRefInfo MRI) { + switch (MRI) { + case MRI_NoModRef: + ++NumNoModRefResults; + break; + case MRI_Ref: + ++NumRefResults; + break; + case MRI_Mod: + ++NumModResults; + break; + case MRI_ModRef: + ++NumModRefResults; + break; + } +} + ModRefInfo FunctionAAResults::getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) { ModRefInfo Result = MRI_ModRef; + ++NumModRefInfoQueries; for (const auto &AA : AAs) { Result = ModRefInfo(Result & AA->getModRefInfo(CS, Loc)); // Early-exit the moment we reach the bottom of the lattice. if (Result == MRI_NoModRef) - return Result; + break; } + countModRefInfoResult(Result); return Result; } @@ -151,14 +205,16 @@ ImmutableCallSite CS2) { ModRefInfo Result = MRI_ModRef; + ++NumModRefInfoQueries; for (const auto &AA : AAs) { Result = ModRefInfo(Result & AA->getModRefInfo(CS1, CS2)); // Early-exit the moment we reach the bottom of the lattice. if (Result == MRI_NoModRef) - return Result; + break; } + countModRefInfoResult(Result); return Result; } @@ -166,6 +222,7 @@ FunctionAAResults::getModRefBehavior(ImmutableCallSite CS) { FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior; + ++NumModRefBehaviorQueries; for (const auto &AA : AAs) { Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(CS)); @@ -180,6 +237,7 @@ FunctionModRefBehavior FunctionAAResults::getModRefBehavior(const Function *F) { FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior; + ++NumModRefBehaviorQueries; for (const auto &AA : AAs) { Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(F)); Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -51,6 +51,17 @@ "decompose GEPs is reached"); STATISTIC(SearchTimes, "Number of times a GEP is decomposed"); +STATISTIC(NumAliasQueries, "BasicAA 'alias' queries"); +STATISTIC(NumNoAliasResults, "BasicAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumMayAliasResults, "BasicAA 'alias' queries resulting in 'MayAlias'"); +STATISTIC(NumMustAliasResults, "BasicAA 'alias' queries resulting in 'MustAlias'"); +STATISTIC(NumPartialAliasResults, "BasicAA 'alias' queries resulting in 'PartialAlias'"); +STATISTIC(NumPointsToConstQueries, "BasicAA 'pointsToConstantMemory' queries"); +STATISTIC(NumArgModRefInfoQueries, "BasicAA argument 'ModRefInfo' queries"); +STATISTIC(NumModRefInfoQueries, "BasicAA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, "BasicAA 'ModRefInfo' queries resulting in 'NoModRef'"); +STATISTIC(NumModRefBehaviorQueries, "BasicAA 'ModRefBehavior' queries"); + /// Cutoff after which to stop analysing a set of phi nodes potentially involved /// in a cycle. Because we are analysing 'through' phi nodes we need to be /// careful with value equivalence. We use reachability to make sure a value @@ -395,12 +406,45 @@ return V; } +AliasResult BasicAAResult::alias(const MemoryLocation &LocA, + const MemoryLocation &LocB) { + ++NumAliasQueries; + assert(AliasCache.empty() && "AliasCache must be cleared after use!"); + assert(notDifferentParent(LocA.Ptr, LocB.Ptr) && + "BasicAliasAnalysis doesn't support interprocedural queries."); + AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, LocB.Ptr, + LocB.Size, LocB.AATags); + switch (Alias) { + case NoAlias: + ++NumNoAliasResults; + break; + case MustAlias: + ++NumMustAliasResults; + break; + case PartialAlias: + ++NumPartialAliasResults; + break; + case MayAlias: + ++NumMayAliasResults; + break; + } + + // AliasCache rarely has more than 1 or 2 elements, always use + // shrink_and_clear so it quickly returns to the inline capacity of the + // SmallDenseMap if it ever grows larger. + // FIXME: This should really be shrink_to_inline_capacity_and_clear(). + AliasCache.shrink_and_clear(); + VisitedPhiBBs.clear(); + return Alias; +} + /// Returns whether the given pointer value points to memory that is local to /// the function, with global constants being considered local to all /// functions. bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) { assert(Visited.empty() && "Visited must be cleared after use!"); + ++NumPointsToConstQueries; unsigned MaxLookup = 8; SmallVector Worklist; @@ -477,6 +521,7 @@ /// Returns the behavior when calling the given call site. FunctionModRefBehavior BasicAAResult::getModRefBehavior(ImmutableCallSite CS) { + ++NumModRefBehaviorQueries; if (CS.doesNotAccessMemory()) // Can't do better than this. return FMRB_DoesNotAccessMemory; @@ -498,6 +543,7 @@ /// Returns the behavior when calling the given function. For use when the call /// site is not known. FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) { + ++NumModRefBehaviorQueries; // If the function declares it doesn't access memory, we can't do better. if (F->doesNotAccessMemory()) return FMRB_DoesNotAccessMemory; @@ -520,6 +566,7 @@ ModRefInfo BasicAAResult::getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) { + ++NumArgModRefInfoQueries; if (const IntrinsicInst *II = dyn_cast(CS.getInstruction())) switch (II->getIntrinsicID()) { default: @@ -565,6 +612,7 @@ const MemoryLocation &Loc) { assert(notDifferentParent(CS.getInstruction(), Loc.Ptr) && "AliasAnalysis query involving multiple functions!"); + ++NumModRefInfoQueries; const Value *Object = GetUnderlyingObject(Loc.Ptr, DL); @@ -575,8 +623,10 @@ // may reference them. if (isa(Object)) if (const CallInst *CI = dyn_cast(CS.getInstruction())) - if (CI->isTailCall()) + if (CI->isTailCall()) { + ++NumNoModRefResults; return MRI_NoModRef; + } // If the pointer is to a locally allocated object that does not escape, // then the call can not mod/ref the pointer unless the call takes the pointer @@ -608,15 +658,19 @@ } } - if (!PassedAsArg) + if (!PassedAsArg) { + ++NumNoModRefResults; return MRI_NoModRef; + } } // While the assume intrinsic is marked as arbitrarily writing so that // proper control dependencies will be maintained, it never aliases any // particular memory location. - if (isAssumeIntrinsic(CS)) + if (isAssumeIntrinsic(CS)) { + ++NumNoModRefResults; return MRI_NoModRef; + } // The AAResultBase base class has some smarts, lets use them. return AAResultBase::getModRefInfo(CS, Loc); @@ -627,8 +681,10 @@ // While the assume intrinsic is marked as arbitrarily writing so that // proper control dependencies will be maintained, it never aliases any // particular memory location. - if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2)) + if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2)) { + ++NumNoModRefResults; return MRI_NoModRef; + } // The AAResultBase base class has some smarts, lets use them. return AAResultBase::getModRefInfo(CS1, CS2); Index: lib/Analysis/GlobalsModRef.cpp =================================================================== --- lib/Analysis/GlobalsModRef.cpp +++ lib/Analysis/GlobalsModRef.cpp @@ -39,6 +39,14 @@ STATISTIC(NumReadMemFunctions, "Number of functions that only read memory"); STATISTIC(NumIndirectGlobalVars, "Number of indirect global objects"); +STATISTIC(NumAliasQueries, "GlobalsAA 'alias' queries"); +STATISTIC(NumNoAliasResults, + "GlobalsAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumModRefInfoQueries, "GlobalsAA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, + "GlobalsAA 'ModRefInfo' queries resulting in 'NoModRef'"); +STATISTIC(NumModRefBehaviorQueries, "GlobalsAA 'ModRefBehavior' queries"); + // An option to enable unsafe alias results from the GlobalsModRef analysis. // When enabled, GlobalsModRef will provide no-alias results which in extremely // rare cases may not be conservatively correct. In particular, in the face of @@ -228,6 +236,7 @@ FunctionModRefBehavior GlobalsAAResult::getModRefBehavior(const Function *F) { FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior; + ++NumModRefBehaviorQueries; if (FunctionInfo *FI = getFunctionInfo(F)) { if (FI->getModRefInfo() == MRI_NoModRef) @@ -242,6 +251,7 @@ FunctionModRefBehavior GlobalsAAResult::getModRefBehavior(ImmutableCallSite CS) { FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior; + ++NumModRefBehaviorQueries; if (const Function *F = CS.getCalledFunction()) if (FunctionInfo *FI = getFunctionInfo(F)) { @@ -688,6 +698,8 @@ /// address of the global isn't taken. AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + ++NumAliasQueries; + // Get the base object these pointers point to. const Value *UV1 = GetUnderlyingObject(LocA.Ptr, DL); const Value *UV2 = GetUnderlyingObject(LocB.Ptr, DL); @@ -706,23 +718,29 @@ // If the two pointers are derived from two different non-addr-taken // globals we know these can't alias. - if (GV1 && GV2 && GV1 != GV2) + if (GV1 && GV2 && GV1 != GV2) { + ++NumNoAliasResults; return NoAlias; + } // If one is and the other isn't, it isn't strictly safe but we can fake // this result if necessary for performance. This does not appear to be // a common problem in practice. if (EnableUnsafeGlobalsModRefAliasResults) - if ((GV1 || GV2) && GV1 != GV2) + if ((GV1 || GV2) && GV1 != GV2) { + ++NumNoAliasResults; return NoAlias; + } // Check for a special case where a non-escaping global can be used to // conclude no-alias. if ((GV1 || GV2) && GV1 != GV2) { const GlobalValue *GV = GV1 ? GV1 : GV2; const Value *UV = GV1 ? UV2 : UV1; - if (isNonEscapingGlobalNoAlias(GV, UV)) + if (isNonEscapingGlobalNoAlias(GV, UV)) { + ++NumNoAliasResults; return NoAlias; + } } // Otherwise if they are both derived from the same addr-taken global, we @@ -752,15 +770,19 @@ // Now that we know whether the two pointers are related to indirect globals, // use this to disambiguate the pointers. If the pointers are based on // different indirect globals they cannot alias. - if (GV1 && GV2 && GV1 != GV2) + if (GV1 && GV2 && GV1 != GV2) { + ++NumNoAliasResults; return NoAlias; + } // If one is based on an indirect global and the other isn't, it isn't // strictly safe but we can fake this result if necessary for performance. // This does not appear to be a common problem in practice. if (EnableUnsafeGlobalsModRefAliasResults) - if ((GV1 || GV2) && GV1 != GV2) + if ((GV1 || GV2) && GV1 != GV2) { + ++NumNoAliasResults; return NoAlias; + } return AAResultBase::alias(LocA, LocB); } @@ -768,6 +790,7 @@ ModRefInfo GlobalsAAResult::getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) { unsigned Known = MRI_ModRef; + ++NumModRefInfoQueries; // 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. @@ -779,8 +802,10 @@ if (const FunctionInfo *FI = getFunctionInfo(F)) Known = FI->getModRefInfoForGlobal(*GV); - if (Known == MRI_NoModRef) + if (Known == MRI_NoModRef) { + ++NumNoModRefResults; return MRI_NoModRef; // No need to query other mod/ref analyses + } return ModRefInfo(Known & AAResultBase::getModRefInfo(CS, Loc)); } Index: lib/Analysis/ObjCARCAliasAnalysis.cpp =================================================================== --- lib/Analysis/ObjCARCAliasAnalysis.cpp +++ lib/Analysis/ObjCARCAliasAnalysis.cpp @@ -24,6 +24,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/ObjCARCAliasAnalysis.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ObjCARCAnalysisUtils.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -41,10 +42,26 @@ EnableARCAliasAnalysis("enable-objc-arc-aa", cl::desc("enable/disable ARC-based Alias Analysis"), cl::init(true)); + +STATISTIC(NumAliasQueries, "ObcARCAA 'alias' queries"); +STATISTIC(NumNoAliasResults, "ObcARCAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumMayAliasResults, + "ObcARCAA 'alias' queries resulting in 'MayAlias'"); +STATISTIC(NumMustAliasResults, + "ObcARCAA 'alias' queries resulting in 'MustAlias'"); +STATISTIC(NumPartialAliasResults, + "ObcARCAA 'alias' queries resulting in 'PartialAlias'"); +STATISTIC(NumPointsToConstQueries, "ObcARCAA 'pointsToConstantMemory' queries"); +STATISTIC(NumModRefInfoQueries, "ObcARCAA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, + "ObcARCAA 'ModRefInfo' queries resulting in 'NoModRef'"); +STATISTIC(NumModRefBehaviorQueries, "ObcARCAA 'ModRefBehavior' queries"); + AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { if (!EnableARCAliasAnalysis) return AAResultBase::alias(LocA, LocB); + ++NumAliasQueries; // First, strip off no-ops, including ObjC-specific no-ops, and try making a // precise alias query. @@ -53,8 +70,15 @@ AliasResult Result = AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags), MemoryLocation(SB, LocB.Size, LocB.AATags)); - if (Result != MayAlias) + if (Result != MayAlias) { + if (Result == NoAlias) + ++NumNoAliasResults; + else if (Result == MustAlias) + ++NumMustAliasResults; + else if (Result == PartialAlias) + ++NumPartialAliasResults; return Result; + } // If that failed, climb to the underlying object, including climbing through // ObjC-specific no-ops, and try making an imprecise alias query. @@ -64,8 +88,10 @@ Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB)); // We can't use MustAlias or PartialAlias results here because // GetUnderlyingObjCPtr may return an offsetted pointer value. - if (Result == NoAlias) + if (Result == NoAlias) { + ++NumNoAliasResults; return NoAlias; + } } // If that failed, fail. We don't need to chain here, since that's covered @@ -77,6 +103,7 @@ bool OrLocal) { if (!EnableARCAliasAnalysis) return AAResultBase::pointsToConstantMemory(Loc, OrLocal); + ++NumPointsToConstQueries; // First, strip off no-ops, including ObjC-specific no-ops, and try making // a precise alias query. @@ -99,6 +126,7 @@ FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) { if (!EnableARCAliasAnalysis) return AAResultBase::getModRefBehavior(F); + ++NumModRefBehaviorQueries; switch (GetFunctionClass(F)) { case ARCInstKind::NoopCast: @@ -114,6 +142,7 @@ const MemoryLocation &Loc) { if (!EnableARCAliasAnalysis) return AAResultBase::getModRefInfo(CS, Loc); + ++NumModRefInfoQueries; switch (GetBasicARCInstKind(CS.getInstruction())) { case ARCInstKind::Retain: @@ -127,6 +156,7 @@ // These functions don't access any memory visible to the compiler. // Note that this doesn't include objc_retainBlock, because it updates // pointers when it copies block data. + ++NumNoModRefResults; return MRI_NoModRef; default: break; Index: lib/Analysis/ScalarEvolutionAliasAnalysis.cpp =================================================================== --- lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -20,24 +20,37 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/TargetLibraryInfo.h" using namespace llvm; +#define DEBUG_TYPE "scevaa" +STATISTIC(NumAliasQueries, "SCEVAA 'alias' queries"); +STATISTIC(NumNoAliasResults, "SCEVAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumMustAliasResults, + "SCEVAA 'alias' queries resulting in 'MustAlias'"); + AliasResult SCEVAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + ++NumAliasQueries; + // If either of the memory references is empty, it doesn't matter what the // pointer values are. This allows the code below to ignore this special // case. - if (LocA.Size == 0 || LocB.Size == 0) + if (LocA.Size == 0 || LocB.Size == 0) { + ++NumNoAliasResults; return NoAlias; + } // This is SCEVAAResult. Get the SCEVs! const SCEV *AS = SE.getSCEV(const_cast(LocA.Ptr)); const SCEV *BS = SE.getSCEV(const_cast(LocB.Ptr)); // If they evaluate to the same expression, it's a MustAlias. - if (AS == BS) + if (AS == BS) { + ++NumMustAliasResults; return MustAlias; + } // If something is known about the difference between the two addresses, // see if it's enough to prove a NoAlias. @@ -54,8 +67,10 @@ // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt // are non-zero, which is special-cased above. if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) && - (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax())) + (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax())) { + ++NumNoAliasResults; return NoAlias; + } // Folding the subtraction while preserving range information can be tricky // (because of INT_MIN, etc.); if the prior test failed, swap AS and BS @@ -68,8 +83,11 @@ // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt // are non-zero, which is special-cased above. if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) && - (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax())) + (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax())) { + ++NumNoAliasResults; return NoAlias; + } + } // If ScalarEvolution can find an underlying object, form a new query. @@ -83,8 +101,10 @@ AO ? AAMDNodes() : LocA.AATags), MemoryLocation(BO ? BO : LocB.Ptr, BO ? +MemoryLocation::UnknownSize : LocB.Size, - BO ? AAMDNodes() : LocB.AATags)) == NoAlias) + BO ? AAMDNodes() : LocB.AATags)) == NoAlias) { + ++NumNoAliasResults; return NoAlias; + } // Forward the query to the next analysis. return AAResultBase::alias(LocA, LocB); Index: lib/Analysis/ScopedNoAliasAA.cpp =================================================================== --- lib/Analysis/ScopedNoAliasAA.cpp +++ lib/Analysis/ScopedNoAliasAA.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" @@ -43,12 +44,21 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; +#define DEBUG_TYPE "scoped-noalias" + // A handy option for disabling scoped no-alias functionality. The same effect // can also be achieved by stripping the associated metadata tags from IR, but // this option is sometimes more convenient. static cl::opt EnableScopedNoAlias("enable-scoped-noalias", cl::init(true)); +STATISTIC(NumAliasQueries, "ScopedNoAliasAA 'alias' queries"); +STATISTIC(NumNoAliasResults, + "ScopedNoAliasAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumModRefInfoQueries, "ScopedNoAliasAA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, + "ScopedNoAliasAA 'ModRefInfo' queries resulting in 'NoModRef'"); + namespace { /// AliasScopeNode - This is a simple wrapper around an MDNode which provides /// a higher-level interface by hiding the details of how alias analysis @@ -76,17 +86,22 @@ const MemoryLocation &LocB) { if (!EnableScopedNoAlias) return AAResultBase::alias(LocA, LocB); + ++NumAliasQueries; // Get the attached MDNodes. const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope; const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias; - if (!mayAliasInScopes(AScopes, BNoAlias)) + if (!mayAliasInScopes(AScopes, BNoAlias)) { + ++NumNoAliasResults; return NoAlias; + } - if (!mayAliasInScopes(BScopes, ANoAlias)) + if (!mayAliasInScopes(BScopes, ANoAlias)) { + ++NumNoAliasResults; return NoAlias; + } // If they may alias, chain to the next AliasAnalysis. return AAResultBase::alias(LocA, LocB); @@ -96,15 +111,20 @@ const MemoryLocation &Loc) { if (!EnableScopedNoAlias) return AAResultBase::getModRefInfo(CS, Loc); + ++NumModRefInfoQueries; if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata( - LLVMContext::MD_noalias))) + LLVMContext::MD_noalias))) { + ++NumNoModRefResults; return MRI_NoModRef; + } if (!mayAliasInScopes( CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), - Loc.AATags.NoAlias)) + Loc.AATags.NoAlias)) { + ++NumNoModRefResults; return MRI_NoModRef; + } return AAResultBase::getModRefInfo(CS, Loc); } @@ -113,16 +133,21 @@ ImmutableCallSite CS2) { if (!EnableScopedNoAlias) return AAResultBase::getModRefInfo(CS1, CS2); + ++NumModRefInfoQueries; if (!mayAliasInScopes( CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), - CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) + CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) { + ++NumNoModRefResults; return MRI_NoModRef; + } if (!mayAliasInScopes( CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), - CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) + CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) { + ++NumNoModRefResults; return MRI_NoModRef; + } return AAResultBase::getModRefInfo(CS1, CS2); } Index: lib/Analysis/TypeBasedAliasAnalysis.cpp =================================================================== --- lib/Analysis/TypeBasedAliasAnalysis.cpp +++ lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -124,17 +124,28 @@ #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" using namespace llvm; +#define DEBUG_TYPE "tbaa" + // A handy option for disabling TBAA functionality. The same effect can also be // achieved by stripping the !tbaa tags from IR, but this option is sometimes // more convenient. static cl::opt EnableTBAA("enable-tbaa", cl::init(true)); +STATISTIC(NumAliasQueries, "TBAA 'alias' queries"); +STATISTIC(NumNoAliasResults, "TBAA 'alias' queries resulting in 'NoAlias'"); +STATISTIC(NumPointsToConstQueries, "TBAA 'pointsToConstantMemory' queries"); +STATISTIC(NumModRefInfoQueries, "TBAA 'ModRefInfo' queries"); +STATISTIC(NumNoModRefResults, + "TBAA 'ModRefInfo' queries resulting in 'NoModRef'"); +STATISTIC(NumModRefBehaviorQueries, "TBAA 'ModRefBehavior' queries"); + namespace { /// TBAANode - This is a simple wrapper around an MDNode which provides a /// higher-level interface by hiding the details of how alias analysis @@ -283,6 +294,7 @@ const MemoryLocation &LocB) { if (!EnableTBAA) return AAResultBase::alias(LocA, LocB); + ++NumAliasQueries; // Get the attached MDNodes. If either value lacks a tbaa MDNode, we must // be conservative. @@ -298,6 +310,7 @@ return AAResultBase::alias(LocA, LocB); // Otherwise return a definitive result. + ++NumNoAliasResults; return NoAlias; } @@ -305,6 +318,7 @@ bool OrLocal) { if (!EnableTBAA) return AAResultBase::pointsToConstantMemory(Loc, OrLocal); + ++NumPointsToConstQueries; const MDNode *M = Loc.AATags.TBAA; if (!M) @@ -323,6 +337,7 @@ TypeBasedAAResult::getModRefBehavior(ImmutableCallSite CS) { if (!EnableTBAA) return AAResultBase::getModRefBehavior(CS); + ++NumModRefBehaviorQueries; FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior; @@ -345,12 +360,15 @@ const MemoryLocation &Loc) { if (!EnableTBAA) return AAResultBase::getModRefInfo(CS, Loc); + ++NumModRefInfoQueries; if (const MDNode *L = Loc.AATags.TBAA) if (const MDNode *M = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) - if (!Aliases(L, M)) + if (!Aliases(L, M)) { + ++NumNoModRefResults; return MRI_NoModRef; + } return AAResultBase::getModRefInfo(CS, Loc); } @@ -359,13 +377,16 @@ ImmutableCallSite CS2) { if (!EnableTBAA) return AAResultBase::getModRefInfo(CS1, CS2); + ++NumModRefInfoQueries; if (const MDNode *M1 = CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) if (const MDNode *M2 = CS2.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) - if (!Aliases(M1, M2)) + if (!Aliases(M1, M2)) { + ++NumNoModRefResults; return MRI_NoModRef; + } return AAResultBase::getModRefInfo(CS1, CS2); }