mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
teach AllocBoxToStack to remove alloc_stack's that are artificial (or inlined)
and only stored to. With this change, we now -emit-sil this testcase:
func f() {
var a = 1
}
as:
sil @_T1t1fFT_T_ : $@thin () -> () {
bb0:
%0 = tuple ()
%1 = alloc_stack $Int64 // var a // users: %8, %7
%2 = metatype $Int64.metatype
%3 = metatype $Int64.metatype
%4 = module #Builtin
%5 = integer_literal $Builtin.Int64, 1 // user: %6
%6 = struct $Int64 (%5 : $Builtin.Int64) // user: %7
store %6 to %1#1 : $*Int64
dealloc_stack %1#0 : $*@local_storage Int64
%9 = tuple () // user: %10
return %9 : $()
}
Swift SVN r9305
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
using namespace swift;
|
||||
|
||||
STATISTIC(NumStackPromoted, "Number of alloc_box's promoted to the stack");
|
||||
STATISTIC(NumStackRemoved, "Number of variables removed completely");
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// alloc_box Promotion
|
||||
@@ -250,12 +251,100 @@ static bool optimizeAllocBox(AllocBoxInst *ABI,
|
||||
User->eraseFromParent();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
// AllocStack Removal
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// areAllocStackUsesSafeToRemove - Return true if there are no uses of the
|
||||
/// specified address (or any pointers derived from it) that prevent us from
|
||||
/// removing the allocation. For example, stores to the value can just be
|
||||
/// discarded, but loads from the value require the memory to exist.
|
||||
static bool areAllocStackUsesSafeToRemove(SILValue V) {
|
||||
for (auto UI : V.getUses()) {
|
||||
auto *User = cast<SILInstruction>(UI->getUser());
|
||||
|
||||
// Stores to the pointer (either in store or copy_addr form) can be
|
||||
// discarded.
|
||||
if ((isa<CopyAddrInst>(User) || isa<StoreInst>(User)) &&
|
||||
UI->getOperandNumber() == 1)
|
||||
continue;
|
||||
|
||||
// Zero initializations can be dropped.
|
||||
if (isa<InitializeVarInst>(User))
|
||||
continue;
|
||||
|
||||
// Recursively check uses of instructions that derive a pointer from the
|
||||
// original pointer.
|
||||
if (isa<StructElementAddrInst>(User) || isa<TupleElementAddrInst>(User) ||
|
||||
isa<ProjectExistentialInst>(User)) {
|
||||
if (!areAllocStackUsesSafeToRemove(SILValue(User, 0)))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, this is something we don't know about, conservatively keep the
|
||||
// instruction
|
||||
DEBUG(llvm::errs() << "*** Failed to remove autogenerated alloc_stack: "
|
||||
"kept alive by: " << *User);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void eraseUsesOfInstruction(SILInstruction *Inst) {
|
||||
for (auto UI : Inst->getUses()) {
|
||||
auto *User = cast<SILInstruction>(UI->getUser());
|
||||
eraseUsesOfInstruction(User);
|
||||
User->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
/// optimizeAllocStack - Remove alloc_stack's the are only stored to, if they
|
||||
/// are artificial allocations. We keep around normal allocations for debug
|
||||
/// info generation to use.
|
||||
static bool optimizeAllocStack(AllocStackInst *ASI) {
|
||||
// We only look at (and try to remove) autogenerated allocations.
|
||||
if (!ASI->getLoc().isAutoGenerated() &&
|
||||
// FIXME: This is a temporary hack. The transparent inliner should set
|
||||
// the autogenerated bit on inlined allocations.
|
||||
!ASI->getLoc().is<InlinedLocation>())
|
||||
return false;
|
||||
|
||||
// Walk the use list to see if we have only safe-to-remove uses hanging off
|
||||
// of the allocation. Check the local_storage piece first.
|
||||
for (auto UI : SILValue(ASI, 0).getUses()) {
|
||||
auto *User = cast<SILInstruction>(UI->getUser());
|
||||
|
||||
if (isa<DeallocStackInst>(User))
|
||||
continue;
|
||||
|
||||
// Otherwise, it was an instruction we can't handle.
|
||||
DEBUG(llvm::errs() << "*** Failed to remove autogenerated alloc_stack: "
|
||||
"kept alive by: " << *User);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Next, check uses of the address.
|
||||
if (!areAllocStackUsesSafeToRemove(SILValue(ASI, 1)))
|
||||
return false;
|
||||
|
||||
DEBUG(llvm::errs() << "*** Removing autogenerated alloc_stack: " << *ASI);
|
||||
|
||||
// If it is safe to remove, do it. Recursively remove all instructions
|
||||
// hanging off the alloc_stack, then return success.
|
||||
eraseUsesOfInstruction(ASI);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void swift::performSILAllocBoxToStackPromotion(SILModule *M) {
|
||||
@@ -268,21 +357,25 @@ void swift::performSILAllocBoxToStackPromotion(SILModule *M) {
|
||||
for (auto &BB : Fn) {
|
||||
auto I = BB.begin(), E = BB.end();
|
||||
while (I != E) {
|
||||
auto *ABI = dyn_cast<AllocBoxInst>(I);
|
||||
if (auto *ABI = dyn_cast<AllocBoxInst>(I))
|
||||
if (optimizeAllocBox(ABI, PostDomInfo)) {
|
||||
++NumStackPromoted;
|
||||
// Carefully move iterator to avoid invalidation problems.
|
||||
++I;
|
||||
ABI->eraseFromParent();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ABI) {
|
||||
++I;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (optimizeAllocBox(ABI, PostDomInfo)) {
|
||||
++NumStackPromoted;
|
||||
// Carefully move iterator to avoid invalidation problems.
|
||||
++I;
|
||||
ABI->eraseFromParent();
|
||||
} else {
|
||||
++I;
|
||||
}
|
||||
if (auto *ASI = dyn_cast<AllocStackInst>(I))
|
||||
if (optimizeAllocStack(ASI)) {
|
||||
++NumStackRemoved;
|
||||
// Carefully move iterator to avoid invalidation problems.
|
||||
++I;
|
||||
ASI->eraseFromParent();
|
||||
continue;
|
||||
}
|
||||
|
||||
++I;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user