Skip to content

Commit 89d3326

Browse files
committed
Swift Optimizer: add a simplification for pointer_to_address
For a redundant pair of pointer-address conversions, e.g. %2 = address_to_pointer %1 %3 = pointer_to_address %2 [strict] replace all uses of %3 with %1.
1 parent e45b82f commit 89d3326

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ swift_compiler_sources(Optimizer
1919
SimplifyInitEnumDataAddr.swift
2020
SimplifyLoad.swift
2121
SimplifyPartialApply.swift
22+
SimplifyPointerToAddress.swift
2223
SimplifyRefCasts.swift
2324
SimplifyRetainReleaseValue.swift
2425
SimplifyStrongRetainRelease.swift
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- SimplifyPointerToAddress.swift -----------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension PointerToAddressInst : OnoneSimplifyable {
16+
17+
/// For a redundant pair of pointer-address conversions, e.g.
18+
///
19+
/// %2 = address_to_pointer %1
20+
/// %3 = pointer_to_address %2 [strict]
21+
///
22+
/// replace all uses of %3 with %1.
23+
///
24+
func simplify(_ context: SimplifyContext) {
25+
if let atp = self.pointer as? AddressToPointerInst,
26+
atp.address.type == self.type,
27+
self.isStrict,
28+
29+
// If the pointer is within an ownership scope, the transformation can break ownership rules, e.g.
30+
// %2 = begin_borrow %1
31+
// %3 = ref_tail_addr %2
32+
// %4 = address_to_pointer %3
33+
// end_borrow %2
34+
// %5 = pointer_to_address %4 <- cannot replace %5 with %3!
35+
//
36+
!atp.address.accessBase.hasLocalOwnershipLifetime
37+
{
38+
self.uses.replaceAll(with: atp.address, context)
39+
}
40+
}
41+
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ class AddressToPointerInst : SingleValueInstruction, UnaryInstruction {
457457
final public
458458
class PointerToAddressInst : SingleValueInstruction, UnaryInstruction {
459459
public var pointer: Value { operand.value }
460+
public var isStrict: Bool { bridged.PointerToAddressInst_isStrict() }
460461
}
461462

462463
final public

include/swift/SIL/SILBridging.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,9 @@ struct BridgedInstruction {
546546
return getAs<swift::BuiltinInst>()->getSubstitutions();
547547
}
548548

549+
bool PointerToAddressInst_isStrict() const {
550+
return getAs<swift::PointerToAddressInst>()->isStrict();
551+
}
549552

550553
bool AddressToPointerInst_needsStackProtection() const {
551554
return getAs<swift::AddressToPointerInst>()->needsStackProtection();
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -onone-simplification -simplify-instruction=pointer_to_address | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
sil_stage canonical
6+
7+
import Builtin
8+
import Swift
9+
import SwiftShims
10+
11+
class C {}
12+
13+
// CHECK-LABEL: sil @remove_conversion :
14+
// CHECK-NOT: address_to_pointer
15+
// CHECK-NOT: pointer_to_address
16+
// CHECK: [[L:%.*]] = load %0
17+
// CHECK: return [[L]]
18+
// CHECK: } // end sil function 'remove_conversion'
19+
sil @remove_conversion : $@convention(thin) (@in Int) -> Int {
20+
bb0(%0 : $*Int):
21+
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
22+
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int
23+
%3 = load %2 : $*Int
24+
return %3 : $Int
25+
}
26+
27+
// CHECK-LABEL: sil @mismatching_type :
28+
// CHECK: address_to_pointer
29+
// CHECK: [[A:%.*]] = pointer_to_address
30+
// CHECK: [[L:%.*]] = load [[A]]
31+
// CHECK: return [[L]]
32+
// CHECK: } // end sil function 'mismatching_type'
33+
sil @mismatching_type : $@convention(thin) (@in Int) -> Bool {
34+
bb0(%0 : $*Int):
35+
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
36+
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Bool
37+
%3 = load %2 : $*Bool
38+
return %3 : $Bool
39+
}
40+
41+
// CHECK-LABEL: sil @no_strict :
42+
// CHECK: address_to_pointer
43+
// CHECK: [[A:%.*]] = pointer_to_address
44+
// CHECK: [[L:%.*]] = load [[A]]
45+
// CHECK: return [[L]]
46+
// CHECK: } // end sil function 'no_strict'
47+
sil @no_strict : $@convention(thin) (@in Int) -> Int {
48+
bb0(%0 : $*Int):
49+
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
50+
%2 = pointer_to_address %1 : $Builtin.RawPointer to $*Int
51+
%3 = load %2 : $*Int
52+
return %3 : $Int
53+
}
54+
55+
// CHECK-LABEL: sil [ossa] @borrow_escape :
56+
// CHECK: address_to_pointer
57+
// CHECK: [[A:%.*]] = pointer_to_address
58+
// CHECK: [[L:%.*]] = load [trivial] [[A]]
59+
// CHECK: return [[L]]
60+
// CHECK: } // end sil function 'borrow_escape'
61+
sil [ossa] @borrow_escape : $@convention(thin) (@guaranteed C) -> Int {
62+
bb0(%0 : @guaranteed $C):
63+
%1 = begin_borrow %0 : $C
64+
%2 = ref_tail_addr %1: $C, $Int
65+
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
66+
end_borrow %1 : $C
67+
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int
68+
%6 = load [trivial] %5 : $*Int
69+
return %6 : $Int
70+
}
71+
72+
sil @createC : $@convention(thin) () -> @owned C
73+
74+
// CHECK-LABEL: sil @non_ossa_local_ownership :
75+
// CHECK: [[A:%.*]] = ref_tail_addr
76+
// CHECK-NOT: address_to_pointer
77+
// CHECK-NOT: pointer_to_address
78+
// CHECK: [[L:%.*]] = load [[A]]
79+
// CHECK: return [[L]]
80+
// CHECK: } // end sil function 'non_ossa_local_ownership'
81+
sil @non_ossa_local_ownership : $@convention(thin) () -> Int {
82+
bb0:
83+
%f = function_ref @createC : $@convention(thin) () -> @owned C
84+
%0 = apply %f() : $@convention(thin) () -> @owned C
85+
%2 = ref_tail_addr %0: $C, $Int
86+
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
87+
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int
88+
%6 = load %5 : $*Int
89+
strong_release %0 : $C
90+
return %6 : $Int
91+
}
92+

0 commit comments

Comments
 (0)