@@ -865,14 +865,20 @@ SILInstruction *SILCombiner::visitCondFailInst(CondFailInst *CFI) {
865865 return nullptr ;
866866}
867867
868- // / Create a value from stores to an address.
868+ // / Whether there exists a unique value to which \p addr is always initialized
869+ // / at \p forInst.
869870// /
870- // / If there are only stores to \p addr, return the stored value. Also, if there
871- // / are address projections, create aggregate instructions for it.
872- // / If builder is null, it's just a dry-run to check if it's possible.
873- static SILValue createValueFromAddr (SILValue addr, SILBuilder *builder,
874- SILLocation loc) {
875- SmallVector<SILValue, 4 > elems;
871+ // / If \p builder is passed, create the value using it. If \p addr is
872+ // / initialized piecewise via initializations of tuple element memory, the full
873+ // / tuple is constructed via the builder.
874+ // /
875+ // / A best effort.
876+ // / TODO: Construct structs.
877+ // / Handle stores of identical values on multiple paths.
878+ static std::optional<std::pair<SILValue, SILInstruction *>>
879+ createValueFromAddr (SILValue addr, SILInstruction *forInst, DominanceInfo *DI,
880+ SILBuilder *builder, SILLocation loc) {
881+ SmallVector<std::optional<std::pair<SILValue, SILInstruction *>>, 4 > pairs;
876882 enum Kind {
877883 none, store, tuple
878884 } kind = none;
@@ -884,7 +890,7 @@ static SILValue createValueFromAddr(SILValue addr, SILBuilder *builder,
884890
885891 auto *st = dyn_cast<StoreInst>(user);
886892 if (st && kind == none && st->getDest () == addr) {
887- elems .push_back (st->getSrc ());
893+ pairs .push_back ({{ st->getSrc (), st}} );
888894 kind = store;
889895 // We cannot just return st->getSrc() here because we also have to check
890896 // if the store destination is the only use of addr.
@@ -893,35 +899,55 @@ static SILValue createValueFromAddr(SILValue addr, SILBuilder *builder,
893899
894900 if (auto *telem = dyn_cast<TupleElementAddrInst>(user)) {
895901 if (kind == none) {
896- elems .resize (addr->getType ().castTo <TupleType>()->getNumElements ());
902+ pairs .resize (addr->getType ().castTo <TupleType>()->getNumElements ());
897903 kind = tuple;
898904 }
899905 if (kind == tuple) {
900- if (elems[telem->getFieldIndex ()])
901- return SILValue ();
902- elems[telem->getFieldIndex ()] = createValueFromAddr (telem, builder, loc);
906+ if (pairs[telem->getFieldIndex ()]) {
907+ // Already found a tuple_element_addr at this index. Assume that a
908+ // different value is stored to addr by it.
909+ return std::nullopt ;
910+ }
911+ pairs[telem->getFieldIndex ()] =
912+ createValueFromAddr (telem, forInst, DI, builder, loc);
903913 continue ;
904914 }
905915 }
906916 // TODO: handle StructElementAddrInst to create structs.
907917
908- return SILValue () ;
918+ return std:: nullopt ;
909919 }
910920 switch (kind) {
911921 case none:
912- return SILValue () ;
922+ return std:: nullopt ;
913923 case store:
914- assert (elems.size () == 1 );
915- return elems[0 ];
924+ assert (pairs.size () == 1 );
925+ {
926+ auto pair = pairs[0 ];
927+ assert (pair.has_value ());
928+ bool isEmpty = pair->first ->getType ().isEmpty (*addr->getFunction ());
929+ if (isEmpty && !DI->properlyDominates (pair->second , forInst))
930+ return std::nullopt ;
931+ return pair;
932+ }
916933 case tuple:
917- if (std::any_of (elems.begin (), elems.end (),
918- [](SILValue v){ return !(bool )v; }))
919- return SILValue ();
934+ if (std::any_of (pairs.begin (), pairs.end (), [&](auto pair) {
935+ return !pair.has_value () ||
936+ (pair->first ->getType ().isEmpty (*addr->getFunction ()) &&
937+ !DI->properlyDominates (pair->second , forInst));
938+ }))
939+ return std::nullopt ;
920940 if (builder) {
921- return builder->createTuple (loc, addr->getType ().getObjectType (), elems);
941+ SmallVector<SILValue, 4 > elements;
942+ for (auto pair : pairs) {
943+ elements.push_back (pair->first );
944+ }
945+ auto *tuple =
946+ builder->createTuple (loc, addr->getType ().getObjectType (), elements);
947+ return {{tuple, tuple}};
922948 }
923949 // Just return anything not null for the dry-run.
924- return elems [0 ];
950+ return pairs [0 ];
925951 }
926952 llvm_unreachable (" invalid kind" );
927953}
@@ -1185,9 +1211,12 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
11851211 // store %payload1 to %elem1_addr
11861212 // inject_enum_addr %enum_addr, $EnumType.case
11871213 //
1188- if (createValueFromAddr (DataAddrInst, nullptr , DataAddrInst->getLoc ())) {
1189- SILValue en =
1190- createValueFromAddr (DataAddrInst, &Builder, DataAddrInst->getLoc ());
1214+ auto DI = DA->get (IEAI->getFunction ());
1215+ if (createValueFromAddr (DataAddrInst, IEAI, DI, nullptr ,
1216+ DataAddrInst->getLoc ())) {
1217+ SILValue en = createValueFromAddr (DataAddrInst, IEAI, DI, &Builder,
1218+ DataAddrInst->getLoc ())
1219+ ->first ;
11911220 assert (en);
11921221
11931222 // In that case, create the payload enum/store.
@@ -1224,7 +1253,14 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
12241253 // store %1 to %nopayload_addr
12251254 //
12261255 auto *AI = dyn_cast_or_null<ApplyInst>(getSingleNonDebugUser (DataAddrInst));
1227- if (!AI)
1256+ bool hasEmptyAssociatedType =
1257+ IEAI->getElement ()->hasAssociatedValues ()
1258+ ? IEAI->getOperand ()
1259+ ->getType ()
1260+ .getEnumElementType (IEAI->getElement (), func)
1261+ .isEmpty (*func)
1262+ : false ;
1263+ if (!AI || (hasEmptyAssociatedType && !DI->properlyDominates (AI, IEAI)))
12281264 return nullptr ;
12291265
12301266 unsigned ArgIdx = 0 ;
0 commit comments