From 990f5d95ec26b947c0adced8b9c6f5cb83516173 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 31 Jan 2025 15:03:01 -0800 Subject: [PATCH] Fix swift::areUsesWithinValueLifetime for guaranteed values To find if all the uses are within a guaranteed value, we should find all borrow introducers. swift::findOwnershipReferenceAggregate looks only through forwarding operations with single operands. For simplicity, continue using swift::findOwnershipReferenceAggregate, but return false when it does not find a borrow introducer. --- lib/SILOptimizer/Utils/OwnershipOptUtils.cpp | 7 ++++++ test/SILOptimizer/outliner_ossa.sil | 25 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp b/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp index 850533fec9148..f3d5308eddcde 100644 --- a/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp +++ b/lib/SILOptimizer/Utils/OwnershipOptUtils.cpp @@ -468,8 +468,15 @@ bool swift::areUsesWithinValueLifetime(SILValue value, ArrayRef uses, return false; } if (value->getOwnershipKind() == OwnershipKind::Guaranteed) { + // For guaranteed values, we have to find the borrow introducing guaranteed + // reference roots and then ensure uses are within all of their lifetimes. + // For simplicity, we only look through single forwarding operations to find + // a borrow introducer here. value = findOwnershipReferenceAggregate(value); BorrowedValue borrowedValue(value); + if (!borrowedValue) { + return false; + } if (!borrowedValue.isLocalScope()) { return true; } diff --git a/test/SILOptimizer/outliner_ossa.sil b/test/SILOptimizer/outliner_ossa.sil index 7e2598530d8e6..78f66e9f9ec33 100644 --- a/test/SILOptimizer/outliner_ossa.sil +++ b/test/SILOptimizer/outliner_ossa.sil @@ -16,6 +16,7 @@ import Foundation struct DataWrapper { let data: Data + let otherData: Data } sil @getData : $@convention(thin) () -> @owned Data @@ -200,6 +201,30 @@ bb0(%0: @owned $MyObject): return %51 : $Optional } +// Not optimized +// CHECK-LABEL: sil [Osize] [ossa] @test_struct_guaranteed : +// CHECK: objc_method +// CHECK-LABEL: } // end sil function 'test_struct_guaranteed' +sil [Osize] [ossa] @test_struct_guaranteed : $@convention(thin) (@owned MyObject) -> @owned Optional { +bb0(%0 : @owned $MyObject): + %1 = metatype $@objc_metatype MyObject.Type + %2 = function_ref @getData : $@convention(thin) () -> @owned Data + %3 = apply %2() : $@convention(thin) () -> @owned Data + %4 = begin_borrow %3 + %5 = struct $DataWrapper (%4, %4) + %6 = struct_extract %5, #DataWrapper.data + %7 = function_ref @$s10Foundation4DataV19_bridgeToObjectiveCSo6NSDataCyF : $@convention(method) (@guaranteed Data) -> @owned NSData + %8 = apply %7(%6) : $@convention(method) (@guaranteed Data) -> @owned NSData + %9 = enum $Optional, #Optional.some!enumelt, %8 + end_borrow %4 + %13 = objc_method %1, #MyObject.take!foreign : (MyObject.Type) -> (Data?) -> Data?, $@convention(objc_method) (Optional, @objc_metatype MyObject.Type) -> @autoreleased Optional + %14 = apply %13(%9, %1) : $@convention(objc_method) (Optional, @objc_metatype MyObject.Type) -> @autoreleased Optional + destroy_value %0 + destroy_value %3 + destroy_value %9 + return %14 +} + sil [Osize] [ossa] @test_dont_crash : $@convention(thin) (@owned MyObject) -> () { bb0(%0: @owned $MyObject): %35 = metatype $@objc_metatype MyObject.Type