@@ -60,6 +60,9 @@ STATISTIC(DeadKeyPathEliminated,
60
60
STATISTIC (DeadAllocApplyEliminated,
61
61
" number of allocating Apply instructions removed" );
62
62
63
+ STATISTIC (DeadAllocPackEliminated,
64
+ " number of AllocPack instructions removed" );
65
+
63
66
using UserList = llvm::SmallSetVector<SILInstruction *, 16 >;
64
67
65
68
namespace {
@@ -283,6 +286,14 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
283
286
if (isa<BeginAccessInst>(Inst) || isa<EndAccessInst>(Inst))
284
287
return true ;
285
288
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
+
286
297
// If Inst does not read or write to memory, have side effects, and is not a
287
298
// terminator, we can zap it.
288
299
if (!Inst->mayHaveSideEffects () && !Inst->mayReadFromMemory () &&
@@ -738,6 +749,7 @@ class DeadObjectElimination : public SILFunctionTransform {
738
749
bool processKeyPath (KeyPathInst *KPI);
739
750
bool processAllocBox (AllocBoxInst *ABI){ return false ;}
740
751
bool processAllocApply (ApplyInst *AI, DeadEndBlocks &DEBlocks);
752
+ bool processAllocPack (AllocPackInst *API);
741
753
742
754
bool insertCompensatingReleases (SILInstruction *before,
743
755
const UserList &users);
@@ -766,6 +778,8 @@ class DeadObjectElimination : public SILFunctionTransform {
766
778
Changed |= processAllocBox (A);
767
779
else if (auto *A = dyn_cast<ApplyInst>(&inst))
768
780
Changed |= processAllocApply (A, DEBlocks);
781
+ else if (auto *A = dyn_cast<AllocPackInst>(&inst))
782
+ Changed |= processAllocPack (A);
769
783
}
770
784
deleter.cleanupDeadInstructions ();
771
785
}
@@ -899,6 +913,36 @@ bool DeadObjectElimination::processKeyPath(KeyPathInst *KPI) {
899
913
return true ;
900
914
}
901
915
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
+
902
946
// / If AI is the version of an initializer where we pass in either an apply or
903
947
// / an alloc_ref to initialize in place, validate that we are able to continue
904
948
// / optimizing and return To
0 commit comments