1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[ObjCARC][NewPM] Port objc-arc-contract to NPM

Similar to https://reviews.llvm.org/D86178.

This is a module pass instead of a function pass since
ARCRuntimeEntryPoints can lazily add function declarations.

Reviewed By: ahatanak

Differential Revision: https://reviews.llvm.org/D87806
This commit is contained in:
Arthur Eubanks 2020-09-02 16:22:24 -07:00
parent 85f907b9af
commit 1a477f367f
6 changed files with 117 additions and 74 deletions

View File

@ -317,7 +317,7 @@ void initializeNaryReassociateLegacyPassPass(PassRegistry&);
void initializeNewGVNLegacyPassPass(PassRegistry&);
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
void initializeObjCARCAPElimPass(PassRegistry&);
void initializeObjCARCContractPass(PassRegistry&);
void initializeObjCARCContractLegacyPassPass(PassRegistry &);
void initializeObjCARCExpandPass(PassRegistry&);
void initializeObjCARCOptLegacyPassPass(PassRegistry &);
void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&);

View File

@ -44,10 +44,11 @@ Pass *createObjCARCContractPass();
//
Pass *createObjCARCOptPass();
class ObjCARCOptPass : public PassInfoMixin<ObjCARCOptPass> {
public:
ObjCARCOptPass() {}
struct ObjCARCOptPass : public PassInfoMixin<ObjCARCOptPass> {
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
struct ObjCARCContractPass : public PassInfoMixin<ObjCARCContractPass> {
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};

View File

@ -70,6 +70,7 @@ MODULE_PASS("mergefunc", MergeFunctionsPass())
MODULE_PASS("name-anon-globals", NameAnonGlobalPass())
MODULE_PASS("no-op-module", NoOpModulePass())
MODULE_PASS("objc-arc", ObjCARCOptPass())
MODULE_PASS("objc-arc-contract", ObjCARCContractPass())
MODULE_PASS("partial-inliner", PartialInlinerPass())
MODULE_PASS("pgo-icall-prom", PGOIndirectCallPromotion())
MODULE_PASS("pgo-instr-gen", PGOInstrumentationGen())

View File

@ -29,7 +29,7 @@ void llvm::initializeObjCARCOpts(PassRegistry &Registry) {
initializeObjCARCAAWrapperPassPass(Registry);
initializeObjCARCAPElimPass(Registry);
initializeObjCARCExpandPass(Registry);
initializeObjCARCContractPass(Registry);
initializeObjCARCContractLegacyPassPass(Registry);
initializeObjCARCOptLegacyPassPass(Registry);
initializePAEvalPass(Registry);
}

View File

@ -35,10 +35,12 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/ObjCARC.h"
using namespace llvm;
using namespace llvm::objcarc;
@ -53,59 +55,66 @@ STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed");
//===----------------------------------------------------------------------===//
namespace {
/// Late ARC optimizations
///
/// These change the IR in a way that makes it difficult to be analyzed by
/// ObjCARCOpt, so it's run late.
class ObjCARCContract : public FunctionPass {
bool Changed;
AliasAnalysis *AA;
DominatorTree *DT;
ProvenanceAnalysis PA;
ARCRuntimeEntryPoints EP;
/// Late ARC optimizations
///
/// These change the IR in a way that makes it difficult to be analyzed by
/// ObjCARCOpt, so it's run late.
/// A flag indicating whether this optimization pass should run.
bool Run;
class ObjCARCContract {
bool Changed;
AliasAnalysis *AA;
DominatorTree *DT;
ProvenanceAnalysis PA;
ARCRuntimeEntryPoints EP;
/// The inline asm string to insert between calls and RetainRV calls to make
/// the optimization work on targets which need it.
const MDString *RVInstMarker;
/// A flag indicating whether this optimization pass should run.
bool Run;
/// The set of inserted objc_storeStrong calls. If at the end of walking the
/// function we have found no alloca instructions, these calls can be marked
/// "tail".
SmallPtrSet<CallInst *, 8> StoreStrongCalls;
/// The inline asm string to insert between calls and RetainRV calls to make
/// the optimization work on targets which need it.
const MDString *RVInstMarker;
/// Returns true if we eliminated Inst.
bool tryToPeepholeInstruction(
Function &F, Instruction *Inst, inst_iterator &Iter,
SmallPtrSetImpl<Instruction *> &DepInsts,
SmallPtrSetImpl<const BasicBlock *> &Visited,
bool &TailOkForStoreStrong,
const DenseMap<BasicBlock *, ColorVector> &BlockColors);
/// The set of inserted objc_storeStrong calls. If at the end of walking the
/// function we have found no alloca instructions, these calls can be marked
/// "tail".
SmallPtrSet<CallInst *, 8> StoreStrongCalls;
bool optimizeRetainCall(Function &F, Instruction *Retain);
/// Returns true if we eliminated Inst.
bool tryToPeepholeInstruction(
Function &F, Instruction *Inst, inst_iterator &Iter,
SmallPtrSetImpl<Instruction *> &DepInsts,
SmallPtrSetImpl<const BasicBlock *> &Visited, bool &TailOkForStoreStrong,
const DenseMap<BasicBlock *, ColorVector> &BlockColors);
bool
contractAutorelease(Function &F, Instruction *Autorelease,
ARCInstKind Class,
SmallPtrSetImpl<Instruction *> &DependingInstructions,
SmallPtrSetImpl<const BasicBlock *> &Visited);
bool optimizeRetainCall(Function &F, Instruction *Retain);
void tryToContractReleaseIntoStoreStrong(
Instruction *Release, inst_iterator &Iter,
const DenseMap<BasicBlock *, ColorVector> &BlockColors);
bool
contractAutorelease(Function &F, Instruction *Autorelease, ARCInstKind Class,
SmallPtrSetImpl<Instruction *> &DependingInstructions,
SmallPtrSetImpl<const BasicBlock *> &Visited);
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool doInitialization(Module &M) override;
bool runOnFunction(Function &F) override;
void tryToContractReleaseIntoStoreStrong(
Instruction *Release, inst_iterator &Iter,
const DenseMap<BasicBlock *, ColorVector> &BlockColors);
public:
static char ID;
ObjCARCContract() : FunctionPass(ID) {
initializeObjCARCContractPass(*PassRegistry::getPassRegistry());
}
};
public:
bool init(Module &M);
bool run(Function &F, AAResults *AA, DominatorTree *DT);
};
class ObjCARCContractLegacyPass : public FunctionPass {
ObjCARCContract OCARCC;
public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool doInitialization(Module &M) override;
bool runOnFunction(Function &F) override;
static char ID;
ObjCARCContractLegacyPass() : FunctionPass(ID) {
initializeObjCARCContractLegacyPassPass(*PassRegistry::getPassRegistry());
}
};
}
//===----------------------------------------------------------------------===//
@ -542,7 +551,22 @@ bool ObjCARCContract::tryToPeepholeInstruction(
// Top Level Driver
//===----------------------------------------------------------------------===//
bool ObjCARCContract::runOnFunction(Function &F) {
bool ObjCARCContract::init(Module &M) {
// If nothing in the Module uses ARC, don't do anything.
Run = ModuleHasARC(M);
if (!Run)
return false;
EP.init(&M);
// Initialize RVInstMarker.
const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
RVInstMarker = dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey));
return false;
}
bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
if (!EnableARCOpts)
return false;
@ -550,11 +574,9 @@ bool ObjCARCContract::runOnFunction(Function &F) {
if (!Run)
return false;
Changed = false;
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
AA = A;
DT = D;
PA.setAA(A);
DenseMap<BasicBlock *, ColorVector> BlockColors;
if (F.hasPersonalityFn() &&
@ -720,33 +742,51 @@ bool ObjCARCContract::runOnFunction(Function &F) {
// Misc Pass Manager
//===----------------------------------------------------------------------===//
char ObjCARCContract::ID = 0;
INITIALIZE_PASS_BEGIN(ObjCARCContract, "objc-arc-contract",
char ObjCARCContractLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(ObjCARCContractLegacyPass, "objc-arc-contract",
"ObjC ARC contraction", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(ObjCARCContract, "objc-arc-contract",
INITIALIZE_PASS_END(ObjCARCContractLegacyPass, "objc-arc-contract",
"ObjC ARC contraction", false, false)
void ObjCARCContract::getAnalysisUsage(AnalysisUsage &AU) const {
void ObjCARCContractLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.setPreservesCFG();
}
Pass *llvm::createObjCARCContractPass() { return new ObjCARCContract(); }
bool ObjCARCContract::doInitialization(Module &M) {
// If nothing in the Module uses ARC, don't do anything.
Run = ModuleHasARC(M);
if (!Run)
return false;
EP.init(&M);
// Initialize RVInstMarker.
const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
RVInstMarker = dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey));
return false;
Pass *llvm::createObjCARCContractPass() {
return new ObjCARCContractLegacyPass();
}
bool ObjCARCContractLegacyPass::doInitialization(Module &M) {
return OCARCC.init(M);
}
bool ObjCARCContractLegacyPass::runOnFunction(Function &F) {
auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
return OCARCC.run(F, AA, DT);
}
PreservedAnalyses ObjCARCContractPass::run(Module &M,
ModuleAnalysisManager &AM) {
ObjCARCContract OCAC;
OCAC.init(M);
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
bool Changed = false;
for (Function &F : M) {
if (F.isDeclaration())
continue;
Changed |= OCAC.run(F, &FAM.getResult<AAManager>(F),
&FAM.getResult<DominatorTreeAnalysis>(F));
}
if (Changed) {
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}
return PreservedAnalyses::all();
}

View File

@ -1,4 +1,5 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64"