Skip to content

Commit 2403e56

Browse files
committed
SIL: new "array.end_mutation" and "array.finalize_intrinsic" array semantics
Used to "finalize" an array literal. It's not used, yet. So this is NFC. Also handle the "array.finalize_intrinsic" function in various array specific optimizations.
1 parent 01465d9 commit 2403e56

File tree

11 files changed

+98
-39
lines changed

11 files changed

+98
-39
lines changed

include/swift/AST/SemanticAttrs.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ SEMANTICS_ATTR(ARRAY_GET_ELEMENT_ADDRESS, "array.get_element_address")
5151
SEMANTICS_ATTR(ARRAY_INIT, "array.init")
5252
SEMANTICS_ATTR(ARRAY_INIT_EMPTY, "array.init.empty")
5353
SEMANTICS_ATTR(ARRAY_MAKE_MUTABLE, "array.make_mutable")
54+
SEMANTICS_ATTR(ARRAY_END_MUTATION, "array.end_mutation")
5455
SEMANTICS_ATTR(ARRAY_MUTATE_UNKNOWN, "array.mutate_unknown")
5556
SEMANTICS_ATTR(ARRAY_PROPS_IS_NATIVE_TYPE_CHECKED, "array.props.isNativeTypeChecked")
5657
SEMANTICS_ATTR(ARRAY_RESERVE_CAPACITY_FOR_APPEND, "array.reserve_capacity_for_append")

