@@ -126,8 +126,25 @@ class ConditionForwarding : public SILFunctionTransform {
126126
127127// / Returns true if all instructions of block \p BB are safe to be moved
128128// / across other code.
129- static bool hasNoRelevantSideEffects (SILBasicBlock *BB) {
129+ static bool hasNoRelevantSideEffects (SILBasicBlock *BB, EnumInst *enumInst ) {
130130 for (SILInstruction &I : *BB) {
131+ if (BB->getParent ()->hasOwnership () && &I != enumInst) {
132+ // The instruction must not use any (non-trivial) value because we don't
133+ // do liveness analysis. When moving the block, there is no guarantee that
134+ // the operand value is still alive at the new location.
135+ for (Operand *op : I.getRealOperands ()) {
136+ SILValue opv = op->get ();
137+ // The `enum` is an exception, because it's a forwarded value and we already
138+ // check that it's forwarded to the `switch_enum` at the new location.
139+ if (opv == enumInst)
140+ continue ;
141+ // If the value is defined in the block it's a block-local liferange.
142+ if (opv->getParentBlock () == BB)
143+ continue ;
144+ if (opv->getOwnershipKind () != OwnershipKind::None)
145+ return false ;
146+ }
147+ }
131148 if (I.getMemoryBehavior () == MemoryBehavior::None)
132149 continue ;
133150 if (auto *CF = dyn_cast<CondFailInst>(&I)) {
@@ -144,9 +161,6 @@ static bool hasNoRelevantSideEffects(SILBasicBlock *BB) {
144161 return false ;
145162 continue ;
146163 }
147- if (isa<BeginBorrowInst>(&I) || isa<EndBorrowInst>(&I)) {
148- continue ;
149- }
150164 LLVM_DEBUG (llvm::dbgs () << " Bailing out, found inst with side-effects " );
151165 LLVM_DEBUG (I.dump ());
152166 return false ;
@@ -212,7 +226,7 @@ bool ConditionForwarding::tryOptimize(SwitchEnumInst *SEI) {
212226 CommonBranchBlock = PredPred;
213227
214228 // We cannot move the block across other code if it has side-effects.
215- if (!hasNoRelevantSideEffects (Pred))
229+ if (!hasNoRelevantSideEffects (Pred, EI ))
216230 return false ;
217231 PredBlocks.push_back (Pred);
218232 }
0 commit comments