aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/ObjCARC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC')
-rw-r--r--llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp6
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARC.cpp21
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARC.h4
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp29
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp5
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp26
-rw-r--r--llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp172
-rw-r--r--llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp70
-rw-r--r--llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h1
-rw-r--r--llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp38
-rw-r--r--llvm/lib/Transforms/ObjCARC/PtrState.cpp4
11 files changed, 124 insertions, 252 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
index de0f5803b4c7..0fea6bcc4882 100644
--- a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
+++ b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
@@ -48,10 +48,10 @@ bool llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
const auto *Call = cast<CallBase>(Inst);
// See if AliasAnalysis can help us with the call.
- FunctionModRefBehavior MRB = PA.getAA()->getModRefBehavior(Call);
- if (AliasAnalysis::onlyReadsMemory(MRB))
+ MemoryEffects ME = PA.getAA()->getMemoryEffects(Call);
+ if (ME.onlyReadsMemory())
return false;
- if (AliasAnalysis::onlyAccessesArgPointees(MRB)) {
+ if (ME.onlyAccessesArgPointees()) {
for (const Value *Op : Call->args()) {
if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op))
return true;
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
index 70f150c9461a..02f9db719e26 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
@@ -13,35 +13,14 @@
//===----------------------------------------------------------------------===//
#include "ObjCARC.h"
-#include "llvm-c/Initialization.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/InitializePasses.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-namespace llvm {
- class PassRegistry;
-}
-
using namespace llvm;
using namespace llvm::objcarc;
-/// initializeObjCARCOptsPasses - Initialize all passes linked into the
-/// ObjCARCOpts library.
-void llvm::initializeObjCARCOpts(PassRegistry &Registry) {
- initializeObjCARCAAWrapperPassPass(Registry);
- initializeObjCARCAPElimPass(Registry);
- initializeObjCARCExpandPass(Registry);
- initializeObjCARCContractLegacyPassPass(Registry);
- initializeObjCARCOptLegacyPassPass(Registry);
- initializePAEvalPass(Registry);
-}
-
-void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R) {
- initializeObjCARCOpts(*unwrap(R));
-}
-
CallInst *objcarc::createCallInstWithColors(
FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,
Instruction *InsertBefore,
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
index 2bc0c8f87d77..d4570ff908f1 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
@@ -132,8 +132,8 @@ public:
auto It = RVCalls.find(CI);
if (It != RVCalls.end()) {
// Remove call to @llvm.objc.clang.arc.noop.use.
- for (auto U = It->second->user_begin(), E = It->second->user_end(); U != E; ++U)
- if (auto *CI = dyn_cast<CallInst>(*U))
+ for (User *U : It->second->users())
+ if (auto *CI = dyn_cast<CallInst>(U))
if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) {
CI->eraseFromParent();
break;
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
index 03e5fb18d5ac..dceb2ebb1863 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
@@ -29,8 +29,6 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/PassManager.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/ObjCARC.h"
@@ -147,35 +145,8 @@ bool runImpl(Module &M) {
return Changed;
}
-/// Autorelease pool elimination.
-class ObjCARCAPElim : public ModulePass {
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnModule(Module &M) override;
-
-public:
- static char ID;
- ObjCARCAPElim() : ModulePass(ID) {
- initializeObjCARCAPElimPass(*PassRegistry::getPassRegistry());
- }
-};
} // namespace
-char ObjCARCAPElim::ID = 0;
-INITIALIZE_PASS(ObjCARCAPElim, "objc-arc-apelim",
- "ObjC ARC autorelease pool elimination", false, false)
-
-Pass *llvm::createObjCARCAPElimPass() { return new ObjCARCAPElim(); }
-
-void ObjCARCAPElim::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
-}
-
-bool ObjCARCAPElim::runOnModule(Module &M) {
- if (skipModule(M))
- return false;
- return runImpl(M);
-}
-
PreservedAnalyses ObjCARCAPElimPass::run(Module &M, ModuleAnalysisManager &AM) {
if (!runImpl(M))
return PreservedAnalyses::all();
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
index f64c26ef2bed..ab90ef090ae0 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
@@ -428,7 +428,7 @@ bool ObjCARCContract::tryToPeepholeInstruction(
if (!optimizeRetainCall(F, Inst))
return false;
// If we succeed in our optimization, fall through.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case ARCInstKind::RetainRV:
case ARCInstKind::UnsafeClaimRV: {
// Return true if this is a bundled retainRV/claimRV call, which is always
@@ -472,7 +472,8 @@ bool ObjCARCContract::tryToPeepholeInstruction(
RVInstMarker->getString(),
/*Constraints=*/"", /*hasSideEffects=*/true);
- objcarc::createCallInstWithColors(IA, None, "", Inst, BlockColors);
+ objcarc::createCallInstWithColors(IA, std::nullopt, "", Inst,
+ BlockColors);
}
decline_rv_optimization:
return false;
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp
index efcdc51ef5e3..bb0a01b78a96 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp
@@ -29,9 +29,6 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Value.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Pass.h"
-#include "llvm/PassRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -89,31 +86,8 @@ static bool runImpl(Function &F) {
return Changed;
}
-/// Early ARC transformations.
-class ObjCARCExpand : public FunctionPass {
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnFunction(Function &F) override;
-
-public:
- static char ID;
- ObjCARCExpand() : FunctionPass(ID) {
- initializeObjCARCExpandPass(*PassRegistry::getPassRegistry());
- }
-};
} // namespace
-char ObjCARCExpand::ID = 0;
-INITIALIZE_PASS(ObjCARCExpand, "objc-arc-expand", "ObjC ARC expansion", false,
- false)
-
-Pass *llvm::createObjCARCExpandPass() { return new ObjCARCExpand(); }
-
-void ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
-}
-
-bool ObjCARCExpand::runOnFunction(Function &F) { return runImpl(F); }
-
PreservedAnalyses ObjCARCExpandPass::run(Function &F,
FunctionAnalysisManager &AM) {
if (!runImpl(F))
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index e1a000b31cf9..a374958f9707 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -31,7 +31,6 @@
#include "ProvenanceAnalysis.h"
#include "PtrState.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -58,8 +57,6 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -483,8 +480,8 @@ namespace {
/// The main ARC optimization pass.
class ObjCARCOpt {
- bool Changed;
- bool CFGChanged;
+ bool Changed = false;
+ bool CFGChanged = false;
ProvenanceAnalysis PA;
/// A cache of references to runtime entry point constants.
@@ -504,6 +501,8 @@ class ObjCARCOpt {
/// is in fact used in the current function.
unsigned UsedInThisFunction;
+ DenseMap<BasicBlock *, ColorVector> BlockEHColors;
+
bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV);
void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,
ARCInstKind &Class);
@@ -511,17 +510,16 @@ class ObjCARCOpt {
/// Optimize an individual call, optionally passing the
/// GetArgRCIdentityRoot if it has already been computed.
- void OptimizeIndividualCallImpl(
- Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
- Instruction *Inst, ARCInstKind Class, const Value *Arg);
+ void OptimizeIndividualCallImpl(Function &F, Instruction *Inst,
+ ARCInstKind Class, const Value *Arg);
/// Try to optimize an AutoreleaseRV with a RetainRV or UnsafeClaimRV. If the
/// optimization occurs, returns true to indicate that the caller should
/// assume the instructions are dead.
- bool OptimizeInlinedAutoreleaseRVCall(
- Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
- Instruction *Inst, const Value *&Arg, ARCInstKind Class,
- Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg);
+ bool OptimizeInlinedAutoreleaseRVCall(Function &F, Instruction *Inst,
+ const Value *&Arg, ARCInstKind Class,
+ Instruction *AutoreleaseRV,
+ const Value *&AutoreleaseRVArg);
void CheckForCFGHazards(const BasicBlock *BB,
DenseMap<const BasicBlock *, BBState> &BBStates,
@@ -569,54 +567,41 @@ class ObjCARCOpt {
void OptimizeReturns(Function &F);
+ template <typename PredicateT>
+ static void cloneOpBundlesIf(CallBase *CI,
+ SmallVectorImpl<OperandBundleDef> &OpBundles,
+ PredicateT Predicate) {
+ for (unsigned I = 0, E = CI->getNumOperandBundles(); I != E; ++I) {
+ OperandBundleUse B = CI->getOperandBundleAt(I);
+ if (Predicate(B))
+ OpBundles.emplace_back(B);
+ }
+ }
+
+ void addOpBundleForFunclet(BasicBlock *BB,
+ SmallVectorImpl<OperandBundleDef> &OpBundles) {
+ if (!BlockEHColors.empty()) {
+ const ColorVector &CV = BlockEHColors.find(BB)->second;
+ assert(CV.size() > 0 && "Uncolored block");
+ for (BasicBlock *EHPadBB : CV)
+ if (auto *EHPad = dyn_cast<FuncletPadInst>(EHPadBB->getFirstNonPHI())) {
+ OpBundles.emplace_back("funclet", EHPad);
+ return;
+ }
+ }
+ }
+
#ifndef NDEBUG
void GatherStatistics(Function &F, bool AfterOptimization = false);
#endif
public:
- void init(Module &M);
+ void init(Function &F);
bool run(Function &F, AAResults &AA);
- void releaseMemory();
bool hasCFGChanged() const { return CFGChanged; }
};
-
-/// The main ARC optimization pass.
-class ObjCARCOptLegacyPass : public FunctionPass {
-public:
- ObjCARCOptLegacyPass() : FunctionPass(ID) {
- initializeObjCARCOptLegacyPassPass(*PassRegistry::getPassRegistry());
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool doInitialization(Module &M) override {
- OCAO.init(M);
- return false;
- }
- bool runOnFunction(Function &F) override {
- return OCAO.run(F, getAnalysis<AAResultsWrapperPass>().getAAResults());
- }
- void releaseMemory() override { OCAO.releaseMemory(); }
- static char ID;
-
-private:
- ObjCARCOpt OCAO;
-};
} // end anonymous namespace
-char ObjCARCOptLegacyPass::ID = 0;
-
-INITIALIZE_PASS_BEGIN(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization",
- false, false)
-INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
-INITIALIZE_PASS_END(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization",
- false, false)
-
-Pass *llvm::createObjCARCOptPass() { return new ObjCARCOptLegacyPass(); }
-
-void ObjCARCOptLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<ObjCARCAAWrapperPass>();
- AU.addRequired<AAResultsWrapperPass>();
-}
-
/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
/// not a return value.
bool
@@ -664,8 +649,7 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
}
bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall(
- Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
- Instruction *Inst, const Value *&Arg, ARCInstKind Class,
+ Function &F, Instruction *Inst, const Value *&Arg, ARCInstKind Class,
Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) {
if (BundledInsts->contains(Inst))
return false;
@@ -718,8 +702,7 @@ bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall(
EraseInstruction(Inst);
// Run the normal optimizations on Release.
- OptimizeIndividualCallImpl(F, BlockColors, Release, ARCInstKind::Release,
- Arg);
+ OptimizeIndividualCallImpl(F, Release, ARCInstKind::Release, Arg);
return true;
}
@@ -772,31 +755,6 @@ void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F,
LLVM_DEBUG(dbgs() << "New: " << *AutoreleaseRV << "\n");
}
-namespace {
-Instruction *
-CloneCallInstForBB(CallInst &CI, BasicBlock &BB,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
- SmallVector<OperandBundleDef, 1> OpBundles;
- for (unsigned I = 0, E = CI.getNumOperandBundles(); I != E; ++I) {
- auto Bundle = CI.getOperandBundleAt(I);
- // Funclets will be reassociated in the future.
- if (Bundle.getTagID() == LLVMContext::OB_funclet)
- continue;
- OpBundles.emplace_back(Bundle);
- }
-
- if (!BlockColors.empty()) {
- const ColorVector &CV = BlockColors.find(&BB)->second;
- assert(CV.size() == 1 && "non-unique color for block!");
- Instruction *EHPad = CV.front()->getFirstNonPHI();
- if (EHPad->isEHPad())
- OpBundles.emplace_back("funclet", EHPad);
- }
-
- return CallInst::Create(&CI, OpBundles);
-}
-}
-
/// Visit each call, one at a time, and make simplifications without doing any
/// additional analysis.
void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
@@ -804,11 +762,6 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
// Reset all the flags in preparation for recomputing them.
UsedInThisFunction = 0;
- DenseMap<BasicBlock *, ColorVector> BlockColors;
- if (F.hasPersonalityFn() &&
- isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
- BlockColors = colorEHFunclets(F);
-
// Store any delayed AutoreleaseRV intrinsics, so they can be easily paired
// with RetainRV and UnsafeClaimRV.
Instruction *DelayedAutoreleaseRV = nullptr;
@@ -821,7 +774,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
auto optimizeDelayedAutoreleaseRV = [&]() {
if (!DelayedAutoreleaseRV)
return;
- OptimizeIndividualCallImpl(F, BlockColors, DelayedAutoreleaseRV,
+ OptimizeIndividualCallImpl(F, DelayedAutoreleaseRV,
ARCInstKind::AutoreleaseRV,
DelayedAutoreleaseRVArg);
setDelayedAutoreleaseRV(nullptr);
@@ -884,7 +837,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
case ARCInstKind::UnsafeClaimRV:
if (DelayedAutoreleaseRV) {
// We have a potential RV pair. Check if they cancel out.
- if (OptimizeInlinedAutoreleaseRVCall(F, BlockColors, Inst, Arg, Class,
+ if (OptimizeInlinedAutoreleaseRVCall(F, Inst, Arg, Class,
DelayedAutoreleaseRV,
DelayedAutoreleaseRVArg)) {
setDelayedAutoreleaseRV(nullptr);
@@ -895,7 +848,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
break;
}
- OptimizeIndividualCallImpl(F, BlockColors, Inst, Class, Arg);
+ OptimizeIndividualCallImpl(F, Inst, Class, Arg);
}
// Catch the final delayed AutoreleaseRV.
@@ -929,9 +882,9 @@ static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) {
return false;
}
-void ObjCARCOpt::OptimizeIndividualCallImpl(
- Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
- Instruction *Inst, ARCInstKind Class, const Value *Arg) {
+void ObjCARCOpt::OptimizeIndividualCallImpl(Function &F, Instruction *Inst,
+ ARCInstKind Class,
+ const Value *Arg) {
LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
// We can delete this call if it takes an inert value.
@@ -1038,7 +991,7 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
CallInst *NewCall =
CallInst::Create(Decl, Call->getArgOperand(0), "", Call);
NewCall->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease),
- MDNode::get(C, None));
+ MDNode::get(C, std::nullopt));
LLVM_DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) "
"since x is otherwise unused.\nOld: "
@@ -1189,8 +1142,12 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
continue;
Value *Op = PN->getIncomingValue(i);
Instruction *InsertPos = &PN->getIncomingBlock(i)->back();
- CallInst *Clone = cast<CallInst>(
- CloneCallInstForBB(*CInst, *InsertPos->getParent(), BlockColors));
+ SmallVector<OperandBundleDef, 1> OpBundles;
+ cloneOpBundlesIf(CInst, OpBundles, [](const OperandBundleUse &B) {
+ return B.getTagID() != LLVMContext::OB_funclet;
+ });
+ addOpBundleForFunclet(InsertPos->getParent(), OpBundles);
+ CallInst *Clone = CallInst::Create(CInst, OpBundles);
if (Op->getType() != ParamTy)
Op = new BitCastInst(Op, ParamTy, "", InsertPos);
Clone->setArgOperand(0, Op);
@@ -1503,7 +1460,7 @@ static void collectReleaseInsertPts(
const BlotMapVector<Value *, RRInfo> &Retains,
DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>
&ReleaseInsertPtToRCIdentityRoots) {
- for (auto &P : Retains) {
+ for (const auto &P : Retains) {
// Retains is a map from an objc_retain call to a RRInfo of the RC identity
// root of the call. Get the RC identity root of the objc_retain call.
Instruction *Retain = cast<Instruction>(P.first);
@@ -1541,7 +1498,7 @@ bool ObjCARCOpt::VisitInstructionTopDown(
if (const SmallPtrSet<const Value *, 2> *Roots =
getRCIdentityRootsFromReleaseInsertPt(
Inst, ReleaseInsertPtToRCIdentityRoots))
- for (auto *Root : *Roots) {
+ for (const auto *Root : *Roots) {
TopDownPtrState &S = MyStates.getPtrTopDownState(Root);
// Disable code motion if the current position is S_Retain to prevent
// moving the objc_retain call past objc_release calls. If it's
@@ -1812,7 +1769,9 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt);
Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);
- CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
+ SmallVector<OperandBundleDef, 1> BundleList;
+ addOpBundleForFunclet(InsertPt->getParent(), BundleList);
+ CallInst *Call = CallInst::Create(Decl, MyArg, BundleList, "", InsertPt);
Call->setDoesNotThrow();
Call->setTailCall();
@@ -1825,7 +1784,9 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt);
Function *Decl = EP.get(ARCRuntimeEntryPointKind::Release);
- CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
+ SmallVector<OperandBundleDef, 1> BundleList;
+ addOpBundleForFunclet(InsertPt->getParent(), BundleList);
+ CallInst *Call = CallInst::Create(Decl, MyArg, BundleList, "", InsertPt);
// Attach a clang.imprecise_release metadata tag, if appropriate.
if (MDNode *M = ReleasesToMove.ReleaseMetadata)
Call->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease), M);
@@ -2441,17 +2402,22 @@ ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) {
}
#endif
-void ObjCARCOpt::init(Module &M) {
+void ObjCARCOpt::init(Function &F) {
if (!EnableARCOpts)
return;
// Intuitively, objc_retain and others are nocapture, however in practice
// they are not, because they return their argument value. And objc_release
// calls finalizers which can have arbitrary side effects.
- MDKindCache.init(&M);
+ MDKindCache.init(F.getParent());
// Initialize our runtime entry point cache.
- EP.init(&M);
+ EP.init(F.getParent());
+
+ // Compute which blocks are in which funclet.
+ if (F.hasPersonalityFn() &&
+ isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
+ BlockEHColors = colorEHFunclets(F);
}
bool ObjCARCOpt::run(Function &F, AAResults &AA) {
@@ -2521,17 +2487,13 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
return Changed;
}
-void ObjCARCOpt::releaseMemory() {
- PA.clear();
-}
-
/// @}
///
PreservedAnalyses ObjCARCOptPass::run(Function &F,
FunctionAnalysisManager &AM) {
ObjCARCOpt OCAO;
- OCAO.init(*F.getParent());
+ OCAO.init(F);
bool Changed = OCAO.run(F, AM.getResult<AAManager>(F));
bool CFGChanged = OCAO.hasCFGChanged();
diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
index 6731b841771c..2fa25a79ae9d 100644
--- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp
@@ -42,21 +42,40 @@ bool ProvenanceAnalysis::relatedSelect(const SelectInst *A,
const Value *B) {
// If the values are Selects with the same condition, we can do a more precise
// check: just check for relations between the values on corresponding arms.
- if (const SelectInst *SB = dyn_cast<SelectInst>(B))
+ if (const SelectInst *SB = dyn_cast<SelectInst>(B)) {
if (A->getCondition() == SB->getCondition())
return related(A->getTrueValue(), SB->getTrueValue()) ||
related(A->getFalseValue(), SB->getFalseValue());
+ // Check both arms of B individually. Return false if neither arm is related
+ // to A.
+ if (!(related(SB->getTrueValue(), A) || related(SB->getFalseValue(), A)))
+ return false;
+ }
+
// Check both arms of the Select node individually.
return related(A->getTrueValue(), B) || related(A->getFalseValue(), B);
}
bool ProvenanceAnalysis::relatedPHI(const PHINode *A,
const Value *B) {
- // If the values are PHIs in the same block, we can do a more precise as well
- // as efficient check: just check for relations between the values on
- // corresponding edges.
- if (const PHINode *PNB = dyn_cast<PHINode>(B))
+
+ auto comparePHISources = [this](const PHINode *PNA, const Value *B) -> bool {
+ // Check each unique source of the PHI node against B.
+ SmallPtrSet<const Value *, 4> UniqueSrc;
+ for (Value *PV1 : PNA->incoming_values()) {
+ if (UniqueSrc.insert(PV1).second && related(PV1, B))
+ return true;
+ }
+
+ // All of the arms checked out.
+ return false;
+ };
+
+ if (const PHINode *PNB = dyn_cast<PHINode>(B)) {
+ // If the values are PHIs in the same block, we can do a more precise as
+ // well as efficient check: just check for relations between the values on
+ // corresponding edges.
if (PNB->getParent() == A->getParent()) {
for (unsigned i = 0, e = A->getNumIncomingValues(); i != e; ++i)
if (related(A->getIncomingValue(i),
@@ -65,15 +84,11 @@ bool ProvenanceAnalysis::relatedPHI(const PHINode *A,
return false;
}
- // Check each unique source of the PHI node against B.
- SmallPtrSet<const Value *, 4> UniqueSrc;
- for (Value *PV1 : A->incoming_values()) {
- if (UniqueSrc.insert(PV1).second && related(PV1, B))
- return true;
+ if (!comparePHISources(PNB, A))
+ return false;
}
- // All of the arms checked out.
- return false;
+ return comparePHISources(A, B);
}
/// Test if the value of P, or any value covered by its provenance, is ever
@@ -125,22 +140,19 @@ bool ProvenanceAnalysis::relatedCheck(const Value *A, const Value *B) {
bool BIsIdentified = IsObjCIdentifiedObject(B);
// An ObjC-Identified object can't alias a load if it is never locally stored.
- if (AIsIdentified) {
- // Check for an obvious escape.
- if (isa<LoadInst>(B))
- return IsStoredObjCPointer(A);
- if (BIsIdentified) {
- // Check for an obvious escape.
- if (isa<LoadInst>(A))
- return IsStoredObjCPointer(B);
- // Both pointers are identified and escapes aren't an evident problem.
- return false;
- }
- } else if (BIsIdentified) {
- // Check for an obvious escape.
- if (isa<LoadInst>(A))
- return IsStoredObjCPointer(B);
- }
+
+ // Check for an obvious escape.
+ if ((AIsIdentified && isa<LoadInst>(B) && !IsStoredObjCPointer(A)) ||
+ (BIsIdentified && isa<LoadInst>(A) && !IsStoredObjCPointer(B)))
+ return false;
+
+ if ((AIsIdentified && isa<LoadInst>(B)) ||
+ (BIsIdentified && isa<LoadInst>(A)))
+ return true;
+
+ // Both pointers are identified and escapes aren't an evident problem.
+ if (AIsIdentified && BIsIdentified && !isa<LoadInst>(A) && !isa<LoadInst>(B))
+ return false;
// Special handling for PHI and Select.
if (const PHINode *PN = dyn_cast<PHINode>(A))
@@ -174,6 +186,8 @@ bool ProvenanceAnalysis::related(const Value *A, const Value *B) {
return Pair.first->second;
bool Result = relatedCheck(A, B);
+ assert(relatedCheck(B, A) == Result &&
+ "relatedCheck result depending on order of parameters!");
CachedResults[ValuePairTy(A, B)] = Result;
return Result;
}
diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h
index 1624cf26094a..bc946fac4544 100644
--- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h
+++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h
@@ -26,6 +26,7 @@
#define LLVM_LIB_TRANSFORMS_OBJCARC_PROVENANCEANALYSIS_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include <utility>
diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp
index fe637ee066a4..9f15772f2fa1 100644
--- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp
@@ -7,38 +7,16 @@
//===----------------------------------------------------------------------===//
#include "ProvenanceAnalysis.h"
+#include "llvm/Transforms/ObjCARC.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
-#include "llvm/IR/InstrTypes.h"
-#include "llvm/IR/Module.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::objcarc;
-namespace {
-class PAEval : public FunctionPass {
-
-public:
- static char ID;
- PAEval();
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnFunction(Function &F) override;
-};
-}
-
-char PAEval::ID = 0;
-PAEval::PAEval() : FunctionPass(ID) {}
-
-void PAEval::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<AAResultsWrapperPass>();
-}
-
static StringRef getName(Value *V) {
StringRef Name = V->getName();
if (Name.startswith("\1"))
@@ -52,7 +30,7 @@ static void insertIfNamed(SetVector<Value *> &Values, Value *V) {
Values.insert(V);
}
-bool PAEval::runOnFunction(Function &F) {
+PreservedAnalyses PAEvalPass::run(Function &F, FunctionAnalysisManager &AM) {
SetVector<Value *> Values;
for (auto &Arg : F.args())
@@ -66,7 +44,7 @@ bool PAEval::runOnFunction(Function &F) {
}
ProvenanceAnalysis PA;
- PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
+ PA.setAA(&AM.getResult<AAManager>(F));
for (Value *V1 : Values) {
StringRef NameV1 = getName(V1);
@@ -82,13 +60,5 @@ bool PAEval::runOnFunction(Function &F) {
}
}
- return false;
+ return PreservedAnalyses::all();
}
-
-FunctionPass *llvm::createPAEvalPass() { return new PAEval(); }
-
-INITIALIZE_PASS_BEGIN(PAEval, "pa-eval",
- "Evaluate ProvenanceAnalysis on all pairs", false, true)
-INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(PAEval, "pa-eval",
- "Evaluate ProvenanceAnalysis on all pairs", false, true)
diff --git a/llvm/lib/Transforms/ObjCARC/PtrState.cpp b/llvm/lib/Transforms/ObjCARC/PtrState.cpp
index d10d5851d5ea..e9b2dbeb62e6 100644
--- a/llvm/lib/Transforms/ObjCARC/PtrState.cpp
+++ b/llvm/lib/Transforms/ObjCARC/PtrState.cpp
@@ -212,7 +212,7 @@ bool BottomUpPtrState::MatchWithRetain() {
// imprecise release, clear our reverse insertion points.
if (OldSeq != S_Use || IsTrackingImpreciseReleases())
ClearReverseInsertPts();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case S_CanRelease:
return true;
case S_None:
@@ -360,7 +360,7 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
case S_CanRelease:
if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
ClearReverseInsertPts();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case S_Use:
SetReleaseMetadata(ReleaseMetadata);
SetTailCallRelease(cast<CallInst>(Release)->isTailCall());