Skip to content

Commit de557ca

Browse files
committed
Optimizer: support the new array literal initialization pattern in the ArrayCountPropagation pass
1 parent 71381fa commit de557ca

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ArrayAllocation {
4949
SILValue ArrayValue;
5050
/// The count of the allocated array.
5151
SILValue ArrayCount;
52+
bool isUninitialized = false;
5253
// The calls to Array.count that use this array allocation.
5354
llvm::SmallSetVector<ApplyInst *, 16> CountCalls;
5455
// Array count calls that are dead as a consequence of propagating the count
@@ -61,7 +62,7 @@ class ArrayAllocation {
6162
bool propagate();
6263
bool isInitializationWithKnownCount();
6364
bool analyzeArrayValueUses();
64-
bool recursivelyCollectUses(ValueBase *Def);
65+
bool recursivelyCollectUses(ValueBase *Def, bool isInInitSection);
6566
bool propagateCountToUsers();
6667

6768
public:
@@ -100,8 +101,10 @@ bool ArrayAllocation::isInitializationWithKnownCount() {
100101
ArraySemanticsCall Uninitialized(Alloc, "array.uninitialized");
101102
if (Uninitialized &&
102103
(ArrayCount = Uninitialized.getInitializationCount()) &&
103-
(ArrayValue = Uninitialized.getArrayValue()))
104+
(ArrayValue = Uninitialized.getArrayValue())) {
105+
isUninitialized = true;
104106
return true;
107+
}
105108

106109
ArraySemanticsCall Init(Alloc, "array.init", /*matchPartialName*/true);
107110
if (Init &&
@@ -115,19 +118,30 @@ bool ArrayAllocation::isInitializationWithKnownCount() {
115118
/// Collect all getCount users and check that there are no escapes or uses that
116119
/// could change the array value.
117120
bool ArrayAllocation::analyzeArrayValueUses() {
118-
return recursivelyCollectUses(ArrayValue);
121+
return recursivelyCollectUses(ArrayValue, /*isInInitSection=*/ isUninitialized);
119122
}
120123

121124
/// Recursively look at all uses of this definition. Abort if the array value
122125
/// could escape or be changed. Collect all uses that are calls to array.count.
123-
bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
126+
bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def, bool isInInitSection) {
124127
for (auto *Opd : Def->getUses()) {
125128
auto *User = Opd->getUser();
126129
// Ignore reference counting and debug instructions.
127130
if (isa<RefCountingInst>(User) || isa<DestroyValueInst>(User) ||
128131
isa<DebugValueInst>(User))
129132
continue;
130133

134+
if (BeginBorrowInst *beginBorrow = dyn_cast<BeginBorrowInst>(User)) {
135+
if (isInInitSection) {
136+
// This begin_borrow is used to get the element addresses for array
137+
// initialization. This is happening between the allocate-uninitialized
138+
// and the finalize-array intrinsic calls. We can igore this.
139+
continue;
140+
}
141+
if (!recursivelyCollectUses(beginBorrow, isInInitSection))
142+
return false;
143+
}
144+
131145
if (auto mdi = MarkDependenceInstruction(User)) {
132146
if (Def == mdi.getBase()) {
133147
continue;
@@ -136,7 +150,7 @@ bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
136150

137151
// Array value projection.
138152
if (auto *SEI = dyn_cast<StructExtractInst>(User)) {
139-
if (!recursivelyCollectUses(SEI))
153+
if (!recursivelyCollectUses(SEI, isInInitSection))
140154
return false;
141155
continue;
142156
}
@@ -151,7 +165,7 @@ bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
151165
CountCalls.insert(ArrayOp);
152166
break;
153167
case ArrayCallKind::kArrayFinalizeIntrinsic:
154-
if (!recursivelyCollectUses(apply))
168+
if (!recursivelyCollectUses(apply, /*isInInitSection=*/ false))
155169
return false;
156170
break;
157171
default:

test/SILOptimizer/array_count_propagation_ossa.sil

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ struct MyInt {
1111

1212
struct MyBool {}
1313

14+
class Storage {}
15+
1416
struct _MyBridgeStorage {
1517
@_hasStorage var rawValue : Builtin.BridgeObject
1618
}
@@ -51,7 +53,13 @@ bb0:
5153
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
5254
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
5355
(%7, %8a) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
54-
%8 = mark_dependence %8a : $UnsafeMutablePointer<MyInt> on %7 : $MyArray<MyInt>
56+
%i1 = begin_borrow %7
57+
%i2 = struct_extract %i1, #MyArray._buffer
58+
%i3 = struct_extract %i2, #_MyArrayBuffer._storage
59+
%i4 = struct_extract %i3, #_MyBridgeStorage.rawValue
60+
%i5 = unchecked_ref_cast %i4 to $Storage
61+
%i6 = ref_tail_addr %i5, $MyInt
62+
end_borrow %i1
5563
debug_value %7 : $MyArray<MyInt>
5664
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
5765
%a = apply %f(%7) : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
@@ -75,7 +83,13 @@ bb0:
7583
%5 = function_ref @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
7684
%6 = apply %5(%3, %4) : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
7785
(%7, %8a) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
78-
%8 = mark_dependence %8a : $UnsafeMutablePointer<MyInt> on %7 : $MyArray<MyInt>
86+
%i1 = begin_borrow %7
87+
%i2 = struct_extract %i1, #MyArray._buffer
88+
%i3 = struct_extract %i2, #_MyArrayBuffer._storage
89+
%i4 = struct_extract %i3, #_MyBridgeStorage.rawValue
90+
%i5 = unchecked_ref_cast %i4 to $Storage
91+
%i6 = ref_tail_addr %i5, $MyInt
92+
end_borrow %i1
7993
debug_value %7 : $MyArray<MyInt>
8094
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
8195
%10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
@@ -131,7 +145,13 @@ bb0:
131145
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
132146
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
133147
(%7, %8a) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
134-
%8 = mark_dependence %8a : $UnsafeMutablePointer<MyInt> on %7 : $MyArray<MyInt>
148+
%i1 = begin_borrow %7
149+
%i2 = struct_extract %i1, #MyArray._buffer
150+
%i3 = struct_extract %i2, #_MyArrayBuffer._storage
151+
%i4 = struct_extract %i3, #_MyBridgeStorage.rawValue
152+
%i5 = unchecked_ref_cast %i4 to $Storage
153+
%i6 = ref_tail_addr %i5, $MyInt
154+
end_borrow %i1
135155
%copy7 = copy_value %7 : $MyArray<MyInt>
136156
debug_value %7 : $MyArray<MyInt>
137157
store %7 to [init] %15 : $*MyArray<MyInt>
@@ -159,7 +179,13 @@ bb0:
159179
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
160180
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
161181
(%7, %8a) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
162-
%8 = mark_dependence %8a : $UnsafeMutablePointer<MyInt> on %7 : $MyArray<MyInt>
182+
%i1 = begin_borrow %7
183+
%i2 = struct_extract %i1, #MyArray._buffer
184+
%i3 = struct_extract %i2, #_MyArrayBuffer._storage
185+
%i4 = struct_extract %i3, #_MyBridgeStorage.rawValue
186+
%i5 = unchecked_ref_cast %i4 to $Storage
187+
%i6 = ref_tail_addr %i5, $MyInt
188+
end_borrow %i1
163189
debug_value %7 : $MyArray<MyInt>
164190
%15 = function_ref @mayWrite : $@convention(thin) (@guaranteed MyArray<MyInt>) -> ()
165191
%16 = apply %15(%7) : $@convention(thin) (@guaranteed MyArray<MyInt>) -> ()

0 commit comments

Comments
 (0)