@@ -761,6 +761,8 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
761
761
SILBasicBlock::iterator II = IEAI->getIterator ();
762
762
StoreInst *SI = nullptr ;
763
763
InitEnumDataAddrInst *DataAddrInst = nullptr ;
764
+ ApplyInst *AI = nullptr ;
765
+ Operand *EnumInitOperand = nullptr ;
764
766
for (;;) {
765
767
if (II == IEAI->getParent ()->begin ())
766
768
return nullptr ;
@@ -772,20 +774,76 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
772
774
DataAddrInst = dyn_cast<InitEnumDataAddrInst>(SI->getDest ().getDef ());
773
775
if (DataAddrInst && DataAddrInst->getOperand () == IEAI->getOperand ())
774
776
break ;
777
+ SI = nullptr ;
778
+ }
779
+ // Check whether we have an apply initializing the enum.
780
+ // %iedai = init_enum_data_addr %enum_addr
781
+ // = apply(%iedai,...)
782
+ // inject_enum_addr %enum_addr
783
+ //
784
+ // We can localize the store to an alloc_stack.
785
+ // Allowing us to perform the same optimization as for the store.
786
+ //
787
+ // %alloca = alloc_stack
788
+ // apply(%alloca#1,...)
789
+ // %load = load %alloca#1
790
+ // %1 = enum $EnumType, $EnumType.case, %load
791
+ // store %1 to %nopayload_addr
792
+ //
793
+ if ((AI = dyn_cast<ApplyInst>(&*II))) {
794
+ auto Params = AI->getSubstCalleeType ()->getParameters ();
795
+ unsigned ArgIdx = 0 ;
796
+ for (auto &Opd : AI->getArgumentOperands ()) {
797
+ // Found an apply that initializes the enum. We can optimize this by
798
+ // localizing the initialization to an alloc_stack and loading from it.
799
+ DataAddrInst = dyn_cast<InitEnumDataAddrInst>(Opd.get ().getDef ());
800
+ if (DataAddrInst && DataAddrInst->getOperand () == IEAI->getOperand () &&
801
+ Params[ArgIdx].getConvention () ==
802
+ ParameterConvention::Indirect_Out) {
803
+ EnumInitOperand = &Opd;
804
+ break ;
805
+ }
806
+ ++ArgIdx;
807
+ }
808
+ // We found an enum initialization.
809
+ if (EnumInitOperand)
810
+ break ;
811
+ AI = nullptr ;
775
812
}
776
813
}
777
814
// Found the store to this enum payload. Check if the store is the only use.
778
815
if (!DataAddrInst->hasOneUse ())
779
816
return nullptr ;
780
817
781
- // In that case, create the payload enum/store.
782
- EnumInst *E =
818
+ if (SI) {
819
+ // In that case, create the payload enum/store.
820
+ EnumInst *E =
783
821
Builder.createEnum (DataAddrInst->getLoc (), SI->getSrc (),
784
- DataAddrInst->getElement (),
785
- DataAddrInst->getOperand ().getType ().getObjectType ());
822
+ DataAddrInst->getElement (),
823
+ DataAddrInst->getOperand ().getType ().getObjectType ());
824
+ Builder.createStore (DataAddrInst->getLoc (), E, DataAddrInst->getOperand ());
825
+ // Cleanup.
826
+ eraseInstFromFunction (*SI);
827
+ eraseInstFromFunction (*DataAddrInst);
828
+ return eraseInstFromFunction (*IEAI);
829
+ }
830
+
831
+ assert (AI && " Must have an apply" );
832
+ // Localize the address access.
833
+ Builder.setInsertionPoint (AI);
834
+ auto *AllocStack = Builder.createAllocStack (DataAddrInst->getLoc (),
835
+ EnumInitOperand->get ().getType ());
836
+ EnumInitOperand->set (AllocStack->getAddressResult ());
837
+ Builder.setInsertionPoint (std::next (SILBasicBlock::iterator (AI)));
838
+ SILValue Load (Builder.createLoad (DataAddrInst->getLoc (),
839
+ AllocStack->getAddressResult ()),
840
+ 0 );
841
+ EnumInst *E = Builder.createEnum (
842
+ DataAddrInst->getLoc (), Load, DataAddrInst->getElement (),
843
+ DataAddrInst->getOperand ().getType ().getObjectType ());
786
844
Builder.createStore (DataAddrInst->getLoc (), E, DataAddrInst->getOperand ());
787
- // Cleanup.
788
- eraseInstFromFunction (*SI );
845
+ Builder. createDeallocStack (DataAddrInst-> getLoc (),
846
+ AllocStack-> getContainerResult () );
789
847
eraseInstFromFunction (*DataAddrInst);
790
848
return eraseInstFromFunction (*IEAI);
791
849
}
0 commit comments