Skip to content

EndBorrow support in LLVMPasses #5332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/LLVMPasses/LLVMARCContract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,10 @@ bool SwiftARCContractImpl::run() {
case RT_UnknownReleaseN:
case RT_BridgeReleaseN:
llvm_unreachable("These are only created by LLVMARCContract !");
// Delete all fix lifetime instructions. After llvm-ir they have no use
// and show up as calls in the final binary.
// Delete all fix lifetime and end borrow instructions. After llvm-ir they
// have no use and show up as calls in the final binary.
case RT_FixLifetime:
case RT_EndBorrow:
Inst.eraseFromParent();
++NumNoopDeleted;
continue;
Expand Down
5 changes: 5 additions & 0 deletions lib/LLVMPasses/LLVMARCOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B,
case RT_BridgeRelease:
case RT_AllocObject:
case RT_FixLifetime:
case RT_EndBorrow:
case RT_NoMemoryAccessed:
case RT_RetainUnowned:
case RT_CheckUnowned:
Expand Down Expand Up @@ -368,6 +369,7 @@ static bool performLocalReleaseMotion(CallInst &Release, BasicBlock &BB,
}

case RT_FixLifetime:
case RT_EndBorrow:
case RT_RetainUnowned:
case RT_CheckUnowned:
case RT_Unknown:
Expand Down Expand Up @@ -441,6 +443,7 @@ static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB,
break;

case RT_FixLifetime: // This only stops release motion. Retains can move over it.
case RT_EndBorrow:
break;

