diff --git a/include/swift/SILOptimizer/Utils/ValueLifetime.h b/include/swift/SILOptimizer/Utils/ValueLifetime.h index 92af2083ef62f..9fe60c1bbfb43 100644 --- a/include/swift/SILOptimizer/Utils/ValueLifetime.h +++ b/include/swift/SILOptimizer/Utils/ValueLifetime.h @@ -17,8 +17,9 @@ #ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H #define SWIFT_SILOPTIMIZER_UTILS_CFG_H -#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" namespace swift { @@ -159,7 +160,8 @@ class ValueLifetimeAnalysis { /// destroy_value at each instruction of the \p frontier. void endLifetimeAtFrontier(SILValue valueOrStackLoc, const ValueLifetimeAnalysis::Frontier &frontier, - SILBuilderContext &builderCtxt); + SILBuilderContext &builderCtxt, + InstModCallbacks callbacks); } // end namespace swift diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 91e75def71ffb..f8691786ebb97 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -1323,7 +1323,8 @@ bool swift::collectDestroys(SingleValueInstruction *inst, /// not be needed anymore with OSSA. static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai, ArrayRef paiUsers, - SILBuilderContext &builderCtxt) { + SILBuilderContext &builderCtxt, + InstModCallbacks callbacks) { SmallVector argsToHandle; getConsumedPartialApplyArgs(pai, argsToHandle, /*includeTrivialAddrArgs*/ false); @@ -1357,7 +1358,7 @@ static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai, // Delay the destroy of the value (either as SSA value or in the stack- // allocated temporary) at the end of the partial_apply's lifetime. - endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt); + endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks); } return true; } @@ -1406,7 +1407,8 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *closure, "partial_apply [stack] should have been handled before"); SILBuilderContext builderCtxt(pai->getModule()); if (needKeepArgsAlive) { - if (!keepArgsOfPartialApplyAlive(pai, closureDestroys, builderCtxt)) + if (!keepArgsOfPartialApplyAlive(pai, closureDestroys, builderCtxt, + callbacks)) return false; } else { // A preceeding partial_apply -> apply conversion (done in diff --git a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp index d9a36eb051e16..4d662e974d1b8 100644 --- a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp +++ b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp @@ -115,7 +115,7 @@ bool PartialApplyCombiner::copyArgsToTemporaries( // Destroy the argument value (either as SSA value or in the stack- // allocated temporary) at the end of the partial_apply's lifetime. - endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt); + endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks); } return true; } diff --git a/lib/SILOptimizer/Utils/ValueLifetime.cpp b/lib/SILOptimizer/Utils/ValueLifetime.cpp index 4f90e9cc0bd80..55c0e05625a87 100644 --- a/lib/SILOptimizer/Utils/ValueLifetime.cpp +++ b/lib/SILOptimizer/Utils/ValueLifetime.cpp @@ -327,15 +327,12 @@ void ValueLifetimeAnalysis::dump() const { void swift::endLifetimeAtFrontier( SILValue valueOrStackLoc, const ValueLifetimeAnalysis::Frontier &frontier, - SILBuilderContext &builderCtxt) { + SILBuilderContext &builderCtxt, InstModCallbacks callbacks) { for (SILInstruction *endPoint : frontier) { SILBuilderWithScope builder(endPoint, builderCtxt); SILLocation loc = RegularLocation(endPoint->getLoc().getSourceLoc()); - if (valueOrStackLoc->getType().isObject()) { - builder.emitDestroyValueOperation(loc, valueOrStackLoc); - } else { - assert(isa(valueOrStackLoc)); - builder.createDestroyAddr(loc, valueOrStackLoc); + emitDestroyOperation(builder, loc, valueOrStackLoc, callbacks); + if (isa(valueOrStackLoc)) { builder.createDeallocStack(loc, valueOrStackLoc); } } diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil index 05d275d17913a..fcb3d1060684f 100644 --- a/test/SILOptimizer/sil_combine_apply.sil +++ b/test/SILOptimizer/sil_combine_apply.sil @@ -991,3 +991,29 @@ sil @test_partial_apply_method : $@convention(thin) () -> @owned @callee_owned ( // CHECK: [[FN:%.*]] = function_ref @method // CHECK-NEXT: partial_apply [[FN]]() // CHECK-NEXT: return + +sil [noinline] @$foo : $@convention(thin) (@owned { var Int64 }) -> () + +// CHECK-LABEL: sil private [noinline] @$testdeadpartialapply : +// CHECK-NOT: partial_apply +// CHECK-LABEL: } // end sil function '$testdeadpartialapply' +sil private [noinline] @$testdeadpartialapply : $@convention(thin) (@owned { var Int64 }) -> () { +bb0(%0 : ${ var Int64 }): + %3 = function_ref @$foo : $@convention(thin) (@owned { var Int64 }) -> () + %5 = partial_apply [callee_guaranteed] %3(%0) : $@convention(thin) (@owned { var Int64 }) -> () + cond_br undef, bb1, bb2 +bb1: + strong_retain %0 : ${ var Int64 } + strong_retain %5 : $@callee_guaranteed () -> () + unreachable +bb2: + strong_retain %0 : ${ var Int64 } + strong_retain %5 : $@callee_guaranteed () -> () + br bb3 +bb3: + strong_release %5 : $@callee_guaranteed () -> () + strong_release %5 : $@callee_guaranteed () -> () + strong_release %0 : ${ var Int64 } + %rv = tuple() + return %rv : $() +}