#include "ARCRuntimeEntryPoints.h"
#include "BlotMapVector.h"
#include "DependencyAnalysis.h"
#include "ObjCARC.h"
#include "ProvenanceAnalysis.h"
#include "PtrState.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
#include "llvm/Analysis/ObjCARCInstKind.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/ObjCARC.h"
#include <cassert>
#include <iterator>
#include <utility>
usingnamespacellvm;
usingnamespacellvm::objcarc;
#define DEBUG_TYPE …
static cl::opt<unsigned> MaxPtrStates("arc-opt-max-ptr-states",
cl::Hidden,
cl::desc("Maximum number of ptr states the optimizer keeps track of"),
cl::init(4095));
static const Value *FindSingleUseIdentifiedObject(const Value *Arg) { … }
STATISTIC(NumNoops, "Number of no-op objc calls eliminated");
STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");
STATISTIC(NumAutoreleases,"Number of autoreleases converted to releases");
STATISTIC(NumRets, "Number of return value forwarding "
"retain+autoreleases eliminated");
STATISTIC(NumRRs, "Number of retain+release paths eliminated");
STATISTIC(NumPeeps, "Number of calls peephole-optimized");
#ifndef NDEBUG
STATISTIC(NumRetainsBeforeOpt,
"Number of retains before optimization");
STATISTIC(NumReleasesBeforeOpt,
"Number of releases before optimization");
STATISTIC(NumRetainsAfterOpt,
"Number of retains after optimization");
STATISTIC(NumReleasesAfterOpt,
"Number of releases after optimization");
#endif
namespace {
class BBState { … };
}
const unsigned BBState::OverflowOccurredValue = …;
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS,
BBState &BBState) LLVM_ATTRIBUTE_UNUSED;
}
void BBState::InitFromPred(const BBState &Other) { … }
void BBState::InitFromSucc(const BBState &Other) { … }
void BBState::MergePred(const BBState &Other) { … }
void BBState::MergeSucc(const BBState &Other) { … }
raw_ostream &llvm::operator<<(raw_ostream &OS, BBState &BBInfo) { … }
namespace {
class ObjCARCOpt { … };
}
bool
ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { … }
bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall(
Function &F, Instruction *Inst, const Value *&Arg, ARCInstKind Class,
Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) { … }
void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F,
Instruction *AutoreleaseRV,
ARCInstKind &Class) { … }
void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { … }
static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) { … }
void ObjCARCOpt::OptimizeIndividualCallImpl(Function &F, Instruction *Inst,
ARCInstKind Class,
const Value *Arg) { … }
static void CheckForUseCFGHazard(const Sequence SuccSSeq,
const bool SuccSRRIKnownSafe,
TopDownPtrState &S,
bool &SomeSuccHasSame,
bool &AllSuccsHaveSame,
bool &NotAllSeqEqualButKnownSafe,
bool &ShouldContinue) { … }
static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq,
const bool SuccSRRIKnownSafe,
TopDownPtrState &S,
bool &SomeSuccHasSame,
bool &AllSuccsHaveSame,
bool &NotAllSeqEqualButKnownSafe) { … }
void
ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
DenseMap<const BasicBlock *, BBState> &BBStates,
BBState &MyStates) const { … }
bool ObjCARCOpt::VisitInstructionBottomUp(
Instruction *Inst, BasicBlock *BB, BlotMapVector<Value *, RRInfo> &Retains,
BBState &MyStates) { … }
bool ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
DenseMap<const BasicBlock *, BBState> &BBStates,
BlotMapVector<Value *, RRInfo> &Retains) { … }
static void collectReleaseInsertPts(
const BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>
&ReleaseInsertPtToRCIdentityRoots) { … }
static const SmallPtrSet<const Value *, 2> *
getRCIdentityRootsFromReleaseInsertPt(
const Instruction *InsertPt,
const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>
&ReleaseInsertPtToRCIdentityRoots) { … }
bool ObjCARCOpt::VisitInstructionTopDown(
Instruction *Inst, DenseMap<Value *, RRInfo> &Releases, BBState &MyStates,
const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>
&ReleaseInsertPtToRCIdentityRoots) { … }
bool ObjCARCOpt::VisitTopDown(
BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates,
DenseMap<Value *, RRInfo> &Releases,
const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>
&ReleaseInsertPtToRCIdentityRoots) { … }
static void
ComputePostOrders(Function &F,
SmallVectorImpl<BasicBlock *> &PostOrder,
SmallVectorImpl<BasicBlock *> &ReverseCFGPostOrder,
unsigned NoObjCARCExceptionsMDKind,
DenseMap<const BasicBlock *, BBState> &BBStates) { … }
bool ObjCARCOpt::Visit(Function &F,
DenseMap<const BasicBlock *, BBState> &BBStates,
BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases) { … }
void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
RRInfo &ReleasesToMove,
BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
SmallVectorImpl<Instruction *> &DeadInsts,
Module *M) { … }
bool ObjCARCOpt::PairUpRetainsAndReleases(
DenseMap<const BasicBlock *, BBState> &BBStates,
BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases, Module *M,
Instruction *Retain,
SmallVectorImpl<Instruction *> &DeadInsts, RRInfo &RetainsToMove,
RRInfo &ReleasesToMove, Value *Arg, bool KnownSafe,
bool &AnyPairsCompletelyEliminated) { … }
bool ObjCARCOpt::PerformCodePlacement(
DenseMap<const BasicBlock *, BBState> &BBStates,
BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases, Module *M) { … }
void ObjCARCOpt::OptimizeWeakCalls(Function &F) { … }
bool ObjCARCOpt::OptimizeSequences(Function &F) { … }
static CallInst *HasSafePathToPredecessorCall(const Value *Arg,
Instruction *Retain,
ProvenanceAnalysis &PA) { … }
static CallInst *
FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB,
Instruction *Autorelease,
ProvenanceAnalysis &PA) { … }
static CallInst *
FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB,
ReturnInst *Ret,
ProvenanceAnalysis &PA) { … }
void ObjCARCOpt::OptimizeReturns(Function &F) { … }
#ifndef NDEBUG
void
ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) {
Statistic &NumRetains =
AfterOptimization ? NumRetainsAfterOpt : NumRetainsBeforeOpt;
Statistic &NumReleases =
AfterOptimization ? NumReleasesAfterOpt : NumReleasesBeforeOpt;
for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
Instruction *Inst = &*I++;
switch (GetBasicARCInstKind(Inst)) {
default:
break;
case ARCInstKind::Retain:
++NumRetains;
break;
case ARCInstKind::Release:
++NumReleases;
break;
}
}
}
#endif
void ObjCARCOpt::init(Function &F) { … }
bool ObjCARCOpt::run(Function &F, AAResults &AA) { … }
PreservedAnalyses ObjCARCOptPass::run(Function &F,
FunctionAnalysisManager &AM) { … }