Skip to content

Commit dfca714

Browse files
authored
Merge pull request #5332 from gottesmm/semantic_arc_endborrow_llvmpasses
EndBorrow support in LLVMPasses
2 parents 1315d1a + b018645 commit dfca714

File tree

7 files changed

+216
-163
lines changed

7 files changed

+216
-163
lines changed

lib/LLVMPasses/LLVMARCContract.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,10 @@ bool SwiftARCContractImpl::run() {
273273
case RT_UnknownReleaseN:
274274
case RT_BridgeReleaseN:
275275
llvm_unreachable("These are only created by LLVMARCContract !");
276-
// Delete all fix lifetime instructions. After llvm-ir they have no use
277-
// and show up as calls in the final binary.
276+
// Delete all fix lifetime and end borrow instructions. After llvm-ir they
277+
// have no use and show up as calls in the final binary.
278278
case RT_FixLifetime:
279+
case RT_EndBorrow:
279280
Inst.eraseFromParent();
280281
++NumNoopDeleted;
281282
continue;

lib/LLVMPasses/LLVMARCOpts.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B,
102102
case RT_BridgeRelease:
103103
case RT_AllocObject:
104104
case RT_FixLifetime:
105+
case RT_EndBorrow:
105106
case RT_NoMemoryAccessed:
106107
case RT_RetainUnowned:
107108
case RT_CheckUnowned:
@@ -368,6 +369,7 @@ static bool performLocalReleaseMotion(CallInst &Release, BasicBlock &BB,
368369
}
369370

370371
case RT_FixLifetime:
372+
case RT_EndBorrow:
371373
case RT_RetainUnowned:
372374
case RT_CheckUnowned:
373375
case RT_Unknown:
@@ -441,6 +443,7 @@ static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB,
441443
break;
442444

443445
case RT_FixLifetime: // This only stops release motion. Retains can move over it.
446+
case RT_EndBorrow:
444447
break;
445448

446449
case RT_Retain:
@@ -588,6 +591,7 @@ static DtorKind analyzeDestructor(Value *P) {
588591
case RT_NoMemoryAccessed:
589592
case RT_AllocObject:
590593
case RT_FixLifetime:
594+
case RT_EndBorrow:
591595
case RT_CheckUnowned:
592596
// Skip over random instructions that don't touch memory in the caller.
593597
continue;
@@ -717,6 +721,7 @@ static bool performStoreOnlyObjectElimination(CallInst &Allocation,
717721
case RT_Release:
718722
case RT_Retain:
719723
case RT_FixLifetime:
724+
case RT_EndBorrow:
720725
case RT_CheckUnowned:
721726
// It is perfectly fine to eliminate various retains and releases of this
722727
// object: we are zapping all accesses or none.

lib/LLVMPasses/LLVMARCOpts.h

Lines changed: 30 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -25,68 +25,8 @@
2525
namespace swift {
2626

2727
enum RT_Kind {
28-
/// An instruction with this classification is known to not access (read or
29-
/// write) memory.
30-
RT_NoMemoryAccessed,
31-
32-
/// void swift_retain(SwiftHeapObject *object)
33-
RT_Retain,
34-
35-
/// void swift_retain_n(SwiftHeapObject *object)
36-
RT_RetainN,
37-
38-
/// void swift::swift_retainUnowned(HeapObject *object)
39-
RT_RetainUnowned,
40-
41-
/// void swift_checkUnowned(HeapObject *object)
42-
RT_CheckUnowned,
43-
44-
/// void swift_release(SwiftHeapObject *object)
45-
RT_Release,
46-
47-
/// void swift_release_n(SwiftHeapObject *object)
48-
RT_ReleaseN,
49-
50-
/// SwiftHeapObject *swift_allocObject(SwiftHeapMetadata *metadata,
51-
/// size_t size, size_t alignment)
52-
RT_AllocObject,
53-
54-
/// void objc_release(%objc_object* %P)
55-
RT_ObjCRelease,
56-
57-
/// %objc_object* objc_retain(%objc_object* %P)
58-
RT_ObjCRetain,
59-
60-
/// void swift_unknownRetain(%swift.refcounted* %P)
61-
RT_UnknownRetain,
62-
63-
/// void swift_unknownRetain_n(%swift.refcounted* %P)
64-
RT_UnknownRetainN,
65-
66-
/// void swift_unknownRelease(%swift.refcounted* %P)
67-
RT_UnknownRelease,
68-
69-
/// void swift_unknownRelease_n(%swift.refcounted* %P)
70-
RT_UnknownReleaseN,
71-
72-
/// void __swift_fixLifetime(%swift.refcounted* %P)
73-
RT_FixLifetime,
74-
75-
/// void swift_bridgeRetain(%swift.refcounted* %P)
76-
RT_BridgeRetain,
77-
78-
/// void swift_bridgeRetain_n(%swift.refcounted* %P)
79-
RT_BridgeRetainN,
80-
81-
/// void swift_bridgeRelease(%swift.refcounted* %P)
82-
RT_BridgeRelease,
83-
84-
/// void swift_bridgeRelease_n(%swift.refcounted* %P)
85-
RT_BridgeReleaseN,
86-
87-
/// This is not a runtime function that we support. Maybe it is not a call,
88-
/// or is a call to something we don't care about.
89-
RT_Unknown,
28+
#define KIND(Name, MemBehavior) RT_ ## Name,
29+
#include "LLVMSwift.def"
9030
};
9131

9232
/// classifyInstruction - Take a look at the specified instruction and classify
@@ -102,77 +42,38 @@ inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
10242
if (F == 0) return RT_Unknown;
10343

10444
return llvm::StringSwitch<RT_Kind>(F->getName())
105-
.Case("swift_retain", RT_Retain)
106-
.Case("swift_retain_n", RT_RetainN)
107-
.Case("swift_release", RT_Release)
108-
.Case("swift_release_n", RT_ReleaseN)
109-
.Case("swift_allocObject", RT_AllocObject)
110-
.Case("objc_release", RT_ObjCRelease)
111-
.Case("objc_retain", RT_ObjCRetain)
112-
.Case("swift_retainUnowned", RT_RetainUnowned)
113-
.Case("swift_checkUnowned", RT_CheckUnowned)
114-
.Case("swift_bridgeObjectRetain", RT_BridgeRetain)
115-
.Case("swift_bridgeObjectRetain_n", RT_BridgeRetainN)
116-
.Case("swift_bridgeObjectRelease", RT_BridgeRelease)
117-
.Case("swift_bridgeObjectRelease_n", RT_BridgeReleaseN)
118-
.Case("swift_unknownRetain", RT_UnknownRetain)
119-
.Case("swift_unknownRetain_n", RT_UnknownRetainN)
120-
.Case("swift_unknownRelease", RT_UnknownRelease)
121-
.Case("swift_unknownRelease_n", RT_UnknownReleaseN)
122-
.Case("__swift_fixLifetime", RT_FixLifetime)
45+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
46+
.Case("swift_" #TextualName, RT_ ## Name)
47+
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
48+
.Case("objc_" #TextualName, RT_ ## Name)
49+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
50+
.Case("__swift_" #TextualName, RT_ ## Name)
51+
#include "LLVMSwift.def"
52+
12353
#if defined(SWIFT_WRAPPER_PREFIX)
124-
.Case(SWIFT_WRAPPER_NAME("swift_retain"), RT_Retain)
125-
.Case(SWIFT_WRAPPER_NAME("swift_retain_n"), RT_RetainN)
126-
.Case(SWIFT_WRAPPER_NAME("swift_release"), RT_Release)
127-
.Case(SWIFT_WRAPPER_NAME("swift_release_n"), RT_ReleaseN)
128-
.Case(SWIFT_WRAPPER_NAME("swift_allocObject"), RT_AllocObject)
129-
.Case(SWIFT_WRAPPER_NAME("objc_release"), RT_ObjCRelease)
130-
.Case(SWIFT_WRAPPER_NAME("objc_retain"), RT_ObjCRetain)
131-
.Case(SWIFT_WRAPPER_NAME("swift_retainUnowned"), RT_RetainUnowned)
132-
.Case(SWIFT_WRAPPER_NAME("swift_checkUnowned"), RT_CheckUnowned)
133-
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRetain"), RT_BridgeRetain)
134-
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRetain_n"), RT_BridgeRetainN)
135-
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRelease"), RT_BridgeRelease)
136-
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRelease_n"), RT_BridgeReleaseN)
137-
.Case(SWIFT_WRAPPER_NAME("swift_unknownRetain"), RT_UnknownRetain)
138-
.Case(SWIFT_WRAPPER_NAME("swift_unknownRetain_n"), RT_UnknownRetainN)
139-
.Case(SWIFT_WRAPPER_NAME("swift_unknownRelease"), RT_UnknownRelease)
140-
.Case(SWIFT_WRAPPER_NAME("swift_unknownRelease_n"), RT_UnknownReleaseN)
54+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
55+
.Case(SWIFT_WRAPPER_NAME("swift_" #TextualName), RT_ ## Name)
56+
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
57+
.Case(SWIFT_WRAPPER_NAME("objc_" #TextualName), RT_ ## Name)
58+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
59+
#include "LLVMSwift.def"
14160
#endif
61+
14262
// Support non-atomic versions of reference counting entry points.
143-
.Case("swift_nonatomic_retain", RT_Retain)
144-
.Case("swift_nonatomic_retain_n", RT_RetainN)
145-
.Case("swift_nonatomic_release", RT_Release)
146-
.Case("swift_nonatomic_release_n", RT_ReleaseN)
147-
.Case("objc_nonatomic_release", RT_ObjCRelease)
148-
.Case("objc_nonatomic_retain", RT_ObjCRetain)
149-
.Case("swift_nonatomic_retainUnowned", RT_RetainUnowned)
150-
.Case("swift_nonatomic_checkUnowned", RT_CheckUnowned)
151-
.Case("swift_nonatomic_bridgeObjectRetain", RT_BridgeRetain)
152-
.Case("swift_nonatomic_bridgeObjectRetain_n", RT_BridgeRetainN)
153-
.Case("swift_nonatomic_bridgeObjectRelease", RT_BridgeRelease)
154-
.Case("swift_nonatomic_bridgeObjectRelease_n", RT_BridgeReleaseN)
155-
.Case("swift_nonatomic_unknownRetain", RT_UnknownRetain)
156-
.Case("swift_nonatomic_unknownRetain_n", RT_UnknownRetainN)
157-
.Case("swift_nonatomic_unknownRelease", RT_UnknownRelease)
158-
.Case("swift_nonatomic_unknownRelease_n", RT_UnknownReleaseN)
63+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
64+
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
65+
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
66+
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
67+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
68+
#include "LLVMSwift.def"
69+
15970
#if defined(SWIFT_WRAPPER_PREFIX)
160-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retain"), RT_Retain)
161-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retain_n"), RT_RetainN)
162-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_release"), RT_Release)
163-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_release_n"), RT_ReleaseN)
164-
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_release"), RT_ObjCRelease)
165-
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_retain"), RT_ObjCRetain)
166-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retainUnowned"), RT_RetainUnowned)
167-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_checkUnowned"), RT_CheckUnowned)
168-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRetain"), RT_BridgeRetain)
169-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRetain_n"), RT_BridgeRetainN)
170-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRelease"), RT_BridgeRelease)
171-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRelease_n"), RT_BridgeReleaseN)
172-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRetain"), RT_UnknownRetain)
173-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRetain_n"), RT_UnknownRetainN)
174-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRelease"), RT_UnknownRelease)
175-
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRelease_n"), RT_UnknownReleaseN)
71+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
72+
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_" #TextualName), RT_ ## Name)
73+
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
74+
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_" #TextualName), RT_ ## Name)
75+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
76+
#include "LLVMSwift.def"
17677
#endif
17778
.Default(RT_Unknown);
17879
}

lib/LLVMPasses/LLVMSwift.def

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//===--- LLVMSwift.def ----------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// KIND(Name, MemBehavior)
14+
//
15+
// This represents a specific equivalence class of LLVM instructions that have a
16+
// Name and the same MemBehavior from a ModRef perspective.
17+
//
18+
// Name - The name of the kind.
19+
// MemBehavior - One of NoModRef or ModRef.
20+
//
21+
#ifndef KIND
22+
#define KIND(Name, MemBehavior)
23+
#endif
24+
25+
// SWIFT_FUNC(Name, MemBehavior, TextualName)
26+
//
27+
// This defines a special swift function known to the optimizer that may be
28+
// present in either atomic or nonatomic form.
29+
//
30+
// Name - The name of the function
31+
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
32+
// TextualName - The name of the function in the final binary.
33+
#ifndef SWIFT_FUNC
34+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) KIND(Name, MemBehavior)
35+
#endif
36+
37+
// SWIFT_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName)
38+
//
39+
// This defines a special swift function known to the optimizer that does not
40+
// have a nonatomic form.
41+
//
42+
// Name - The name of the function
43+
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
44+
// TextualName - The name of the function in the final binary.
45+
#ifndef SWIFT_NEVER_NONATOMIC_FUNC
46+
#define SWIFT_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName) SWIFT_FUNC(Name, MemBehavior, TextualName)
47+
#endif
48+
49+
// SWIFT_INTERNAL_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName)
50+
//
51+
// This defines a special swift function known to the optimizer that does not
52+
// have a nonatomic form and has an internal prefix (i.e. '__').
53+
//
54+
// Name - The name of the function
55+
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
56+
// TextualName - The name of the function in the final binary.
57+
#ifndef SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC
58+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) SWIFT_FUNC(Name, MemBehavior, TextualName)
59+
#endif
60+
61+
// OBJC_FUNC(Name, MemBehavior, TextualName)
62+
//
63+
// This defines a special objc function known to the optimizer that may have an
64+
// atomic and nonatomic form.
65+
//
66+
// Name - The name of the function
67+
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
68+
// TextualName - The name of the function in the final binary.
69+
#ifndef OBJC_FUNC
70+
#define OBJC_FUNC(Name, MemBehavior, TextualName) KIND(Name, MemBehavior)
71+
#endif
72+
73+
/// An instruction with this classification is known to not access (read or
74+
/// write) memory.
75+
KIND(NoMemoryAccessed, NoModRef)
76+
77+
/// void swift_retain(SwiftHeapObject *object)
78+
SWIFT_FUNC(Retain, NoModRef, retain)
79+
80+
/// void swift_retain_n(SwiftHeapObject *object)
81+
SWIFT_FUNC(RetainN, NoModRef, retain_n)
82+
83+
/// void swift::swift_retainUnowned(HeapObject *object)
84+
SWIFT_FUNC(RetainUnowned, NoModRef, retainUnowned)
85+
86+
/// void swift_checkUnowned(HeapObject *object)
87+
SWIFT_FUNC(CheckUnowned, NoModRef, checkUnowned)
88+
89+
/// void swift_release(SwiftHeapObject *object)
90+
SWIFT_FUNC(Release, ModRef, release)
91+
92+
/// void swift_release_n(SwiftHeapObject *object)
93+
SWIFT_FUNC(ReleaseN, ModRef, release_n)
94+
95+
/// SwiftHeapObject *swift_allocObject(SwiftHeapMetadata *metadata,
96+
/// size_t size, size_t alignment)
97+
SWIFT_NEVER_NONATOMIC_FUNC(AllocObject, NoModRef, allocObject)
98+
99+
/// void objc_release(%objc_object* %P)
100+
OBJC_FUNC(ObjCRelease, ModRef, release)
101+
102+
/// %objc_object* objc_retain(%objc_object* %P)
103+
OBJC_FUNC(ObjCRetain, NoModRef, retain)
104+
105+
/// void swift_unknownRetain(%swift.refcounted* %P)
106+
SWIFT_FUNC(UnknownRetain, NoModRef, unknownRetain)
107+
108+
/// void swift_unknownRetain_n(%swift.refcounted* %P)
109+
SWIFT_FUNC(UnknownRetainN, NoModRef, unknownRetain_n)
110+
111+
/// void swift_unknownRelease(%swift.refcounted* %P)
112+
SWIFT_FUNC(UnknownRelease, ModRef, unknownRelease)
113+
114+
/// void swift_unknownRelease_n(%swift.refcounted* %P)
115+
SWIFT_FUNC(UnknownReleaseN, ModRef, unknownRelease_n)
116+
117+
/// void __swift_fixLifetime(%swift.refcounted* %P)
118+
SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(FixLifetime, NoModRef, fixLifetime)
119+
120+
/// void swift_bridgeObjectRetain(%swift.refcounted* %P)
121+
SWIFT_FUNC(BridgeRetain, NoModRef, bridgeObjectRetain)
122+
123+
/// void swift_bridgeObjectRetain_n(%swift.refcounted* %P)
124+
SWIFT_FUNC(BridgeRetainN, NoModRef, bridgeObjectRetain_n)
125+
126+
/// void swift_bridgeObjectRelease(%swift.refcounted* %P)
127+
SWIFT_FUNC(BridgeRelease, ModRef, bridgeObjectRelease)
128+
129+
/// void swift_bridgeObjectRelease_n(%swift.refcounted* %P)
130+
SWIFT_FUNC(BridgeReleaseN, ModRef, bridgeObjectRelease_n)
131+
132+
/// borrow source is the value that was borrowed from. borrow_dest is the
133+
/// borrowed ref.
134+
///
135+
/// TODO: We may want to communicate to the optimizer that this does not have
136+
/// global effects.
137+
///
138+
/// void __swift_endBorrow(i8* %borrow_source, i8* %borrow_dest)
139+
SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(EndBorrow, ModRef, endBorrow)
140+
141+
/// This is not a runtime function that we support. Maybe it is not a call,
142+
/// or is a call to something we don't care about.
143+
KIND(Unknown, ModRef)
144+
145+
#undef OBJC_NEVER_NONATOMIC_FUNC
146+
#undef SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC
147+
#undef SWIFT_NEVER_NONATOMIC_FUNC
148+
#undef OBJC_FUNC
149+
#undef SWIFT_FUNC
150+
#undef KIND

0 commit comments

Comments
 (0)