include/swift/SILOptimizer/Analysis/ArraySemantic.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class ArrayCallKind {
3131
kGetElement,
3232
kGetElementAddress,
3333
kMakeMutable,
34+
kEndMutation,
3435
kMutateUnknown,
3536
kReserveCapacityForAppend,
3637
kWithUnsafeMutableBufferPointer,
@@ -42,7 +43,8 @@ enum class ArrayCallKind {
4243
// before this comment.
4344
kArrayInit,
4445
kArrayUninitialized,
45-
kArrayUninitializedIntrinsic
46+
kArrayUninitializedIntrinsic,
47+
kArrayFinalizeIntrinsic
4648
};
4749

4850
/// Return true is the given function is an array semantics call.
@@ -78,6 +80,8 @@ class ArraySemanticsCall {
7880
ArraySemanticsCall(SILValue V, StringRef semanticName,
7981
bool matchPartialName);
8082

83+
ArraySemanticsCall() : SemanticsCall(nullptr) {}
84+
8185
/// Can we hoist this call.
8286
bool canHoist(SILInstruction *To, DominanceInfo *DT) const;
8387

lib/SILOptimizer/Analysis/ArraySemantic.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ ArrayCallKind swift::getArraySemanticsKind(SILFunction *f) {
3333
.StartsWith("array.init", ArrayCallKind::kArrayInit)
3434
.Case("array.uninitialized", ArrayCallKind::kArrayUninitialized)
3535
.Case("array.uninitialized_intrinsic", ArrayCallKind::kArrayUninitializedIntrinsic)
36+
.Case("array.finalize_intrinsic", ArrayCallKind::kArrayFinalizeIntrinsic)
3637
.Case("array.check_subscript", ArrayCallKind::kCheckSubscript)
3738
.Case("array.check_index", ArrayCallKind::kCheckIndex)
3839
.Case("array.get_count", ArrayCallKind::kGetCount)
3940
.Case("array.get_capacity", ArrayCallKind::kGetCapacity)
4041
.Case("array.get_element", ArrayCallKind::kGetElement)
4142
.Case("array.make_mutable", ArrayCallKind::kMakeMutable)
43+
.Case("array.end_mutation", ArrayCallKind::kEndMutation)
4244
.Case("array.get_element_address",
4345
ArrayCallKind::kGetElementAddress)
4446
.Case("array.mutate_unknown", ArrayCallKind::kMutateUnknown)
@@ -342,9 +344,9 @@ bool swift::ArraySemanticsCall::canHoist(SILInstruction *InsertBefore,
342344
return canHoistArrayArgument(SemanticsCall, getSelf(), InsertBefore, DT);
343345
}
344346

345-
case ArrayCallKind::kMakeMutable: {
347+
case ArrayCallKind::kMakeMutable:
348+
case ArrayCallKind::kEndMutation:
346349
return canHoistArrayArgument(SemanticsCall, getSelf(), InsertBefore, DT);
347-
}
348350
} // End switch.
349351

350352
return false;
@@ -492,8 +494,8 @@ ApplyInst *swift::ArraySemanticsCall::hoistOrCopy(SILInstruction *InsertBefore,
492494
return Call;
493495
}
494496

495-
case ArrayCallKind::kMakeMutable: {
496-
assert(!LeaveOriginal && "Copying not yet implemented");
497+
case ArrayCallKind::kMakeMutable:
498+
case ArrayCallKind::kEndMutation: {
497499
// Hoist the call.
498500
auto Call = hoistOrCopyCall(SemanticsCall, InsertBefore, LeaveOriginal, DT);
499501
return Call;
@@ -569,6 +571,7 @@ bool swift::ArraySemanticsCall::doesNotChangeArray() const {
569571
case ArrayCallKind::kGetCount:
570572
case ArrayCallKind::kGetCapacity:
571573
case ArrayCallKind::kGetElement:
574+
case ArrayCallKind::kEndMutation:
572575
return true;
573576
}
574577
}

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ static bool isNonMutatingArraySemanticCall(SILInstruction *Inst) {
288288
case ArrayCallKind::kGetCapacity:
289289
case ArrayCallKind::kGetElement:
290290
case ArrayCallKind::kGetElementAddress:
291+
case ArrayCallKind::kEndMutation:
291292
return true;
292293
case ArrayCallKind::kMakeMutable:
293294
case ArrayCallKind::kMutateUnknown:
@@ -296,6 +297,7 @@ static bool isNonMutatingArraySemanticCall(SILInstruction *Inst) {
296297
case ArrayCallKind::kArrayInit:
297298
case ArrayCallKind::kArrayUninitialized:
298299
case ArrayCallKind::kArrayUninitializedIntrinsic:
300+
case ArrayCallKind::kArrayFinalizeIntrinsic:
299301
case ArrayCallKind::kAppendContentsOf:
300302
case ArrayCallKind::kAppendElement:
301303
return false;

lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,24 @@ bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
135135
}
136136

137137
// Check array semantic calls.
138-
if (auto apply = dyn_cast<ApplyInst>(User)) {
138+
if (auto *apply = dyn_cast<ApplyInst>(User)) {
139139
ArraySemanticsCall ArrayOp(apply);
140-
if (ArrayOp && ArrayOp.doesNotChangeArray()) {
141-
if (ArrayOp.getKind() == ArrayCallKind::kGetCount)
140+
switch (ArrayOp.getKind()) {
141+
case ArrayCallKind::kNone:
142+
return false;
143+
case ArrayCallKind::kGetCount:
142144
CountCalls.insert(ArrayOp);
143-
continue;
145+
break;
146+
case ArrayCallKind::kArrayFinalizeIntrinsic:
147+
if (!recursivelyCollectUses(apply))
148+
return false;
149+
break;
150+
default:
151+
if (!ArrayOp.doesNotChangeArray())
152+
return false;
153+
break;
144154
}
155+
continue;
145156
}
146157

147158
// An operation that escapes or modifies the array value.

lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,20 +138,24 @@ bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
138138

139139
// Check array semantic calls.
140140
ArraySemanticsCall ArrayOp(User);
141-
if (ArrayOp) {
142-
if (ArrayOp.getKind() == ArrayCallKind::kAppendContentsOf) {
141+
switch (ArrayOp.getKind()) {
142+
case ArrayCallKind::kNone:
143+
return false;
144+
case ArrayCallKind::kAppendContentsOf:
143145
AppendContentsOfCalls.push_back(ArrayOp);
144-
continue;
145-
} else if (ArrayOp.getKind() == ArrayCallKind::kGetElement) {
146+
break;
147+
case ArrayCallKind::kGetElement:
146148
GetElementCalls.insert(ArrayOp);
147-
continue;
148-
} else if (ArrayOp.doesNotChangeArray()) {
149-
continue;
150-
}
149+
break;
150+
case ArrayCallKind::kArrayFinalizeIntrinsic:
151+
if (!recursivelyCollectUses(cast<SingleValueInstruction>(User)))
152+
return false;
153+
break;
154+
default:
155+
if (ArrayOp.doesNotChangeArray())
156+
break;
157+
return false;
151158
}
152-
153-
// An operation that escapes or modifies the array value.
154-
return false;
155159
}
156160
return true;
157161
}

lib/SILOptimizer/Transforms/DeadObjectElimination.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,13 @@ recursivelyCollectInteriorUses(ValueBase *DefInst,
445445
continue;
446446
}
447447
// Recursively follow projections.
448-
if (auto ProjInst = dyn_cast<SingleValueInstruction>(User)) {
449-
ProjectionIndex PI(ProjInst);
448+
if (auto *svi = dyn_cast<SingleValueInstruction>(User)) {
449+
ProjectionIndex PI(svi);
450450
if (PI.isValid()) {
451451
IndexTrieNode *ProjAddrNode = AddressNode;
452452
bool ProjInteriorAddr = IsInteriorAddress;
453-
if (Projection::isAddressProjection(ProjInst)) {
454-
if (isa<IndexAddrInst>(ProjInst)) {
453+
if (Projection::isAddressProjection(svi)) {
454+
if (isa<IndexAddrInst>(svi)) {
455455
// Don't support indexing within an interior address.
456456
if (IsInteriorAddress)
457457
return false;
@@ -466,13 +466,19 @@ recursivelyCollectInteriorUses(ValueBase *DefInst,
466466
// Don't expect to extract values once we've taken an address.
467467
return false;
468468
}
469-
if (!recursivelyCollectInteriorUses(ProjInst,
469+
if (!recursivelyCollectInteriorUses(svi,
470470
ProjAddrNode->getChild(PI.Index),
471471
ProjInteriorAddr)) {
472472
return false;
473473
}
474474
continue;
475475
}
476+
ArraySemanticsCall AS(svi);
477+
if (AS.getKind() == swift::ArrayCallKind::kArrayFinalizeIntrinsic) {
478+
if (!recursivelyCollectInteriorUses(svi, AddressNode, IsInteriorAddress))
479+
return false;
480+
continue;
481+
}
476482
}
477483
// Otherwise bail.
478484
LLVM_DEBUG(llvm::dbgs() << " Found an escaping use: " << *User);

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ enum class WellKnownFunction {
4545
ArrayInitEmpty,
4646
// Array._allocateUninitializedArray
4747
AllocateUninitializedArray,
48+
// Array._endMutation
49+
EndArrayMutation,
4850
// Array.append(_:)
4951
ArrayAppendElement,
5052
// String.init()
@@ -71,6 +73,8 @@ static llvm::Optional<WellKnownFunction> classifyFunction(SILFunction *fn) {
7173
return WellKnownFunction::ArrayInitEmpty;
7274
if (fn->hasSemanticsAttr(semantics::ARRAY_UNINITIALIZED_INTRINSIC))
7375
return WellKnownFunction::AllocateUninitializedArray;
76+
if (fn->hasSemanticsAttr(semantics::ARRAY_END_MUTATION))
77+
return WellKnownFunction::EndArrayMutation;
7478
if (fn->hasSemanticsAttr(semantics::ARRAY_APPEND_ELEMENT))
7579
return WellKnownFunction::ArrayAppendElement;
7680
if (fn->hasSemanticsAttr(semantics::STRING_INIT_EMPTY))
@@ -946,6 +950,17 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply,
946950
resultType, allocator));
947951
return None;
948952
}
953+
case WellKnownFunction::EndArrayMutation: {
954+
// This function has the following signature in SIL:
955+
// (@inout Array<Element>) -> ()
956+
assert(conventions.getNumParameters() == 1 &&
957+
conventions.getNumDirectSILResults() == 0 &&
958+
conventions.getNumIndirectSILResults() == 0 &&
959+
"unexpected Array._endMutation() signature");
960+
961+
// _endMutation is a no-op.
962+
return None;
963+
}
949964
case WellKnownFunction::ArrayAppendElement: {
950965
// This function has the following signature in SIL:
951966
// (@in Element, @inout Array<Element>) -> ()

test/SILOptimizer/array_count_propagation.sil

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ sil [_semantics "array.uninitialized"] @adoptStorage : $@convention(thin) (@owne
2929
sil [_semantics "array.get_count"] @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
3030
sil [_semantics "array.get_element"] @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
3131
sil [_semantics "array.uninitialized"] @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
32+
sil [_semantics "array.finalize_intrinsic"] @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
3233
sil [_semantics "array.init"] @initRepeatedValueCount : $@convention(thin) (@in MyInt, MyInt, @thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
3334
sil [_semantics "array.init"] @initEmpty : $@convention(thin) (@thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
3435

@@ -50,9 +51,11 @@ bb0:
5051
%7 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 0
5152
%8 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 1
5253
debug_value %7 : $MyArray<MyInt>
54+
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
55+
%a = apply %f(%7) : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
5356
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
54-
%10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
55-
%12 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
57+
%10 = apply %9(%a) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
58+
%12 = struct_extract %a : $MyArray<MyInt>, #MyArray._buffer
5659
%13 = struct_extract %12 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
5760
%14 = struct_extract %13 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
5861
strong_release %14 : $Builtin.BridgeObject

test/SILOptimizer/array_element_propagation.sil

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ sil [_semantics "array.get_element"] @getElement2 : $@convention(method) (MyInt,
3434
sil @unknown_array_use : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
3535
sil [_semantics "array.uninitialized"] @arrayAdoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin Array<MyInt>.Type) -> @owned (Array<MyInt>, UnsafeMutablePointer<MyInt>)
3636
sil @arrayInit : $@convention(method) (@thin Array<MyInt>.Type) -> @owned Array<MyInt>
37+
sil [_semantics "array.finalize_intrinsic"] @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
3738
sil [_semantics "array.append_contentsOf"] @arrayAppendContentsOf : $@convention(method) (@owned Array<MyInt>, @inout Array<MyInt>) -> ()
3839

3940
// CHECK-LABEL: sil @propagate01
@@ -88,35 +89,37 @@ sil @propagate01 : $@convention(thin) () -> () {
8889
%19 = integer_literal $Builtin.Int64, 2
8990
%20 = struct $MyInt (%19 : $Builtin.Int64)
9091
store %20 to %18 : $*MyInt
91-
%23 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
92+
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
93+
%a = apply %f(%7) : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
94+
%23 = struct_extract %a : $MyArray<MyInt>, #MyArray._buffer
9295
%24 = struct_extract %23 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
9396
%25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
9497
%26 = alloc_stack $MyInt
95-
debug_value %7 : $MyArray<MyInt>
98+
debug_value %a : $MyArray<MyInt>
9699
%27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
97-
%28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
100+
%28 = apply %27(%a) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
98101
debug_value %28 : $MyBool // id: %104
99102
%29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
100-
%30 = apply %29(%12, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
103+
%30 = apply %29(%12, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
101104
debug_value %30 : $_MyDependenceToken
102105
%31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
103-
%32 = apply %31(%26, %12, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
106+
%32 = apply %31(%26, %12, %28, %30, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
104107
%35 = alloc_stack $MyInt
105108
debug_value %16 : $MyInt
106-
debug_value %7 : $MyArray<MyInt>
109+
debug_value %a : $MyArray<MyInt>
107110
debug_value %28 : $MyBool
108111
strong_retain %25 : $Builtin.BridgeObject
109-
%36 = apply %29(%16, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
112+
%36 = apply %29(%16, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
110113
debug_value %36 : $_MyDependenceToken
111-
%37 = apply %31(%35, %16, %28, %36, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
114+
%37 = apply %31(%35, %16, %28, %36, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
112115
strong_release %25 : $Builtin.BridgeObject
113116
%44 = alloc_stack $MyInt
114-
debug_value %7 : $MyArray<MyInt>
117+
debug_value %a : $MyArray<MyInt>
115118
debug_value %28 : $MyBool
116119
strong_retain %25 : $Builtin.BridgeObject
117-
%45 = apply %29(%20, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
120+
%45 = apply %29(%20, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
118121
debug_value %45 : $_MyDependenceToken
119-
%46 = apply %31(%44, %20, %28, %45, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
122+
%46 = apply %31(%44, %20, %28, %45, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
120123
strong_release %25 : $Builtin.BridgeObject
121124
%52 = tuple ()
122125
dealloc_stack %44 : $*MyInt

0 commit comments

Comments
 (0)