Index: llvm/include/llvm/Analysis/AssumeBundleQueries.h =================================================================== --- llvm/include/llvm/Analysis/AssumeBundleQueries.h +++ llvm/include/llvm/Analysis/AssumeBundleQueries.h @@ -15,7 +15,6 @@ #define LLVM_ANALYSIS_ASSUMEBUNDLEQUERIES_H #include "llvm/ADT/DenseMap.h" -#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" namespace llvm { Index: llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h =================================================================== --- llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -66,16 +66,7 @@ /// This is a wrapper around getUnderlyingObject which also knows how to /// look through objc_retain and objc_autorelease calls, which we know to return /// their argument verbatim. -inline const Value *GetUnderlyingObjCPtr(const Value *V) { - for (;;) { - V = getUnderlyingObject(V); - if (!IsForwarding(GetBasicARCInstKind(V))) - break; - V = cast(V)->getArgOperand(0); - } - - return V; -} +const Value *GetUnderlyingObjCPtr(const Value *V); /// A wrapper for GetUnderlyingObjCPtr used for results memoization. inline const Value *GetUnderlyingObjCPtrCached( @@ -107,15 +98,7 @@ /// /// Thus this function strips off pointer casts and forwarding calls. *NOTE* /// This implies that two RCIdentical values must alias. -inline const Value *GetRCIdentityRoot(const Value *V) { - for (;;) { - V = V->stripPointerCasts(); - if (!IsForwarding(GetBasicARCInstKind(V))) - break; - V = cast(V)->getArgOperand(0); - } - return V; -} +const Value *GetRCIdentityRoot(const Value *V); /// Helper which calls const Value *GetRCIdentityRoot(const Value *V) and just /// casts away the const of the result. For documentation about what an @@ -128,43 +111,16 @@ /// Assuming the given instruction is one of the special calls such as /// objc_retain or objc_release, return the RCIdentity root of the argument of /// the call. -inline Value *GetArgRCIdentityRoot(Value *Inst) { - return GetRCIdentityRoot(cast(Inst)->getArgOperand(0)); -} +Value *GetArgRCIdentityRoot(Value *Inst); inline bool IsNullOrUndef(const Value *V) { return isa(V) || isa(V); } -inline bool IsNoopInstruction(const Instruction *I) { - return isa(I) || - (isa(I) && - cast(I)->hasAllZeroIndices()); -} +bool IsNoopInstruction(const Instruction *I); /// Test whether the given value is possible a retainable object pointer. -inline bool IsPotentialRetainableObjPtr(const Value *Op) { - // Pointers to static or stack storage are not valid retainable object - // pointers. - if (isa(Op) || isa(Op)) - return false; - // Special arguments can not be a valid retainable object pointer. - if (const Argument *Arg = dyn_cast(Op)) - if (Arg->hasPassPointeeByValueCopyAttr() || Arg->hasNestAttr() || - Arg->hasStructRetAttr()) - return false; - // Only consider values with pointer types. - // - // It seemes intuitive to exclude function pointer types as well, since - // functions are never retainable object pointers, however clang occasionally - // bitcasts retainable object pointers to function-pointer type temporarily. - PointerType *Ty = dyn_cast(Op->getType()); - if (!Ty) - return false; - // Conservatively assume anything else is a potential retainable object - // pointer. - return true; -} +bool IsPotentialRetainableObjPtr(const Value *Op); bool IsPotentialRetainableObjPtr(const Value *Op, AAResults &AA); @@ -183,40 +139,7 @@ /// /// This is similar to AliasAnalysis's isIdentifiedObject, except that it uses /// special knowledge of ObjC conventions. -inline bool IsObjCIdentifiedObject(const Value *V) { - // Assume that call results and arguments have their own "provenance". - // Constants (including GlobalVariables) and Allocas are never - // reference-counted. - if (isa(V) || isa(V) || - isa(V) || isa(V) || - isa(V)) - return true; - - if (const LoadInst *LI = dyn_cast(V)) { - const Value *Pointer = - GetRCIdentityRoot(LI->getPointerOperand()); - if (const GlobalVariable *GV = dyn_cast(Pointer)) { - // A constant pointer can't be pointing to an object on the heap. It may - // be reference-counted, but it won't be deleted. - if (GV->isConstant()) - return true; - StringRef Name = GV->getName(); - // These special variables are known to hold values which are not - // reference-counted pointers. - if (Name.startswith("\01l_objc_msgSend_fixup_")) - return true; - - StringRef Section = GV->getSection(); - if (Section.contains("__message_refs") || - Section.contains("__objc_classrefs") || - Section.contains("__objc_superrefs") || - Section.contains("__objc_methname") || Section.contains("__cstring")) - return true; - } - } - - return false; -} +bool IsObjCIdentifiedObject(const Value *V); enum class ARCMDKindID { ImpreciseRelease, Index: llvm/include/llvm/Analysis/ObjCARCInstKind.h =================================================================== --- llvm/include/llvm/Analysis/ObjCARCInstKind.h +++ llvm/include/llvm/Analysis/ObjCARCInstKind.h @@ -9,9 +9,13 @@ #ifndef LLVM_ANALYSIS_OBJCARCINSTKIND_H #define LLVM_ANALYSIS_OBJCARCINSTKIND_H -#include "llvm/IR/Instructions.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { + +class Function; +class Value; + namespace objcarc { /// \enum ARCInstKind @@ -101,17 +105,7 @@ /// This is similar to GetARCInstKind except that it only detects objc /// runtime calls. This allows it to be faster. /// -inline ARCInstKind GetBasicARCInstKind(const Value *V) { - if (const CallInst *CI = dyn_cast(V)) { - if (const Function *F = CI->getCalledFunction()) - return GetFunctionClass(F); - // Otherwise, be conservative. - return ARCInstKind::CallOrUser; - } - - // Otherwise, be conservative. - return isa(V) ? ARCInstKind::CallOrUser : ARCInstKind::User; -} +ARCInstKind GetBasicARCInstKind(const Value *V); /// Map V to its ARCInstKind equivalence class. ARCInstKind GetARCInstKind(const Value *V); Index: llvm/lib/Analysis/ObjCARCAnalysisUtils.cpp =================================================================== --- llvm/lib/Analysis/ObjCARCAnalysisUtils.cpp +++ llvm/lib/Analysis/ObjCARCAnalysisUtils.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/ObjCARCAnalysisUtils.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/CommandLine.h" using namespace llvm; @@ -25,6 +26,60 @@ "enable-objc-arc-opts", cl::desc("enable/disable all ARC Optimizations"), cl::location(EnableARCOpts), cl::init(true), cl::Hidden); +const Value *llvm::objcarc::GetUnderlyingObjCPtr(const Value *V) { + for (;;) { + V = getUnderlyingObject(V); + if (!IsForwarding(GetBasicARCInstKind(V))) + break; + V = cast(V)->getArgOperand(0); + } + + return V; +} + +const Value *llvm::objcarc::GetRCIdentityRoot(const Value *V) { + for (;;) { + V = V->stripPointerCasts(); + if (!IsForwarding(GetBasicARCInstKind(V))) + break; + V = cast(V)->getArgOperand(0); + } + return V; +} + +Value *llvm::objcarc::GetArgRCIdentityRoot(Value *Inst) { + return GetRCIdentityRoot(cast(Inst)->getArgOperand(0)); +} + +bool llvm::objcarc::IsNoopInstruction(const Instruction *I) { + return isa(I) || + (isa(I) && + cast(I)->hasAllZeroIndices()); +} + +bool llvm::objcarc::IsPotentialRetainableObjPtr(const Value *Op) { + // Pointers to static or stack storage are not valid retainable object + // pointers. + if (isa(Op) || isa(Op)) + return false; + // Special arguments can not be a valid retainable object pointer. + if (const Argument *Arg = dyn_cast(Op)) + if (Arg->hasPassPointeeByValueCopyAttr() || Arg->hasNestAttr() || + Arg->hasStructRetAttr()) + return false; + // Only consider values with pointer types. + // + // It seemes intuitive to exclude function pointer types as well, since + // functions are never retainable object pointers, however clang occasionally + // bitcasts retainable object pointers to function-pointer type temporarily. + PointerType *Ty = dyn_cast(Op->getType()); + if (!Ty) + return false; + // Conservatively assume anything else is a potential retainable object + // pointer. + return true; +} + bool llvm::objcarc::IsPotentialRetainableObjPtr(const Value *Op, AAResults &AA) { // First make the rudimentary check. @@ -43,3 +98,36 @@ // Otherwise assume the worst. return true; } + +bool llvm::objcarc::IsObjCIdentifiedObject(const Value *V) { + // Assume that call results and arguments have their own "provenance". + // Constants (including GlobalVariables) and Allocas are never + // reference-counted. + if (isa(V) || isa(V) || isa(V) || + isa(V) || isa(V)) + return true; + + if (const LoadInst *LI = dyn_cast(V)) { + const Value *Pointer = GetRCIdentityRoot(LI->getPointerOperand()); + if (const GlobalVariable *GV = dyn_cast(Pointer)) { + // A constant pointer can't be pointing to an object on the heap. It may + // be reference-counted, but it won't be deleted. + if (GV->isConstant()) + return true; + StringRef Name = GV->getName(); + // These special variables are known to hold values which are not + // reference-counted pointers. + if (Name.startswith("\01l_objc_msgSend_fixup_")) + return true; + + StringRef Section = GV->getSection(); + if (Section.contains("__message_refs") || + Section.contains("__objc_classrefs") || + Section.contains("__objc_superrefs") || + Section.contains("__objc_methname") || Section.contains("__cstring")) + return true; + } + } + + return false; +} Index: llvm/lib/Analysis/ObjCARCInstKind.cpp =================================================================== --- llvm/lib/Analysis/ObjCARCInstKind.cpp +++ llvm/lib/Analysis/ObjCARCInstKind.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/Analysis/ObjCARCAnalysisUtils.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" using namespace llvm; @@ -153,6 +154,18 @@ } } +ARCInstKind llvm::objcarc::GetBasicARCInstKind(const Value *V) { + if (const CallInst *CI = dyn_cast(V)) { + if (const Function *F = CI->getCalledFunction()) + return GetFunctionClass(F); + // Otherwise, be conservative. + return ARCInstKind::CallOrUser; + } + + // Otherwise, be conservative. + return isa(V) ? ARCInstKind::CallOrUser : ARCInstKind::User; +} + // A list of intrinsics that we know do not use objc pointers or decrement // ref counts. static bool isInertIntrinsic(unsigned ID) {