@@ -681,13 +681,48 @@ bool CSE::processOpenExistentialRef(SILInstruction *Inst, ValueBase *V,
681
681
auto &Builder = Cloner.getBuilder ();
682
682
Builder.setOpenedArchetypesTracker (&OpenedArchetypesTracker);
683
683
684
+ llvm::SmallPtrSet<SILInstruction *, 16 > Processed;
684
685
// Now clone each candidate and replace the opened archetype
685
686
// by a dominating one.
686
- for (auto Candidate : Candidates) {
687
+ while (!Candidates.empty ()) {
688
+ auto Candidate = Candidates.pop_back_val ();
689
+ if (Processed.count (Candidate))
690
+ continue ;
691
+ // True if a candidate depends on the old opened archetype.
692
+ bool DependsOnOldOpenedArchetype = !Candidate->getTypeDependentOperands ().empty ();
693
+ if (!Candidate->use_empty () &&
694
+ Candidate->getType ().getSwiftRValueType ()->hasOpenedExistential ()) {
695
+ // Check if the result type of the candidate depends on the opened
696
+ // existential in question.
697
+ auto ResultDependsOnOldOpenedArchetype =
698
+ Candidate->getType ().getSwiftRValueType ().findIf (
699
+ [&OldOpenedArchetype](Type t) -> bool {
700
+ if (t.getCanonicalTypeOrNull () == OldOpenedArchetype)
701
+ return true ;
702
+ return false ;
703
+ });
704
+ if (ResultDependsOnOldOpenedArchetype) {
705
+ DependsOnOldOpenedArchetype |= ResultDependsOnOldOpenedArchetype;
706
+ // We need to update uses of this candidate, because their types
707
+ // may be affected.
708
+ for (auto Use : Candidate->getUses ()) {
709
+ Candidates.insert (Use->getUser ());
710
+ }
711
+ }
712
+ }
713
+ // Remember that this candidate was processed already.
714
+ Processed.insert (Candidate);
715
+
716
+ // No need to clone if there is no dependency on the old opened archetype.
717
+ if (!DependsOnOldOpenedArchetype)
718
+ continue ;
719
+
687
720
Builder.getOpenedArchetypes ().addOpenedArchetypeOperands (
688
721
Candidate->getTypeDependentOperands ());
689
722
Builder.setInsertionPoint (Candidate);
690
723
auto NewI = Cloner.clone (Candidate);
724
+ // Result types of candidate's uses instructions may be using this archetype.
725
+ // Thus, we need to try to replace it there.
691
726
Candidate->replaceAllUsesWith (NewI);
692
727
if (I == Candidate->getIterator ())
693
728
I = NewI->getIterator ();
0 commit comments