Skip to content

Commit 30bd7bb

Browse files
committed
Merge pull request #1890 from aschwaighofer/unsafe_guaranteed_prototype
Add _withUnsafeGuaranteedRef to Unmanaged
2 parents e86cdba + d454c93 commit 30bd7bb

File tree

13 files changed

+744
-3
lines changed

13 files changed

+744
-3
lines changed

docs/SIL.rst

+30
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,36 @@ Performs a copy of an Objective-C block. Unlike retains of other
24972497
reference-counted types, this can produce a different value from the operand
24982498
if the block is copied from the stack to the heap.
24992499

2500+
builtin "unsafeGuaranteed"
2501+
```````````````````````````
2502+
2503+
::
2504+
2505+
sil-instruction := 'builtin' '"unsafeGuaranteed"' '<' sil-type '>' '(' sil-operand')' ':' sil-type
2506+
2507+
%1 = builtin "unsafeGuaranteed"<T>(%0 : $T) : ($T, Builtin.Int1)
2508+
// $T must be of AnyObject type.
2509+
2510+
Asserts that there exists another reference of the value ``%0`` for the scope
2511+
delinated by the call of this builtin up to the first call of a ``builtin
2512+
"unsafeGuaranteedEnd"`` instruction that uses the second element ``%1.1`` of the
2513+
returned value. If no such instruction can be found nothing can be assumed. This
2514+
assertions holds for uses of the first tuple element of the returned value
2515+
``%1.0`` within this scope. The returned reference value equals the input
2516+
``%0``.
2517+
2518+
builtin "unsafeGuaranteedEnd"
2519+
```````````````````````````
2520+
2521+
::
2522+
2523+
sil-instruction := 'builtin' '"unsafeGuaranteedEnd"' '(' sil-operand')'
2524+
2525+
%1 = builtin "unsafeGuaranteedEnd"(%0 : $Builtin.Int1)
2526+
// $T must be of AnyObject type.
2527+
2528+
Ends the scope for the ``builtin "unsafeGuaranteed"`` instruction.
2529+
25002530
Literals
25012531
~~~~~~~~
25022532

include/swift/AST/Builtins.def

+6
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ BUILTIN_MISC_OPERATION(CopyArray, "copyArray", "", Special)
434434
BUILTIN_MISC_OPERATION(TakeArrayFrontToBack, "takeArrayFrontToBack", "", Special)
435435
BUILTIN_MISC_OPERATION(TakeArrayBackToFront, "takeArrayBackToFront", "", Special)
436436

437+
// unsafeGuaranteed has type <T: AnyObject> T -> (T, Builtin.Int8)
438+
BUILTIN_MISC_OPERATION(UnsafeGuaranteed, "unsafeGuaranteed", "", Special)
439+
440+
// unsafeGuaranteedEnd has type (Builtin.Int8) -> ()
441+
BUILTIN_MISC_OPERATION(UnsafeGuaranteedEnd, "unsafeGuaranteedEnd", "", Special)
442+
437443
#undef BUILTIN_MISC_OPERATION
438444

439445
// BUILTIN_TYPE_TRAIT_OPERATION - Compile-time type trait operations.

include/swift/SILOptimizer/PassManager/Passes.def

+3
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ PASS(StripDebugInfo, "strip-debug-info",
212212
"Strip debug info")
213213
PASS(SwiftArrayOpts, "array-specialize",
214214
"Specialize arrays")
215+
PASS(UnsafeGuaranteedPeephole, "unsafe-guaranteed-peephole",
216+
"Peephole retain/release removal for regions denoted by "
217+
"Builtin.unsafeGuaranteed")
215218
PASS(UsePrespecialized, "use-prespecialized",
216219
"Use pre-specialized functions")
217220
PASS_RANGE(AllPasses, AADumper, UsePrespecialized)

lib/AST/Builtins.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,23 @@ static ValueDecl *getCastFromBridgeObjectOperation(ASTContext &C,
782782
}
783783
}
784784