case RT_Retain:
Expand Down Expand Up @@ -588,6 +591,7 @@ static DtorKind analyzeDestructor(Value *P) {
case RT_NoMemoryAccessed:
case RT_AllocObject:
case RT_FixLifetime:
case RT_EndBorrow:
case RT_CheckUnowned:
// Skip over random instructions that don't touch memory in the caller.
continue;
Expand Down Expand Up @@ -717,6 +721,7 @@ static bool performStoreOnlyObjectElimination(CallInst &Allocation,
case RT_Release:
case RT_Retain:
case RT_FixLifetime:
case RT_EndBorrow:
case RT_CheckUnowned:
// It is perfectly fine to eliminate various retains and releases of this
// object: we are zapping all accesses or none.
Expand Down
159 changes: 30 additions & 129 deletions lib/LLVMPasses/LLVMARCOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,68 +25,8 @@
namespace swift {

enum RT_Kind {
/// An instruction with this classification is known to not access (read or
/// write) memory.
RT_NoMemoryAccessed,

/// void swift_retain(SwiftHeapObject *object)
RT_Retain,

/// void swift_retain_n(SwiftHeapObject *object)
RT_RetainN,

/// void swift::swift_retainUnowned(HeapObject *object)
RT_RetainUnowned,

/// void swift_checkUnowned(HeapObject *object)
RT_CheckUnowned,

/// void swift_release(SwiftHeapObject *object)
RT_Release,

/// void swift_release_n(SwiftHeapObject *object)
RT_ReleaseN,

/// SwiftHeapObject *swift_allocObject(SwiftHeapMetadata *metadata,
/// size_t size, size_t alignment)
RT_AllocObject,

/// void objc_release(%objc_object* %P)
RT_ObjCRelease,

/// %objc_object* objc_retain(%objc_object* %P)
RT_ObjCRetain,

/// void swift_unknownRetain(%swift.refcounted* %P)
RT_UnknownRetain,

/// void swift_unknownRetain_n(%swift.refcounted* %P)
RT_UnknownRetainN,

/// void swift_unknownRelease(%swift.refcounted* %P)
RT_UnknownRelease,

/// void swift_unknownRelease_n(%swift.refcounted* %P)
RT_UnknownReleaseN,

/// void __swift_fixLifetime(%swift.refcounted* %P)
RT_FixLifetime,

/// void swift_bridgeRetain(%swift.refcounted* %P)
RT_BridgeRetain,

/// void swift_bridgeRetain_n(%swift.refcounted* %P)
RT_BridgeRetainN,

/// void swift_bridgeRelease(%swift.refcounted* %P)
RT_BridgeRelease,

/// void swift_bridgeRelease_n(%swift.refcounted* %P)
RT_BridgeReleaseN,

/// This is not a runtime function that we support. Maybe it is not a call,
/// or is a call to something we don't care about.
RT_Unknown,
#define KIND(Name, MemBehavior) RT_ ## Name,
#include "LLVMSwift.def"
};

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

return llvm::StringSwitch<RT_Kind>(F->getName())
.Case("swift_retain", RT_Retain)
.Case("swift_retain_n", RT_RetainN)
.Case("swift_release", RT_Release)
.Case("swift_release_n", RT_ReleaseN)
.Case("swift_allocObject", RT_AllocObject)
.Case("objc_release", RT_ObjCRelease)
.Case("objc_retain", RT_ObjCRetain)
.Case("swift_retainUnowned", RT_RetainUnowned)
.Case("swift_checkUnowned", RT_CheckUnowned)
.Case("swift_bridgeObjectRetain", RT_BridgeRetain)
.Case("swift_bridgeObjectRetain_n", RT_BridgeRetainN)
.Case("swift_bridgeObjectRelease", RT_BridgeRelease)
.Case("swift_bridgeObjectRelease_n", RT_BridgeReleaseN)
.Case("swift_unknownRetain", RT_UnknownRetain)
.Case("swift_unknownRetain_n", RT_UnknownRetainN)
.Case("swift_unknownRelease", RT_UnknownRelease)
.Case("swift_unknownRelease_n", RT_UnknownReleaseN)
.Case("__swift_fixLifetime", RT_FixLifetime)
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
.Case("swift_" #TextualName, RT_ ## Name)
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
.Case("objc_" #TextualName, RT_ ## Name)
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
.Case("__swift_" #TextualName, RT_ ## Name)
#include "LLVMSwift.def"

#if defined(SWIFT_WRAPPER_PREFIX)
.Case(SWIFT_WRAPPER_NAME("swift_retain"), RT_Retain)
.Case(SWIFT_WRAPPER_NAME("swift_retain_n"), RT_RetainN)
.Case(SWIFT_WRAPPER_NAME("swift_release"), RT_Release)
.Case(SWIFT_WRAPPER_NAME("swift_release_n"), RT_ReleaseN)
.Case(SWIFT_WRAPPER_NAME("swift_allocObject"), RT_AllocObject)
.Case(SWIFT_WRAPPER_NAME("objc_release"), RT_ObjCRelease)
.Case(SWIFT_WRAPPER_NAME("objc_retain"), RT_ObjCRetain)
.Case(SWIFT_WRAPPER_NAME("swift_retainUnowned"), RT_RetainUnowned)
.Case(SWIFT_WRAPPER_NAME("swift_checkUnowned"), RT_CheckUnowned)
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRetain"), RT_BridgeRetain)
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRetain_n"), RT_BridgeRetainN)
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRelease"), RT_BridgeRelease)
.Case(SWIFT_WRAPPER_NAME("swift_bridgeObjectRelease_n"), RT_BridgeReleaseN)
.Case(SWIFT_WRAPPER_NAME("swift_unknownRetain"), RT_UnknownRetain)
.Case(SWIFT_WRAPPER_NAME("swift_unknownRetain_n"), RT_UnknownRetainN)
.Case(SWIFT_WRAPPER_NAME("swift_unknownRelease"), RT_UnknownRelease)
.Case(SWIFT_WRAPPER_NAME("swift_unknownRelease_n"), RT_UnknownReleaseN)
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
.Case(SWIFT_WRAPPER_NAME("swift_" #TextualName), RT_ ## Name)
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
.Case(SWIFT_WRAPPER_NAME("objc_" #TextualName), RT_ ## Name)
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
#include "LLVMSwift.def"
#endif

// Support non-atomic versions of reference counting entry points.
.Case("swift_nonatomic_retain", RT_Retain)
.Case("swift_nonatomic_retain_n", RT_RetainN)
.Case("swift_nonatomic_release", RT_Release)
.Case("swift_nonatomic_release_n", RT_ReleaseN)
.Case("objc_nonatomic_release", RT_ObjCRelease)
.Case("objc_nonatomic_retain", RT_ObjCRetain)
.Case("swift_nonatomic_retainUnowned", RT_RetainUnowned)
.Case("swift_nonatomic_checkUnowned", RT_CheckUnowned)
.Case("swift_nonatomic_bridgeObjectRetain", RT_BridgeRetain)
.Case("swift_nonatomic_bridgeObjectRetain_n", RT_BridgeRetainN)
.Case("swift_nonatomic_bridgeObjectRelease", RT_BridgeRelease)
.Case("swift_nonatomic_bridgeObjectRelease_n", RT_BridgeReleaseN)
.Case("swift_nonatomic_unknownRetain", RT_UnknownRetain)
.Case("swift_nonatomic_unknownRetain_n", RT_UnknownRetainN)
.Case("swift_nonatomic_unknownRelease", RT_UnknownRelease)
.Case("swift_nonatomic_unknownRelease_n", RT_UnknownReleaseN)
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
#include "LLVMSwift.def"

#if defined(SWIFT_WRAPPER_PREFIX)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retain"), RT_Retain)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retain_n"), RT_RetainN)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_release"), RT_Release)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_release_n"), RT_ReleaseN)
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_release"), RT_ObjCRelease)
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_retain"), RT_ObjCRetain)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_retainUnowned"), RT_RetainUnowned)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_checkUnowned"), RT_CheckUnowned)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRetain"), RT_BridgeRetain)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRetain_n"), RT_BridgeRetainN)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRelease"), RT_BridgeRelease)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_bridgeObjectRelease_n"), RT_BridgeReleaseN)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRetain"), RT_UnknownRetain)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRetain_n"), RT_UnknownRetainN)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRelease"), RT_UnknownRelease)
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_unknownRelease_n"), RT_UnknownReleaseN)
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
.Case(SWIFT_WRAPPER_NAME("swift_nonatomic_" #TextualName), RT_ ## Name)
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
.Case(SWIFT_WRAPPER_NAME("objc_nonatomic_" #TextualName), RT_ ## Name)
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
#include "LLVMSwift.def"
#endif
.Default(RT_Unknown);
}
Expand Down
150 changes: 150 additions & 0 deletions lib/LLVMPasses/LLVMSwift.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//===--- LLVMSwift.def ----------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

// KIND(Name, MemBehavior)
//
// This represents a specific equivalence class of LLVM instructions that have a
// Name and the same MemBehavior from a ModRef perspective.
//
// Name - The name of the kind.
// MemBehavior - One of NoModRef or ModRef.
//
#ifndef KIND
#define KIND(Name, MemBehavior)
#endif

// SWIFT_FUNC(Name, MemBehavior, TextualName)
//
// This defines a special swift function known to the optimizer that may be
// present in either atomic or nonatomic form.
//
// Name - The name of the function
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
// TextualName - The name of the function in the final binary.
#ifndef SWIFT_FUNC
#define SWIFT_FUNC(Name, MemBehavior, TextualName) KIND(Name, MemBehavior)
#endif

// SWIFT_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName)
//
// This defines a special swift function known to the optimizer that does not
// have a nonatomic form.
//
// Name - The name of the function
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
// TextualName - The name of the function in the final binary.
#ifndef SWIFT_NEVER_NONATOMIC_FUNC
#define SWIFT_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName) SWIFT_FUNC(Name, MemBehavior, TextualName)
#endif

// SWIFT_INTERNAL_NEVER_NONATOMIC_FUNC(Name, MemBehavior, TextualName)
//
// This defines a special swift function known to the optimizer that does not
// have a nonatomic form and has an internal prefix (i.e. '__').
//
// Name - The name of the function
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
// TextualName - The name of the function in the final binary.
#ifndef SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) SWIFT_FUNC(Name, MemBehavior, TextualName)
#endif

// OBJC_FUNC(Name, MemBehavior, TextualName)
//
// This defines a special objc function known to the optimizer that may have an
// atomic and nonatomic form.
//
// Name - The name of the function
// MemBehavior - The MemBehavior of the instruction that can be known at compile time
// TextualName - The name of the function in the final binary.
#ifndef OBJC_FUNC
#define OBJC_FUNC(Name, MemBehavior, TextualName) KIND(Name, MemBehavior)
#endif

/// An instruction with this classification is known to not access (read or
/// write) memory.
KIND(NoMemoryAccessed, NoModRef)

/// void swift_retain(SwiftHeapObject *object)
SWIFT_FUNC(Retain, NoModRef, retain)

/// void swift_retain_n(SwiftHeapObject *object)
SWIFT_FUNC(RetainN, NoModRef, retain_n)

/// void swift::swift_retainUnowned(HeapObject *object)
SWIFT_FUNC(RetainUnowned, NoModRef, retainUnowned)

/// void swift_checkUnowned(HeapObject *object)
SWIFT_FUNC(CheckUnowned, NoModRef, checkUnowned)

/// void swift_release(SwiftHeapObject *object)
SWIFT_FUNC(Release, ModRef, release)

/// void swift_release_n(SwiftHeapObject *object)
SWIFT_FUNC(ReleaseN, ModRef, release_n)

/// SwiftHeapObject *swift_allocObject(SwiftHeapMetadata *metadata,
/// size_t size, size_t alignment)
SWIFT_NEVER_NONATOMIC_FUNC(AllocObject, NoModRef, allocObject)

/// void objc_release(%objc_object* %P)
OBJC_FUNC(ObjCRelease, ModRef, release)

/// %objc_object* objc_retain(%objc_object* %P)
OBJC_FUNC(ObjCRetain, NoModRef, retain)

/// void swift_unknownRetain(%swift.refcounted* %P)
SWIFT_FUNC(UnknownRetain, NoModRef, unknownRetain)

/// void swift_unknownRetain_n(%swift.refcounted* %P)
SWIFT_FUNC(UnknownRetainN, NoModRef, unknownRetain_n)

/// void swift_unknownRelease(%swift.refcounted* %P)
SWIFT_FUNC(UnknownRelease, ModRef, unknownRelease)

/// void swift_unknownRelease_n(%swift.refcounted* %P)
SWIFT_FUNC(UnknownReleaseN, ModRef, unknownRelease_n)

/// void __swift_fixLifetime(%swift.refcounted* %P)
SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(FixLifetime, NoModRef, fixLifetime)

/// void swift_bridgeObjectRetain(%swift.refcounted* %P)
SWIFT_FUNC(BridgeRetain, NoModRef, bridgeObjectRetain)

/// void swift_bridgeObjectRetain_n(%swift.refcounted* %P)
SWIFT_FUNC(BridgeRetainN, NoModRef, bridgeObjectRetain_n)

/// void swift_bridgeObjectRelease(%swift.refcounted* %P)
SWIFT_FUNC(BridgeRelease, ModRef, bridgeObjectRelease)

/// void swift_bridgeObjectRelease_n(%swift.refcounted* %P)
SWIFT_FUNC(BridgeReleaseN, ModRef, bridgeObjectRelease_n)

/// borrow source is the value that was borrowed from. borrow_dest is the
/// borrowed ref.
///
/// TODO: We may want to communicate to the optimizer that this does not have
/// global effects.
///
/// void __swift_endBorrow(i8* %borrow_source, i8* %borrow_dest)
SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(EndBorrow, ModRef, endBorrow)

/// This is not a runtime function that we support. Maybe it is not a call,
/// or is a call to something we don't care about.
KIND(Unknown, ModRef)

#undef OBJC_NEVER_NONATOMIC_FUNC
#undef SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC
#undef SWIFT_NEVER_NONATOMIC_FUNC
#undef OBJC_FUNC
#undef SWIFT_FUNC
#undef KIND
Loading