From 5f5692c3ba4bb6ed464803d48905f96e8b7c9478 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 6 Apr 2023 13:33:22 -0700 Subject: [PATCH 1/2] [Gardening] Separated debug output lines. --- lib/SILOptimizer/Transforms/DeadCodeElimination.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp index 93c69946382c6..de64b0508c25b 100644 --- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp @@ -680,7 +680,8 @@ bool DCE::removeDead() { } LLVM_DEBUG(llvm::dbgs() << "Replacing branch: "); LLVM_DEBUG(Inst->dump()); - LLVM_DEBUG(llvm::dbgs() << "with jump to: BB" << postDom->getDebugID()); + LLVM_DEBUG(llvm::dbgs() + << "with jump to: BB" << postDom->getDebugID() << "\n"); replaceBranchWithJump(Inst, postDom); Inst->eraseFromParent(); From 38cbc6fde11d4a0f06a13ab08855082c61b22a07 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 6 Apr 2023 13:33:50 -0700 Subject: [PATCH 2/2] [DCE] Destroys of live values are live. As is done for `end_borrow`s, add a dependency from a `destroy_value`s to its operand so that it is not eliminated if its operand isn't. --- .../Transforms/DeadCodeElimination.cpp | 2 + .../dead_code_elimination_ossa.sil | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp index de64b0508c25b..edd753eb3a694 100644 --- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp @@ -280,6 +280,8 @@ void DCE::markLive() { if (phi && (phi->isLexical() || hasPointerEscape(phi))) { markInstructionLive(&I); } + // The instruction is live only if it's operand value is also live + addReverseDependency(I.getOperand(0), &I); break; } case SILInstructionKind::EndBorrowInst: { diff --git a/test/SILOptimizer/dead_code_elimination_ossa.sil b/test/SILOptimizer/dead_code_elimination_ossa.sil index cf773fa01ec2d..92202f804762c 100644 --- a/test/SILOptimizer/dead_code_elimination_ossa.sil +++ b/test/SILOptimizer/dead_code_elimination_ossa.sil @@ -8,6 +8,16 @@ import Swift public struct S { var o: AnyObject } + +typealias Int1 = Builtin.Int1 + +class C {} + +struct CAndBit { + var c: C + var bit: Int1 +} + sil @dummy : $@convention(thin) () -> () // CHECK-LABEL: sil [ossa] @dead1 : @@ -362,3 +372,38 @@ bb0(%0 : @guaranteed $S): %8 = tuple () return %8 : $() } + +// CHECK-LABEL: sil [ossa] @dce_destroy_of_live_copy : {{.*}} { +// CHECK: [[COPY:%[^,]+]] = copy_value +// CHECK: cond_br {{%[^,]+}}, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT]]: +// CHECK: destroy_value [[COPY]] +// CHECK: br [[EXIT:bb[0-9]+]] +// CHECK: [[RIGHT]]: +// CHECK: destroy_value [[COPY]] +// CHECK: br [[EXIT]] +// CHECK: [[EXIT]]: +// CHECK-LABEL: } // end sil function 'dce_destroy_of_live_copy' +sil [ossa] @dce_destroy_of_live_copy : $@convention(thin) (Int1) -> () { +entry(%condition : $Int1): + %instance = apply undef() : $@convention(thin) () -> (@owned C) + %borrow = begin_borrow %instance : $C + %aggregate = struct $CAndBit(%borrow : $C, %condition : $Int1) + %copy = copy_value %aggregate : $CAndBit + end_borrow %borrow : $C + %borrow2 = begin_borrow %copy : $CAndBit + %bit = struct_extract %borrow2 : $CAndBit, #CAndBit.bit + end_borrow %borrow2 : $CAndBit + apply undef(%bit) : $@convention(thin) (Int1) -> () + cond_br %condition, left, right +left: + destroy_value %copy : $CAndBit + br exit +right: + destroy_value %copy : $CAndBit + br exit +exit: + destroy_value %instance : $C + %retval = tuple () + return %retval : $() +}