785+
static ValueDecl *getUnsafeGuaranteed(ASTContext &C, Identifier Id) {
786+
// <T : AnyObject> T -> (T, Int8Ty)
787+
//
788+
GenericSignatureBuilder builder(C);
789+
auto T = makeGenericParam();
790+
builder.addParameter(T);
791+
Type Int8Ty = BuiltinIntegerType::get(8, C);
792+
builder.setResult(makeTuple(T, makeConcrete(Int8Ty)));
793+
return builder.build(Id);
794+
}
795+
796+
static ValueDecl *getUnsafeGuaranteedEnd(ASTContext &C, Identifier Id) {
797+
// Int8Ty -> ()
798+
Type Int8Ty = BuiltinIntegerType::get(8, C);
799+
return getBuiltinFunction(Id, { Int8Ty }, TupleType::getEmpty(C));
800+
}
801+
785802
static ValueDecl *getCastReferenceOperation(ASTContext &ctx,
786803
Identifier name) {
787804
// <T, U> T -> U
@@ -1574,10 +1591,17 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
15741591
if (Types.size() != 1) return nullptr;
15751592
return getCheckedConversionOperation(Context, Id, Types[0]);
15761593

1594+
case BuiltinValueKind::UnsafeGuaranteed:
1595+
return getUnsafeGuaranteed(Context, Id);
1596+
1597+
case BuiltinValueKind::UnsafeGuaranteedEnd:
1598+
return getUnsafeGuaranteedEnd(Context, Id);
1599+
15771600
case BuiltinValueKind::IntToFPWithOverflow:
15781601
if (Types.size() != 2) return nullptr;
15791602
return getIntToFPWithOverflowOperation(Context, Id, Types[0], Types[1]);
15801603
}
1604+
15811605
llvm_unreachable("bad builtin value!");
15821606
}
15831607

lib/IRGen/GenFunc.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -1734,6 +1734,22 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, Identifier FnId,
17341734
// Decompose the function's name into a builtin name and type list.
17351735
const BuiltinInfo &Builtin = IGF.IGM.SILMod->getBuiltinInfo(FnId);
17361736

1737+
if (Builtin.ID == BuiltinValueKind::UnsafeGuaranteedEnd) {
1738+
// Just consume the incoming argument.
1739+
assert(args.size() == 1 && "Expecting one incoming argument");
1740+
args.claimAll();
1741+
return;
1742+
}
1743+
1744+
if (Builtin.ID == BuiltinValueKind::UnsafeGuaranteed) {
1745+
// Just forward the incoming argument.
1746+
assert(args.size() == 1 && "Expecting one incoming argument");
1747+
out = std::move(args);
1748+
// This is a token.
1749+
out.add(llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0));
1750+
return;
1751+
}
1752+
17371753
// These builtins don't care about their argument:
17381754
if (Builtin.ID == BuiltinValueKind::Sizeof) {
17391755
args.claimAll();

lib/SILOptimizer/PassManager/Passes.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,12 @@ void AddSSAPasses(SILPassManager &PM, OptimizationLevelKind OpLevel) {
241241
PM.addARCSequenceOpts();
242242

243243
PM.addSimplifyCFG();
244-
// Only hoist releases very late.
245-
if (OpLevel == OptimizationLevelKind::LowLevel)
244+
if (OpLevel == OptimizationLevelKind::LowLevel) {
245+
// Remove retain/releases based on Builtin.unsafeGuaranteed
246+
PM.addUnsafeGuaranteedPeephole();
247+
// Only hoist releases very late.
246248
PM.addLateCodeMotion();
247-
else
249+
} else
248250
PM.addEarlyCodeMotion();
249251

250252
PM.addARCSequenceOpts();
@@ -369,6 +371,7 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
369371
// Remove dead code.
370372
PM.addDCE();
371373
PM.addSimplifyCFG();
374+
372375
PM.runOneIteration();
373376

374377
PM.resetAndRemoveTransformations();

lib/SILOptimizer/Transforms/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ set(TRANSFORMS_SOURCES
2525
Transforms/Sink.cpp
2626
Transforms/SpeculativeDevirtualizer.cpp
2727
Transforms/StackPromotion.cpp
28+
Transforms/UnsafeGuaranteedPeephole.cpp
2829
PARENT_SCOPE)

0 commit comments

Comments
 (0)