Skip to content

Commit d5d9338

Browse files
authored
Merge pull request #75689 from eeckstein/alias-analysis-improvements
Optimizer: some improvements for alias analysis in several utilities
2 parents f672c77 + def3b6f commit d5d9338

File tree

11 files changed

+260
-32
lines changed

11 files changed

+260
-32
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/AliasAnalysis.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ struct AliasAnalysis {
309309
if destroy.destroyedValue.type.isNoEscapeFunction {
310310
return .noEffects
311311
}
312+
if destroy.isDeadEnd {
313+
// We don't have to take deinit effects into acount for a `destroy_value [dead_end]`.
314+
// Such destroys are lowered to no-ops and will not call any deinit.
315+
return .noEffects
316+
}
312317
return defaultEffects(of: destroy, on: memLoc)
313318

314319
default:
@@ -569,11 +574,7 @@ private enum MemoryLocation {
569574
var isLetValue: Bool {
570575
switch self {
571576
case .memoryAddress(let addr):
572-
switch addr.accessBase {
573-
case .global(let global): return global.isLet
574-
case .class(let rea): return rea.fieldIsLet
575-
default: return false
576-
}
577+
return addr.accessBase.isLet
577578
case .modifyAccessScope:
578579
return false
579580
}

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
571571
switch uacUse.instruction {
572572
case is IsUniqueInst:
573573
break
574-
case is LoadInst, is LoadBorrowInst:
574+
case is LoadInst, is LoadBorrowInst, is ApplyInst, is TryApplyInst:
575575
if followLoads(at: path) {
576576
return .abortWalk
577577
}

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -625,16 +625,6 @@ private struct EscapesToValueVisitor : EscapeVisitor {
625625
}
626626

627627
extension Function {
628-
var globalOfGlobalInitFunction: GlobalVariable? {
629-
if isGlobalInitFunction,
630-
let ret = returnInstruction,
631-
let atp = ret.returnedValue as? AddressToPointerInst,
632-
let ga = atp.address as? GlobalAddrInst {
633-
return ga.global
634-
}
635-
return nil
636-
}
637-
638628
var initializedGlobal: GlobalVariable? {
639629
if !isGlobalInitOnceFunction {
640630
return nil

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,11 @@ final public class UnmanagedAutoreleaseValueInst : RefCountingInst {}
506506

507507
final public class DestroyValueInst : Instruction, UnaryInstruction {
508508
public var destroyedValue: Value { operand.value }
509+
510+
/// True if this `destroy_value` is inside a dead-end block is only needed to formally
511+
/// end the lifetime of its operand.
512+
/// Such `destroy_value` instructions are lowered to no-ops.
513+
public var isDeadEnd: Bool { bridged.DestroyValueInst_isDeadEnd() }
509514
}
510515

511516
final public class DestroyAddrInst : Instruction, UnaryInstruction {

SwiftCompilerSources/Sources/SIL/Utilities/AccessUtils.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,17 @@ private extension PointerToAddressInst {
434434
}
435435
return walker.result
436436
}
437+
438+
var resultOfGlobalAddressorCall: GlobalVariable? {
439+
if isStrict,
440+
let apply = pointer as? ApplyInst,
441+
let callee = apply.referencedFunction,
442+
let global = callee.globalOfGlobalInitFunction
443+
{
444+
return global
445+
}
446+
return nil
447+
}
437448
}
438449

439450
/// The `EnclosingScope` of an access is the innermost `begin_access`
@@ -507,6 +518,9 @@ private struct AccessPathWalker : AddressUseDefWalker {
507518
if let p2ai = address as? PointerToAddressInst {
508519
if let originatingAddr = p2ai.originatingAddress {
509520
return walkUp(address: originatingAddr, path: path)
521+
} else if let global = p2ai.resultOfGlobalAddressorCall {
522+
self.result = AccessPath(base: .global(global), projectionPath: path.projectionPath)
523+
return .continueWalk
510524
} else {
511525
self.result = AccessPath(base: .pointer(p2ai), projectionPath: path.projectionPath)
512526
return .continueWalk
@@ -628,3 +642,15 @@ extension ValueUseDefWalker where Path == SmallProjectionPath {
628642
}
629643
}
630644
}
645+
646+
extension Function {
647+
public var globalOfGlobalInitFunction: GlobalVariable? {
648+
if isGlobalInitFunction,
649+
let ret = returnInstruction,
650+
let atp = ret.returnedValue as? AddressToPointerInst,
651+
let ga = atp.address as? GlobalAddrInst {
652+
return ga.global
653+
}
654+
return nil
655+
}
656+
}

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,7 @@ struct BridgedInstruction {
951951

952952
BRIDGED_INLINE SwiftInt ProjectBoxInst_fieldIndex() const;
953953
BRIDGED_INLINE bool EndCOWMutationInst_doKeepUnique() const;
954+
BRIDGED_INLINE bool DestroyValueInst_isDeadEnd() const;
954955
BRIDGED_INLINE SwiftInt EnumInst_caseIndex() const;
955956
BRIDGED_INLINE SwiftInt UncheckedEnumDataInst_caseIndex() const;
956957
BRIDGED_INLINE SwiftInt InitEnumDataAddrInst_caseIndex() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,10 @@ bool BridgedInstruction::EndCOWMutationInst_doKeepUnique() const {
11111111
return getAs<swift::EndCOWMutationInst>()->doKeepUnique();
11121112
}
11131113

1114+
bool BridgedInstruction::DestroyValueInst_isDeadEnd() const {
1115+
return getAs<swift::DestroyValueInst>()->isDeadEnd();
1116+
}
1117+
11141118
SwiftInt BridgedInstruction::EnumInst_caseIndex() const {
11151119
return getAs<swift::EnumInst>()->getCaseIndex();
11161120
}

test/SILOptimizer/accessutils.sil

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,85 @@ bb0:
370370

371371
sil_global @global1 : $Int64
372372
sil_global @global2 : $Int64
373+
sil_global @somePointer : $Builtin.RawPointer
374+
375+
sil [global_init] [ossa] @addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer {
376+
bb0:
377+
%0 = global_addr @global1 : $*Int64
378+
%1 = address_to_pointer %0 : $*Int64 to $Builtin.RawPointer
379+
return %1 : $Builtin.RawPointer
380+
}
381+
382+
sil [global_init] [ossa] @external_addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer
383+
384+
sil [global_init] [ossa] @wrong_addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer {
385+
bb0:
386+
%0 = global_addr @somePointer : $*Builtin.RawPointer
387+
%1 = load [trivial] %0 : $*Builtin.RawPointer
388+
return %1 : $Builtin.RawPointer
389+
}
390+
391+
// CHECK-LABEL: Accesses for testSimpleGlobal
392+
// CHECK-NEXT: Value: %0 = global_addr @global1 : $*Int64
393+
// CHECK-NEXT: Scope: base
394+
// CHECK-NEXT: Base: global - @global1
395+
// CHECK-NEXT: Path: ""
396+
// CHECK-NEXT: no Storage paths
397+
// CHECK-NEXT: End accesses for testSimpleGlobal
398+
sil [ossa] @testSimpleGlobal : $@convention(thin) () -> Int64 {
399+
bb0:
400+
%0 = global_addr @global1 : $*Int64
401+
%1 = load [trivial] %0 : $*Int64
402+
return %1 : $Int64
403+
}
404+
405+
// CHECK-LABEL: Accesses for testGlobalViaAddressor
406+
// CHECK-NEXT: Value: %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
407+
// CHECK-NEXT: Scope: base
408+
// CHECK-NEXT: Base: global - @global1
409+
// CHECK-NEXT: Path: ""
410+
// CHECK-NEXT: no Storage paths
411+
// CHECK-NEXT: End accesses for testGlobalViaAddressor
412+
sil [ossa] @testGlobalViaAddressor : $@convention(thin) () -> Int64 {
413+
bb0:
414+
%0 = function_ref @addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer
415+
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
416+
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
417+
%3 = load [trivial] %2 : $*Int64
418+
return %3 : $Int64
419+
}
420+
421+
// CHECK-LABEL: Accesses for testGlobalViaUnknwonAddressor
422+
// CHECK-NEXT: Value: %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
423+
// CHECK-NEXT: Scope: base
424+
// CHECK-NEXT: Base: pointer - %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
425+
// CHECK-NEXT: Path: ""
426+
// CHECK-NEXT: no Storage paths
427+
// CHECK-NEXT: End accesses for testGlobalViaUnknwonAddressor
428+
sil [ossa] @testGlobalViaUnknwonAddressor : $@convention(thin) () -> Int64 {
429+
bb0:
430+
%0 = function_ref @external_addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer
431+
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
432+
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
433+
%3 = load [trivial] %2 : $*Int64
434+
return %3 : $Int64
435+
}
436+
437+
// CHECK-LABEL: Accesses for testGlobalViaWrongAddressor
438+
// CHECK-NEXT: Value: %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
439+
// CHECK-NEXT: Scope: base
440+
// CHECK-NEXT: Base: pointer - %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
441+
// CHECK-NEXT: Path: ""
442+
// CHECK-NEXT: no Storage paths
443+
// CHECK-NEXT: End accesses for testGlobalViaWrongAddressor
444+
sil [ossa] @testGlobalViaWrongAddressor : $@convention(thin) () -> Int64 {
445+
bb0:
446+
%0 = function_ref @wrong_addressor_of_global1 : $@convention(thin) () -> Builtin.RawPointer
447+
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
448+
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int64
449+
%3 = load [trivial] %2 : $*Int64
450+
return %3 : $Int64
451+
}
373452

374453
sil @coro : $@yield_once @convention(thin) () -> @yields @inout Int64
375454

test/SILOptimizer/addr_escape_info.sil

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ sil @non_escaping_class_argument : $@convention(thin) (@guaranteed X) -> () {
4848
sil @inout_class_argument : $@convention(thin) (@inout X) -> () {
4949
[%0: noescape **]
5050
}
51+
sil @inout_class_argument2 : $@convention(thin) (@inout XandIntClass) -> () {
52+
[%0: noescape **]
53+
}
54+
sil @inout_class_argument3 : $@convention(thin) (@inout XandIntClass) -> @error Error {
55+
[%0: noescape **]
56+
}
5157
sil @container_argument : $@convention(thin) (@guaranteed Container) -> ()
5258
sil @take_closure_as_addr : $@convention(thin) (@in @callee_guaranteed () -> ()) -> ()
5359
sil @take_closure_as_addr_noescape : $@convention(thin) (@in @callee_guaranteed () -> ()) -> () {
@@ -813,6 +819,9 @@ bb0(%0 : @owned $X):
813819

814820
// CHECK-LABEL: Address escape information for test_unchecked_addr_cast:
815821
// CHECK: value: %1 = alloc_stack $X
822+
// CHECK: ==> %10 = apply %9(%4) : $@convention(thin) (@inout XandIntClass) -> ()
823+
// CHECK: ==> try_apply %11(%4) : $@convention(thin) (@inout XandIntClass) -> @error any Error, normal bb1, error bb2
824+
// CHECK: - %15 = apply %14() : $@convention(thin) () -> ()
816825
// CHECK-NEXT: End function test_unchecked_addr_cast
817826
sil [ossa] @test_unchecked_addr_cast : $@convention(thin) (@owned X) -> @owned XandIntClass {
818827
bb0(%0 : @owned $X):
@@ -824,25 +833,19 @@ bb0(%0 : @owned $X):
824833
%6 = load_borrow %4 : $*XandIntClass
825834
end_borrow %6 : $XandIntClass
826835
%8 = load [take] %4 : $*XandIntClass
836+
%9 = function_ref @inout_class_argument2 : $@convention(thin) (@inout XandIntClass) -> ()
837+
%10 = apply %9(%4) : $@convention(thin) (@inout XandIntClass) -> ()
838+
%11 = function_ref @inout_class_argument3 : $@convention(thin) (@inout XandIntClass) -> @error Error
839+
try_apply %11(%4) : $@convention(thin) (@inout XandIntClass) -> @error Error, normal bb1, error bb2
840+
841+
bb1(%13 : $()):
842+
%14 = function_ref @no_arguments : $@convention(thin) () -> ()
843+
%15 = apply %14() : $@convention(thin) () -> ()
827844
dealloc_stack %1 : $*X
828845
return %8 : $XandIntClass
829-
}
830846

831-
// CHECK-LABEL: Address escape information for test_unchecked_addr_cast_escaping:
832-
// CHECK: value: %1 = alloc_stack $X
833-
// CHECK-NEXT: ==> %6 = apply %5(%4) : $@convention(thin) (@inout X) -> ()
834-
// CHECK-NEXT: End function test_unchecked_addr_cast_escaping
835-
sil [ossa] @test_unchecked_addr_cast_escaping : $@convention(thin) (@owned XandIntClass) -> () {
836-
bb0(%0 : @owned $XandIntClass):
837-
%1 = alloc_stack $XandIntClass
838-
store %0 to [init] %1 : $*XandIntClass
839-
fix_lifetime %1 : $*XandIntClass
840-
%4 = unchecked_addr_cast %1 : $*XandIntClass to $*X
841-
%5 = function_ref @inout_class_argument : $@convention(thin) (@inout X) -> ()
842-
%6 = apply %5(%4) : $@convention(thin) (@inout X) -> ()
843-
dealloc_stack %1 : $*XandIntClass
844-
%8 = tuple ()
845-
return %8 : $()
847+
bb2(%17 : $Error):
848+
unreachable
846849
}
847850

848851
// CHECK-LABEL: Address escape information for test_store_borrow:

test/SILOptimizer/escape_info.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,3 +1457,17 @@ bb0:
14571457
%3 = unchecked_ref_cast %1 : $Derived to $X
14581458
return %2 : $X
14591459
}
1460+
1461+
// CHECK-LABEL: Escape information for test_unchecked_addr_cast:
1462+
// CHECK: global: %1 = alloc_ref $X
1463+
// CHECK: End function test_unchecked_addr_cast
1464+
sil @test_unchecked_addr_cast : $@convention(thin) () -> @owned Builtin.RawPointer {
1465+
bb0:
1466+
%0 = alloc_stack $X
1467+
%1 = alloc_ref $X
1468+
store %1 to %0 : $*X
1469+
%3 = unchecked_addr_cast %0 : $*X to $*Builtin.RawPointer
1470+
%4 = load %3 : $*Builtin.RawPointer
1471+
dealloc_stack %0 : $*X
1472+
return %4 : $Builtin.RawPointer
1473+
}

0 commit comments

Comments
 (0)