mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 01:24:30 +00:00
Miscellaneous accumulated cleanups.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156445 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -29,18 +29,8 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define DEBUG_TYPE "objc-arc"
|
#define DEBUG_TYPE "objc-arc"
|
||||||
#include "llvm/Function.h"
|
|
||||||
#include "llvm/Intrinsics.h"
|
|
||||||
#include "llvm/GlobalVariable.h"
|
|
||||||
#include "llvm/DerivedTypes.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
|
||||||
#include "llvm/Transforms/Utils/Local.h"
|
|
||||||
#include "llvm/Support/CallSite.h"
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// A handy option to enable/disable all optimizations in this file.
|
// A handy option to enable/disable all optimizations in this file.
|
||||||
@ -141,6 +131,13 @@ namespace {
|
|||||||
// ARC Utilities.
|
// ARC Utilities.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Intrinsics.h"
|
||||||
|
#include "llvm/Module.h"
|
||||||
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
|
#include "llvm/Support/CallSite.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// InstructionClass - A simple classification for instructions.
|
/// InstructionClass - A simple classification for instructions.
|
||||||
enum InstructionClass {
|
enum InstructionClass {
|
||||||
@ -299,22 +296,23 @@ static InstructionClass GetInstructionClass(const Value *V) {
|
|||||||
// None of the intrinsic functions do objc_release. For intrinsics, the
|
// None of the intrinsic functions do objc_release. For intrinsics, the
|
||||||
// only question is whether or not they may be users.
|
// only question is whether or not they may be users.
|
||||||
switch (F->getIntrinsicID()) {
|
switch (F->getIntrinsicID()) {
|
||||||
case 0: break;
|
|
||||||
case Intrinsic::bswap: case Intrinsic::ctpop:
|
|
||||||
case Intrinsic::ctlz: case Intrinsic::cttz:
|
|
||||||
case Intrinsic::returnaddress: case Intrinsic::frameaddress:
|
case Intrinsic::returnaddress: case Intrinsic::frameaddress:
|
||||||
case Intrinsic::stacksave: case Intrinsic::stackrestore:
|
case Intrinsic::stacksave: case Intrinsic::stackrestore:
|
||||||
case Intrinsic::vastart: case Intrinsic::vacopy: case Intrinsic::vaend:
|
case Intrinsic::vastart: case Intrinsic::vacopy: case Intrinsic::vaend:
|
||||||
|
case Intrinsic::objectsize: case Intrinsic::prefetch:
|
||||||
|
case Intrinsic::stackprotector:
|
||||||
|
case Intrinsic::eh_return_i32: case Intrinsic::eh_return_i64:
|
||||||
|
case Intrinsic::eh_typeid_for: case Intrinsic::eh_dwarf_cfa:
|
||||||
|
case Intrinsic::eh_sjlj_lsda: case Intrinsic::eh_sjlj_functioncontext:
|
||||||
|
case Intrinsic::init_trampoline: case Intrinsic::adjust_trampoline:
|
||||||
|
case Intrinsic::lifetime_start: case Intrinsic::lifetime_end:
|
||||||
|
case Intrinsic::invariant_start: case Intrinsic::invariant_end:
|
||||||
// Don't let dbg info affect our results.
|
// Don't let dbg info affect our results.
|
||||||
case Intrinsic::dbg_declare: case Intrinsic::dbg_value:
|
case Intrinsic::dbg_declare: case Intrinsic::dbg_value:
|
||||||
// Short cut: Some intrinsics obviously don't use ObjC pointers.
|
// Short cut: Some intrinsics obviously don't use ObjC pointers.
|
||||||
return IC_None;
|
return IC_None;
|
||||||
default:
|
default:
|
||||||
for (Function::const_arg_iterator AI = F->arg_begin(),
|
break;
|
||||||
AE = F->arg_end(); AI != AE; ++AI)
|
|
||||||
if (IsPotentialUse(AI))
|
|
||||||
return IC_User;
|
|
||||||
return IC_None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GetCallSiteClass(CI);
|
return GetCallSiteClass(CI);
|
||||||
@ -565,9 +563,8 @@ static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
|
|||||||
return Arg;
|
return Arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found an identifiable object but it has multiple uses, but they
|
// If we found an identifiable object but it has multiple uses, but they are
|
||||||
// are trivial uses, we can still consider this to be a single-use
|
// trivial uses, we can still consider this to be a single-use value.
|
||||||
// value.
|
|
||||||
if (IsObjCIdentifiedObject(Arg)) {
|
if (IsObjCIdentifiedObject(Arg)) {
|
||||||
for (Value::const_use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
|
for (Value::const_use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
|
||||||
UI != UE; ++UI) {
|
UI != UE; ++UI) {
|
||||||
@ -915,6 +912,7 @@ bool ObjCARCExpand::runOnFunction(Function &F) {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// ObjCARCAPElim - Autorelease pool elimination.
|
/// ObjCARCAPElim - Autorelease pool elimination.
|
||||||
@ -1094,13 +1092,10 @@ bool ObjCARCAPElim::runOnModule(Module &M) {
|
|||||||
|
|
||||||
// TODO: Delete release+retain pairs (rare).
|
// TODO: Delete release+retain pairs (rare).
|
||||||
|
|
||||||
#include "llvm/GlobalAlias.h"
|
|
||||||
#include "llvm/LLVMContext.h"
|
#include "llvm/LLVMContext.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
|
||||||
|
|
||||||
STATISTIC(NumNoops, "Number of no-op objc calls eliminated");
|
STATISTIC(NumNoops, "Number of no-op objc calls eliminated");
|
||||||
STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");
|
STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");
|
||||||
@ -1386,6 +1381,9 @@ namespace {
|
|||||||
/// PtrState - This class summarizes several per-pointer runtime properties
|
/// PtrState - This class summarizes several per-pointer runtime properties
|
||||||
/// which are propogated through the flow graph.
|
/// which are propogated through the flow graph.
|
||||||
class PtrState {
|
class PtrState {
|
||||||
|
/// NestCount - The known minimum level of retain+release nesting.
|
||||||
|
unsigned NestCount;
|
||||||
|
|
||||||
/// KnownPositiveRefCount - True if the reference count is known to
|
/// KnownPositiveRefCount - True if the reference count is known to
|
||||||
/// be incremented.
|
/// be incremented.
|
||||||
bool KnownPositiveRefCount;
|
bool KnownPositiveRefCount;
|
||||||
@ -1395,19 +1393,16 @@ namespace {
|
|||||||
/// CFG diamond.
|
/// CFG diamond.
|
||||||
bool Partial;
|
bool Partial;
|
||||||
|
|
||||||
/// NestCount - The known minimum level of retain+release nesting.
|
|
||||||
unsigned NestCount;
|
|
||||||
|
|
||||||
/// Seq - The current position in the sequence.
|
/// Seq - The current position in the sequence.
|
||||||
Sequence Seq;
|
Sequence Seq : 8;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// RRI - Unidirectional information about the current sequence.
|
/// RRI - Unidirectional information about the current sequence.
|
||||||
/// TODO: Encapsulate this better.
|
/// TODO: Encapsulate this better.
|
||||||
RRInfo RRI;
|
RRInfo RRI;
|
||||||
|
|
||||||
PtrState() : KnownPositiveRefCount(false), Partial(false),
|
PtrState() : NestCount(0), KnownPositiveRefCount(false), Partial(false),
|
||||||
NestCount(0), Seq(S_None) {}
|
Seq(S_None) {}
|
||||||
|
|
||||||
void SetKnownPositiveRefCount() {
|
void SetKnownPositiveRefCount() {
|
||||||
KnownPositiveRefCount = true;
|
KnownPositiveRefCount = true;
|
||||||
@ -1481,13 +1476,13 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
|
|||||||
RRI.ReleaseMetadata = 0;
|
RRI.ReleaseMetadata = 0;
|
||||||
|
|
||||||
RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe;
|
RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe;
|
||||||
RRI.IsTailCallRelease = RRI.IsTailCallRelease && Other.RRI.IsTailCallRelease;
|
RRI.IsTailCallRelease = RRI.IsTailCallRelease &&
|
||||||
|
Other.RRI.IsTailCallRelease;
|
||||||
RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end());
|
RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end());
|
||||||
|
|
||||||
// Merge the insert point sets. If there are any differences,
|
// Merge the insert point sets. If there are any differences,
|
||||||
// that makes this a partial merge.
|
// that makes this a partial merge.
|
||||||
Partial = RRI.ReverseInsertPts.size() !=
|
Partial = RRI.ReverseInsertPts.size() != Other.RRI.ReverseInsertPts.size();
|
||||||
Other.RRI.ReverseInsertPts.size();
|
|
||||||
for (SmallPtrSet<Instruction *, 2>::const_iterator
|
for (SmallPtrSet<Instruction *, 2>::const_iterator
|
||||||
I = Other.RRI.ReverseInsertPts.begin(),
|
I = Other.RRI.ReverseInsertPts.begin(),
|
||||||
E = Other.RRI.ReverseInsertPts.end(); I != E; ++I)
|
E = Other.RRI.ReverseInsertPts.end(); I != E; ++I)
|
||||||
@ -1792,12 +1787,9 @@ Constant *ObjCARCOpt::getRetainRVCallee(Module *M) {
|
|||||||
if (!RetainRVCallee) {
|
if (!RetainRVCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { I8X };
|
||||||
Params.push_back(I8X);
|
FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
||||||
FunctionType *FTy =
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
RetainRVCallee =
|
RetainRVCallee =
|
||||||
M->getOrInsertFunction("objc_retainAutoreleasedReturnValue", FTy,
|
M->getOrInsertFunction("objc_retainAutoreleasedReturnValue", FTy,
|
||||||
Attributes);
|
Attributes);
|
||||||
@ -1809,12 +1801,9 @@ Constant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) {
|
|||||||
if (!AutoreleaseRVCallee) {
|
if (!AutoreleaseRVCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { I8X };
|
||||||
Params.push_back(I8X);
|
FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
||||||
FunctionType *FTy =
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
AutoreleaseRVCallee =
|
AutoreleaseRVCallee =
|
||||||
M->getOrInsertFunction("objc_autoreleaseReturnValue", FTy,
|
M->getOrInsertFunction("objc_autoreleaseReturnValue", FTy,
|
||||||
Attributes);
|
Attributes);
|
||||||
@ -1825,10 +1814,8 @@ Constant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) {
|
|||||||
Constant *ObjCARCOpt::getReleaseCallee(Module *M) {
|
Constant *ObjCARCOpt::getReleaseCallee(Module *M) {
|
||||||
if (!ReleaseCallee) {
|
if (!ReleaseCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
|
||||||
Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
ReleaseCallee =
|
ReleaseCallee =
|
||||||
M->getOrInsertFunction(
|
M->getOrInsertFunction(
|
||||||
"objc_release",
|
"objc_release",
|
||||||
@ -1841,10 +1828,8 @@ Constant *ObjCARCOpt::getReleaseCallee(Module *M) {
|
|||||||
Constant *ObjCARCOpt::getRetainCallee(Module *M) {
|
Constant *ObjCARCOpt::getRetainCallee(Module *M) {
|
||||||
if (!RetainCallee) {
|
if (!RetainCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
|
||||||
Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
RetainCallee =
|
RetainCallee =
|
||||||
M->getOrInsertFunction(
|
M->getOrInsertFunction(
|
||||||
"objc_retain",
|
"objc_retain",
|
||||||
@ -1857,16 +1842,14 @@ Constant *ObjCARCOpt::getRetainCallee(Module *M) {
|
|||||||
Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
|
Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
|
||||||
if (!RetainBlockCallee) {
|
if (!RetainBlockCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
|
||||||
Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
|
|
||||||
AttrListPtr Attributes;
|
|
||||||
// objc_retainBlock is not nounwind because it calls user copy constructors
|
// objc_retainBlock is not nounwind because it calls user copy constructors
|
||||||
// which could theoretically throw.
|
// which could theoretically throw.
|
||||||
RetainBlockCallee =
|
RetainBlockCallee =
|
||||||
M->getOrInsertFunction(
|
M->getOrInsertFunction(
|
||||||
"objc_retainBlock",
|
"objc_retainBlock",
|
||||||
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
|
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
|
||||||
Attributes);
|
AttrListPtr());
|
||||||
}
|
}
|
||||||
return RetainBlockCallee;
|
return RetainBlockCallee;
|
||||||
}
|
}
|
||||||
@ -1874,10 +1857,8 @@ Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
|
|||||||
Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
|
Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
|
||||||
if (!AutoreleaseCallee) {
|
if (!AutoreleaseCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
|
||||||
Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
AutoreleaseCallee =
|
AutoreleaseCallee =
|
||||||
M->getOrInsertFunction(
|
M->getOrInsertFunction(
|
||||||
"objc_autorelease",
|
"objc_autorelease",
|
||||||
@ -2426,7 +2407,8 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
|
|||||||
// These can always be moved up.
|
// These can always be moved up.
|
||||||
break;
|
break;
|
||||||
case IC_Release:
|
case IC_Release:
|
||||||
// These can't be moved across things that care about the retain count.
|
// These can't be moved across things that care about the retain
|
||||||
|
// count.
|
||||||
FindDependencies(NeedsPositiveRetainCount, Arg,
|
FindDependencies(NeedsPositiveRetainCount, Arg,
|
||||||
Inst->getParent(), Inst,
|
Inst->getParent(), Inst,
|
||||||
DependingInstructions, Visited, PA);
|
DependingInstructions, Visited, PA);
|
||||||
@ -2508,8 +2490,8 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
|
|||||||
for (; SI != SE; ++SI) {
|
for (; SI != SE; ++SI) {
|
||||||
Sequence SuccSSeq = S_None;
|
Sequence SuccSSeq = S_None;
|
||||||
bool SuccSRRIKnownSafe = false;
|
bool SuccSRRIKnownSafe = false;
|
||||||
// If VisitBottomUp has pointer information for this successor, take what we
|
// If VisitBottomUp has pointer information for this successor, take
|
||||||
// know about it.
|
// what we know about it.
|
||||||
DenseMap<const BasicBlock *, BBState>::iterator BBI =
|
DenseMap<const BasicBlock *, BBState>::iterator BBI =
|
||||||
BBStates.find(*SI);
|
BBStates.find(*SI);
|
||||||
assert(BBI != BBStates.end());
|
assert(BBI != BBStates.end());
|
||||||
@ -2562,8 +2544,8 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
|
|||||||
for (; SI != SE; ++SI) {
|
for (; SI != SE; ++SI) {
|
||||||
Sequence SuccSSeq = S_None;
|
Sequence SuccSSeq = S_None;
|
||||||
bool SuccSRRIKnownSafe = false;
|
bool SuccSRRIKnownSafe = false;
|
||||||
// If VisitBottomUp has pointer information for this successor, take what we
|
// If VisitBottomUp has pointer information for this successor, take
|
||||||
// know about it.
|
// what we know about it.
|
||||||
DenseMap<const BasicBlock *, BBState>::iterator BBI =
|
DenseMap<const BasicBlock *, BBState>::iterator BBI =
|
||||||
BBStates.find(*SI);
|
BBStates.find(*SI);
|
||||||
assert(BBI != BBStates.end());
|
assert(BBI != BBStates.end());
|
||||||
@ -2992,9 +2974,10 @@ ComputePostOrders(Function &F,
|
|||||||
// Functions always have exactly one entry block, and we don't have
|
// Functions always have exactly one entry block, and we don't have
|
||||||
// any other block that we treat like an entry block.
|
// any other block that we treat like an entry block.
|
||||||
BasicBlock *EntryBB = &F.getEntryBlock();
|
BasicBlock *EntryBB = &F.getEntryBlock();
|
||||||
BBStates[EntryBB].SetAsEntry();
|
BBState &MyStates = BBStates[EntryBB];
|
||||||
|
MyStates.SetAsEntry();
|
||||||
SuccStack.push_back(std::make_pair(EntryBB, succ_begin(EntryBB)));
|
TerminatorInst *EntryTI = cast<TerminatorInst>(&EntryBB->back());
|
||||||
|
SuccStack.push_back(std::make_pair(EntryBB, succ_iterator(EntryTI)));
|
||||||
Visited.insert(EntryBB);
|
Visited.insert(EntryBB);
|
||||||
OnStack.insert(EntryBB);
|
OnStack.insert(EntryBB);
|
||||||
do {
|
do {
|
||||||
@ -3002,7 +2985,7 @@ ComputePostOrders(Function &F,
|
|||||||
BasicBlock *CurrBB = SuccStack.back().first;
|
BasicBlock *CurrBB = SuccStack.back().first;
|
||||||
TerminatorInst *TI = cast<TerminatorInst>(&CurrBB->back());
|
TerminatorInst *TI = cast<TerminatorInst>(&CurrBB->back());
|
||||||
succ_iterator SE(TI, false);
|
succ_iterator SE(TI, false);
|
||||||
|
|
||||||
// If the terminator is an invoke marked with the
|
// If the terminator is an invoke marked with the
|
||||||
// clang.arc.no_objc_arc_exceptions metadata, the unwind edge can be
|
// clang.arc.no_objc_arc_exceptions metadata, the unwind edge can be
|
||||||
// ignored, for ARC purposes.
|
// ignored, for ARC purposes.
|
||||||
@ -3012,9 +2995,11 @@ ComputePostOrders(Function &F,
|
|||||||
while (SuccStack.back().second != SE) {
|
while (SuccStack.back().second != SE) {
|
||||||
BasicBlock *SuccBB = *SuccStack.back().second++;
|
BasicBlock *SuccBB = *SuccStack.back().second++;
|
||||||
if (Visited.insert(SuccBB)) {
|
if (Visited.insert(SuccBB)) {
|
||||||
SuccStack.push_back(std::make_pair(SuccBB, succ_begin(SuccBB)));
|
TerminatorInst *TI = cast<TerminatorInst>(&SuccBB->back());
|
||||||
|
SuccStack.push_back(std::make_pair(SuccBB, succ_iterator(TI)));
|
||||||
BBStates[CurrBB].addSucc(SuccBB);
|
BBStates[CurrBB].addSucc(SuccBB);
|
||||||
BBStates[SuccBB].addPred(CurrBB);
|
BBState &SuccStates = BBStates[SuccBB];
|
||||||
|
SuccStates.addPred(CurrBB);
|
||||||
OnStack.insert(SuccBB);
|
OnStack.insert(SuccBB);
|
||||||
goto dfs_next_succ;
|
goto dfs_next_succ;
|
||||||
}
|
}
|
||||||
@ -3185,7 +3170,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
|||||||
// not being managed by ObjC reference counting, so we can delete pairs
|
// not being managed by ObjC reference counting, so we can delete pairs
|
||||||
// regardless of what possible decrements or uses lie between them.
|
// regardless of what possible decrements or uses lie between them.
|
||||||
bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
|
bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
|
||||||
|
|
||||||
// A constant pointer can't be pointing to an object on the heap. It may
|
// A constant pointer can't be pointing to an object on the heap. It may
|
||||||
// be reference-counted, but it won't be deleted.
|
// be reference-counted, but it won't be deleted.
|
||||||
if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
|
if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
|
||||||
@ -3570,8 +3555,7 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
|
|||||||
dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
|
dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
|
||||||
if (!Autorelease)
|
if (!Autorelease)
|
||||||
goto next_block;
|
goto next_block;
|
||||||
InstructionClass AutoreleaseClass =
|
InstructionClass AutoreleaseClass = GetBasicInstructionClass(Autorelease);
|
||||||
GetBasicInstructionClass(Autorelease);
|
|
||||||
if (!IsAutorelease(AutoreleaseClass))
|
if (!IsAutorelease(AutoreleaseClass))
|
||||||
goto next_block;
|
goto next_block;
|
||||||
if (GetObjCArg(Autorelease) != Arg)
|
if (GetObjCArg(Autorelease) != Arg)
|
||||||
@ -3714,8 +3698,8 @@ bool ObjCARCOpt::runOnFunction(Function &F) {
|
|||||||
while (OptimizeSequences(F)) {}
|
while (OptimizeSequences(F)) {}
|
||||||
|
|
||||||
// Optimizations if objc_autorelease is used.
|
// Optimizations if objc_autorelease is used.
|
||||||
if (UsedInThisFunction &
|
if (UsedInThisFunction & ((1 << IC_Autorelease) |
|
||||||
((1 << IC_Autorelease) | (1 << IC_AutoreleaseRV)))
|
(1 << IC_AutoreleaseRV)))
|
||||||
OptimizeReturns(F);
|
OptimizeReturns(F);
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
@ -3763,7 +3747,7 @@ namespace {
|
|||||||
/// StoreStrongCalls - The set of inserted objc_storeStrong calls. If
|
/// StoreStrongCalls - The set of inserted objc_storeStrong calls. If
|
||||||
/// at the end of walking the function we have found no alloca
|
/// at the end of walking the function we have found no alloca
|
||||||
/// instructions, these calls can be marked "tail".
|
/// instructions, these calls can be marked "tail".
|
||||||
DenseSet<CallInst *> StoreStrongCalls;
|
SmallPtrSet<CallInst *, 8> StoreStrongCalls;
|
||||||
|
|
||||||
Constant *getStoreStrongCallee(Module *M);
|
Constant *getStoreStrongCallee(Module *M);
|
||||||
Constant *getRetainAutoreleaseCallee(Module *M);
|
Constant *getRetainAutoreleaseCallee(Module *M);
|
||||||
@ -3814,13 +3798,11 @@ Constant *ObjCARCContract::getStoreStrongCallee(Module *M) {
|
|||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
||||||
Type *I8XX = PointerType::getUnqual(I8X);
|
Type *I8XX = PointerType::getUnqual(I8X);
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { I8XX, I8X };
|
||||||
Params.push_back(I8XX);
|
|
||||||
Params.push_back(I8X);
|
|
||||||
|
|
||||||
AttrListPtr Attributes;
|
AttrListPtr Attributes = AttrListPtr()
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
.addAttr(~0u, Attribute::NoUnwind)
|
||||||
Attributes.addAttr(1, Attribute::NoCapture);
|
.addAttr(1, Attribute::NoCapture);
|
||||||
|
|
||||||
StoreStrongCallee =
|
StoreStrongCallee =
|
||||||
M->getOrInsertFunction(
|
M->getOrInsertFunction(
|
||||||
@ -3835,12 +3817,9 @@ Constant *ObjCARCContract::getRetainAutoreleaseCallee(Module *M) {
|
|||||||
if (!RetainAutoreleaseCallee) {
|
if (!RetainAutoreleaseCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { I8X };
|
||||||
Params.push_back(I8X);
|
FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
||||||
FunctionType *FTy =
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
RetainAutoreleaseCallee =
|
RetainAutoreleaseCallee =
|
||||||
M->getOrInsertFunction("objc_retainAutorelease", FTy, Attributes);
|
M->getOrInsertFunction("objc_retainAutorelease", FTy, Attributes);
|
||||||
}
|
}
|
||||||
@ -3851,12 +3830,9 @@ Constant *ObjCARCContract::getRetainAutoreleaseRVCallee(Module *M) {
|
|||||||
if (!RetainAutoreleaseRVCallee) {
|
if (!RetainAutoreleaseRVCallee) {
|
||||||
LLVMContext &C = M->getContext();
|
LLVMContext &C = M->getContext();
|
||||||
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
||||||
std::vector<Type *> Params;
|
Type *Params[] = { I8X };
|
||||||
Params.push_back(I8X);
|
FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
||||||
FunctionType *FTy =
|
AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
|
||||||
FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
|
||||||
AttrListPtr Attributes;
|
|
||||||
Attributes.addAttr(~0u, Attribute::NoUnwind);
|
|
||||||
RetainAutoreleaseRVCallee =
|
RetainAutoreleaseRVCallee =
|
||||||
M->getOrInsertFunction("objc_retainAutoreleaseReturnValue", FTy,
|
M->getOrInsertFunction("objc_retainAutoreleaseReturnValue", FTy,
|
||||||
Attributes);
|
Attributes);
|
||||||
@ -4044,7 +4020,8 @@ bool ObjCARCContract::runOnFunction(Function &F) {
|
|||||||
// It seems that functions which "return twice" are also unsafe for the
|
// It seems that functions which "return twice" are also unsafe for the
|
||||||
// "tail" argument, because they are setjmp, which could need to
|
// "tail" argument, because they are setjmp, which could need to
|
||||||
// return to an earlier stack state.
|
// return to an earlier stack state.
|
||||||
bool TailOkForStoreStrongs = !F.isVarArg() && !F.callsFunctionThatReturnsTwice();
|
bool TailOkForStoreStrongs = !F.isVarArg() &&
|
||||||
|
!F.callsFunctionThatReturnsTwice();
|
||||||
|
|
||||||
// For ObjC library calls which return their argument, replace uses of the
|
// For ObjC library calls which return their argument, replace uses of the
|
||||||
// argument with uses of the call return value, if it dominates the use. This
|
// argument with uses of the call return value, if it dominates the use. This
|
||||||
@ -4134,17 +4111,14 @@ bool ObjCARCContract::runOnFunction(Function &F) {
|
|||||||
// trivially dominate itself, which would lead us to rewriting its
|
// trivially dominate itself, which would lead us to rewriting its
|
||||||
// argument in terms of its return value, which would lead to
|
// argument in terms of its return value, which would lead to
|
||||||
// infinite loops in GetObjCArg.
|
// infinite loops in GetObjCArg.
|
||||||
if (DT->isReachableFromEntry(U) &&
|
if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) {
|
||||||
DT->dominates(Inst, U)) {
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
Instruction *Replacement = Inst;
|
Instruction *Replacement = Inst;
|
||||||
Type *UseTy = U.get()->getType();
|
Type *UseTy = U.get()->getType();
|
||||||
if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
|
if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
|
||||||
// For PHI nodes, insert the bitcast in the predecessor block.
|
// For PHI nodes, insert the bitcast in the predecessor block.
|
||||||
unsigned ValNo =
|
unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo);
|
||||||
PHINode::getIncomingValueNumForOperand(OperandNo);
|
BasicBlock *BB = PHI->getIncomingBlock(ValNo);
|
||||||
BasicBlock *BB =
|
|
||||||
PHI->getIncomingBlock(ValNo);
|
|
||||||
if (Replacement->getType() != UseTy)
|
if (Replacement->getType() != UseTy)
|
||||||
Replacement = new BitCastInst(Replacement, UseTy, "",
|
Replacement = new BitCastInst(Replacement, UseTy, "",
|
||||||
&BB->back());
|
&BB->back());
|
||||||
@ -4186,7 +4160,7 @@ bool ObjCARCContract::runOnFunction(Function &F) {
|
|||||||
// If this function has no escaping allocas or suspicious vararg usage,
|
// If this function has no escaping allocas or suspicious vararg usage,
|
||||||
// objc_storeStrong calls can be marked with the "tail" keyword.
|
// objc_storeStrong calls can be marked with the "tail" keyword.
|
||||||
if (TailOkForStoreStrongs)
|
if (TailOkForStoreStrongs)
|
||||||
for (DenseSet<CallInst *>::iterator I = StoreStrongCalls.begin(),
|
for (SmallPtrSet<CallInst *, 8>::iterator I = StoreStrongCalls.begin(),
|
||||||
E = StoreStrongCalls.end(); I != E; ++I)
|
E = StoreStrongCalls.end(); I != E; ++I)
|
||||||
(*I)->setTailCall();
|
(*I)->setTailCall();
|
||||||
StoreStrongCalls.clear();
|
StoreStrongCalls.clear();
|
||||||
|
Reference in New Issue
Block a user