ConditionForwarding: don't violate ownership

Instructions in a block, which is moved, must not use any (non-trivial) value because we don't do liveness analysis.
When moving a block, there is no guarantee that the operand value is still alive at the new location.

Fixes an ownership violation error
rdar://146630743
This commit is contained in:
Erik Eckstein
2025-03-10 12:48:14 +01:00
parent 737b5ec924
commit 2ce9ddeb46
2 changed files with 54 additions and 5 deletions

View File

@@ -126,8 +126,25 @@ private:
/// Returns true if all instructions of block \p BB are safe to be moved
/// across other code.
static bool hasNoRelevantSideEffects(SILBasicBlock *BB) {
static bool hasNoRelevantSideEffects(SILBasicBlock *BB, EnumInst *enumInst) {
for (SILInstruction &I : *BB) {
if (BB->getParent()->hasOwnership() && &I != enumInst) {
// The instruction must not use any (non-trivial) value because we don't
// do liveness analysis. When moving the block, there is no guarantee that
// the operand value is still alive at the new location.
for (Operand *op : I.getRealOperands()) {
SILValue opv = op->get();
// The `enum` is an exception, because it's a forwarded value and we already
// check that it's forwarded to the `switch_enum` at the new location.
if (opv == enumInst)
continue;
// If the value is defined in the block it's a block-local liferange.
if (opv->getParentBlock() == BB)
continue;
if (opv->getOwnershipKind() != OwnershipKind::None)
return false;
}
}
if (I.getMemoryBehavior() == MemoryBehavior::None)
continue;
if (auto *CF = dyn_cast<CondFailInst>(&I)) {
@@ -144,9 +161,6 @@ static bool hasNoRelevantSideEffects(SILBasicBlock *BB) {
return false;
continue;
}
if (isa<BeginBorrowInst>(&I) || isa<EndBorrowInst>(&I)) {
continue;
}
LLVM_DEBUG(llvm::dbgs() << "Bailing out, found inst with side-effects ");
LLVM_DEBUG(I.dump());
return false;
@@ -212,7 +226,7 @@ bool ConditionForwarding::tryOptimize(SwitchEnumInst *SEI) {
CommonBranchBlock = PredPred;
// We cannot move the block across other code if it has side-effects.
if (!hasNoRelevantSideEffects(Pred))
if (!hasNoRelevantSideEffects(Pred, EI))
return false;
PredBlocks.push_back(Pred);
}