Skip to content

Commit 1ebbc22

Browse files
committed
Eliminate dead alloc_pack
add trivial tuple example
1 parent 2b8a397 commit 1ebbc22

File tree

3 files changed

+102
-6
lines changed

3 files changed

+102
-6
lines changed

lib/SILOptimizer/Transforms/DeadObjectElimination.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ STATISTIC(DeadKeyPathEliminated,
6060
STATISTIC(DeadAllocApplyEliminated,
6161
"number of allocating Apply instructions removed");
6262

63+
STATISTIC(DeadAllocPackEliminated,
64+
"number of AllocPack instructions removed");
65+
6366
using UserList = llvm::SmallSetVector<SILInstruction *, 16>;
6467

6568
namespace {
@@ -283,6 +286,14 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
283286
if (isa<BeginAccessInst>(Inst) || isa<EndAccessInst>(Inst))
284287
return true;
285288

289+
// Setting a value within a pack does not prevent eliminating an alloc_pack.
290+
if (auto set = dyn_cast<PackElementSetInst>(Inst)) {
291+
// TODO: when we have OSSA, we can also accept stores of non trivial values:
292+
// just replace the store with a destroy_value.
293+
return !onlyAcceptTrivialStores ||
294+
set->getElementType().isTrivial(*set->getFunction());
295+
}
296+
286297
// If Inst does not read or write to memory, have side effects, and is not a
287298
// terminator, we can zap it.
288299
if (!Inst->mayHaveSideEffects() && !Inst->mayReadFromMemory() &&
@@ -738,6 +749,7 @@ class DeadObjectElimination : public SILFunctionTransform {
738749
bool processKeyPath(KeyPathInst *KPI);
739750
bool processAllocBox(AllocBoxInst *ABI){ return false;}
740751
bool processAllocApply(ApplyInst *AI, DeadEndBlocks &DEBlocks);
752+
bool processAllocPack(AllocPackInst *API);
741753

742754
bool insertCompensatingReleases(SILInstruction *before,
743755
const UserList &users);
@@ -766,6 +778,8 @@ class DeadObjectElimination : public SILFunctionTransform {
766778
Changed |= processAllocBox(A);
767779
else if (auto *A = dyn_cast<ApplyInst>(&inst))
768780
Changed |= processAllocApply(A, DEBlocks);
781+
else if (auto *A = dyn_cast<AllocPackInst>(&inst))
782+
Changed |= processAllocPack(A);
769783
}
770784
deleter.cleanupDeadInstructions();
771785
}
@@ -899,6 +913,36 @@ bool DeadObjectElimination::processKeyPath(KeyPathInst *KPI) {
899913
return true;
900914
}
901915

916+
bool DeadObjectElimination::processAllocPack(AllocPackInst *API) {
917+
bool isTrivialType = true;
918+
919+
// If all the elements within this pack are trivial, then this pack is trivial.
920+
// Otherwise, a single non-trivial element makes this entire pack non-trivial.
921+
for (auto i : indices(API->getPackType()->getElementTypes())) {
922+
auto eltTy = API->getPackType()->getSILElementType(i);
923+
924+
if (!eltTy.isTrivial(*API->getFunction())) {
925+
isTrivialType = false;
926+
break;
927+
}
928+
}
929+
930+
UserList UsersToRemove;
931+
if (hasUnremovableUsers(API, &UsersToRemove, /*acceptRefCountInsts=*/ true,
932+
/*onlyAcceptTrivialStores*/ !isTrivialType)) {
933+
LLVM_DEBUG(llvm::dbgs() << " Found a use that cannot be zapped...\n");
934+
return false;
935+
}
936+
937+
// Remove the AllocPack and all of its users.
938+
removeInstructions(
939+
ArrayRef<SILInstruction*>(UsersToRemove.begin(), UsersToRemove.end()));
940+
LLVM_DEBUG(llvm::dbgs() << " Success! Eliminating alloc_pack.\n");
941+
942+
++DeadAllocPackEliminated;
943+
return true;
944+
}
945+
902946
/// If AI is the version of an initializer where we pass in either an apply or
903947
/// an alloc_ref to initialize in place, validate that we are able to continue
904948
/// optimizing and return To
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %target-swift-frontend -parse-as-library -O -emit-sil -enable-builtin-module -module-name dap %s | %FileCheck %s
2+
3+
import Builtin
4+
5+
class TrivialDestructor {
6+
var int : Int
7+
var int2 : Int
8+
init() {
9+
self.int = 0
10+
self.int2 = 1
11+
}
12+
//deinit {}
13+
}
14+
15+
class Kl {}
16+
17+
class NontrivialDestructor {
18+
var p : Kl
19+
var i : Int
20+
init() {
21+
self.p = Kl()
22+
self.i = 123
23+
}
24+
}
25+
26+
public func makeTuple<each T>(_ t: repeat each T) -> (repeat each T) {
27+
(repeat each t)
28+
}
29+
30+
// CHECK-LABEL: sil @$s3dap14makeEmptyTupleyyF : $@convention(thin) () -> () {
31+
// CHECK: bb0:
32+
// CHECK-NEXT: [[RET:%.*]] = tuple ()
33+
// CHECK-NEXT: return [[RET]] : $()
34+
public func makeEmptyTuple() {
35+
makeTuple()
36+
}
37+
38+
// CHECK-LABEL: sil @$s3dap16makeTrivialTupleyyF : $@convention(thin) () -> () {
39+
// CHECK: bb0
40+
// CHECK-NEXT: [[RET:%.*]] = tuple ()
41+
// CHECK-NEXT: return [[RET]] : $()
42+
public func makeTrivialTuple() {
43+
makeTuple(123, 321, 456, 654)
44+
}
45+
46+
// CHECK-LABEL: sil @$s3dap26makeTrivialDestructorTupleyyF : $@convention(thin) () -> () {
47+
// CHECK: bb0:
48+
// CHECK-NEXT: %0 = alloc_pack $Pack{TrivialDestructor, TrivialDestructor}
49+
public func makeTrivialDestructorTuple() {
50+
makeTuple(TrivialDestructor(), TrivialDestructor())
51+
}
52+
53+
// CHECK-LABEL: sil @$s3dap19makeNonTrivialTupleyyF : $@convention(thin) () -> () {
54+
// CHECK: bb0:
55+
// CHECK-NEXT: %0 = alloc_pack $Pack{NontrivialDestructor, NontrivialDestructor}
56+
public func makeNonTrivialTuple() {
57+
makeTuple(NontrivialDestructor(), NontrivialDestructor())
58+
}

test/SILOptimizer/tuples_from_packs.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44
return (repeat each t)
55
}
66

7-
// FIXME: Useless alloc_pack/dealloc_pack
8-
97
// CHECK-LABEL: sil @$s17tuples_from_packs14makeEmptyTupleyyF : $@convention(thin) () -> () {
108
// CHECK: bb0:
11-
// CHECK-NEXT: %0 = alloc_pack $Pack{}
12-
// CHECK-NEXT: %1 = alloc_pack $Pack{}
13-
// CHECK-NEXT: dealloc_pack %1 : $*Pack{}
14-
// CHECK-NEXT: dealloc_pack %0 : $*Pack{}
159
// CHECK-NEXT: [[RET:%.*]] = tuple ()
1610
// CHECK-NEXT: return [[RET]] : $()
1711
public func makeEmptyTuple() {

0 commit comments

Comments
 (0)