diff --git a/include/swift/SIL/MemAccessUtils.h b/include/swift/SIL/MemAccessUtils.h index 5d57daef440f2..fbdca6b1be795 100644 --- a/include/swift/SIL/MemAccessUtils.h +++ b/include/swift/SIL/MemAccessUtils.h @@ -1272,7 +1272,8 @@ struct AccessPathWithBase { // The "product leaves" are the leaves obtained by only looking through type // products (structs and tuples) and NOT type sums (enums). void visitProductLeafAccessPathNodes( - SILValue address, TypeExpansionContext tec, SILModule &module, + AccessPath rootPath, SILValue address, TypeExpansionContext tec, + SILModule &module, std::function visitor); inline AccessPath AccessPath::compute(SILValue address) { diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index 8e95c89b5378d..ec8e43e0f3ea7 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -1436,10 +1436,12 @@ AccessPathWithBase AccessPathWithBase::computeInScope(SILValue address) { } void swift::visitProductLeafAccessPathNodes( - SILValue address, TypeExpansionContext tec, SILModule &module, + AccessPath rootPath, SILValue address, TypeExpansionContext tec, + SILModule &module, std::function visitor) { + assert(rootPath.isValid()); + assert(AccessPath::compute(address) == rootPath); SmallVector, 32> worklist; - auto rootPath = AccessPath::compute(address); auto *node = rootPath.getPathNode().node; worklist.push_back({address->getType(), node}); while (!worklist.empty()) { diff --git a/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp b/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp index 755cc2d2ee8f5..d853bce47a560 100644 --- a/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp +++ b/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp @@ -560,6 +560,13 @@ bool HoistDestroys::rewriteDestroys(const AccessStorage &storage, bool HoistDestroys::foldBarrier(SILInstruction *barrier, const AccessStorage &storage, const DeinitBarriers &deinitBarriers) { + auto rootPath = AccessPath::compute(storageRoot); + if (!rootPath.isValid()) { + // [invalid_access_path] The access path to storageRoot isn't understood. + // It can't be determined whether all of its leaves have been visited, so + // foldability can't be determined. Bail. + return false; + } // The load [copy]s which will be folded into load [take]s if folding is // possible. @@ -592,7 +599,8 @@ bool HoistDestroys::foldBarrier(SILInstruction *barrier, // it. SmallPtrSet trivialLeaves; - visitProductLeafAccessPathNodes(storageRoot, typeExpansionContext, module, + visitProductLeafAccessPathNodes(rootPath, storageRoot, typeExpansionContext, + module, [&](AccessPath::PathNode node, SILType ty) { if (ty.isTrivial(*function)) return; @@ -744,10 +752,16 @@ bool HoistDestroys::checkFoldingBarrier( // of the root storage which would be folded if folding were possible. // Find its nontrivial product leaves and remove them from the set of // leaves of the root storage which we're wating to see. + auto rootPath = AccessPath::compute(address); + // [invalid_access_path] The access path to storageRoot was understood, and + // address has identical storage to its storage. The access path to address + // must be valid. + assert(rootPath.isValid()); + bool alreadySawLeaf = false; bool alreadySawTrivialSubleaf = false; visitProductLeafAccessPathNodes( - address, typeExpansionContext, module, + rootPath, address, typeExpansionContext, module, [&](AccessPath::PathNode node, SILType ty) { if (ty.isTrivial(*function)) { bool inserted = !trivialLeaves.insert(node).second; diff --git a/test/SILOptimizer/hoist_destroy_addr.sil b/test/SILOptimizer/hoist_destroy_addr.sil index 837203379b38a..6603959ee92ca 100644 --- a/test/SILOptimizer/hoist_destroy_addr.sil +++ b/test/SILOptimizer/hoist_destroy_addr.sil @@ -1179,3 +1179,23 @@ entry(%addr : $*MoE): %retval = tuple () return %retval : $() } + +sil @getPointer : $@convention(thin) () -> Builtin.RawPointer + +struct Nontrivial { + var guts: Builtin.AnyObject +} + +sil [ossa] @rdar121327964 : $@convention(method) (@owned Nontrivial) -> () { +bb0(%0 : @owned $Nontrivial): + %6 = function_ref @getPointer : $@convention(thin) () -> Builtin.RawPointer + %7 = apply %6() : $@convention(thin) () -> Builtin.RawPointer + %8 = pointer_to_address %7 : $Builtin.RawPointer to [strict] $*Nontrivial + %9 = copy_value %0 : $Nontrivial + %10 = begin_access [modify] [dynamic] %8 : $*Nontrivial + store %9 to [assign] %10 : $*Nontrivial + end_access %10 : $*Nontrivial + destroy_value %0 : $Nontrivial + %14 = tuple () + return %14 : $() +}