Skip to content

Commit 30d3950

Browse files
Merge pull request #41439 from aschwaighofer/optimize_contiguousarraystorage_anyobject
Also optimize calls to getContiguousArrayStorageType<SomeClass> to ContiguousArrayStorage<AnyObject> under the right deployment setting
2 parents 58fe2e1 + 0c9a54a commit 30d3950

File tree

6 files changed

+106
-19
lines changed

6 files changed

+106
-19
lines changed

include/swift/AST/KnownStdlibTypes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ KNOWN_STDLIB_TYPE_DECL(String, NominalTypeDecl, 0)
4949
KNOWN_STDLIB_TYPE_DECL(StaticString, NominalTypeDecl, 0)
5050
KNOWN_STDLIB_TYPE_DECL(Substring, NominalTypeDecl, 0)
5151
KNOWN_STDLIB_TYPE_DECL(Array, NominalTypeDecl, 1)
52-
KNOWN_STDLIB_TYPE_DECL(_ContiguousArrayStorage, NominalTypeDecl, 1)
52+
KNOWN_STDLIB_TYPE_DECL(_ContiguousArrayStorage, ClassDecl, 1)
5353
KNOWN_STDLIB_TYPE_DECL(Set, NominalTypeDecl, 1)
5454
KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
5555
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,9 @@ bool SILCombiner::optimizeIdentityCastComposition(ApplyInst *fInverseApply,
15721572
}
15731573

15741574
/// Should replace a call to `getContiguousArrayStorageType<A>(for:)` by the
1575-
/// metadata constructor.
1575+
/// metadata constructor of the return type.
1576+
/// getContiguousArrayStorageType<Int>(for:)
1577+
/// => metatype @thick ContiguousArrayStorage<Int>.Type
15761578
/// We know that `getContiguousArrayStorageType` will not return the AnyObject
15771579
/// type optimization for any non class or objc existential type instantiation.
15781580
static bool shouldReplaceCallByMetadataConstructor(CanType storageMetaTy) {
@@ -1588,20 +1590,17 @@ static bool shouldReplaceCallByMetadataConstructor(CanType storageMetaTy) {
15881590
if (!boundGenericTy)
15891591
return false;
15901592

1591-
for (auto TP : boundGenericTy->getGenericArgs()) {
1592-
auto ty = TP->getCanonicalType();
1593-
if (ty->getStructOrBoundGenericStruct() ||
1594-
ty->getEnumOrBoundGenericEnum() ||
1595-
isa<BuiltinVectorType>(ty) ||
1596-
isa<BuiltinIntegerType>(ty) ||
1597-
isa<BuiltinFloatType>(ty) ||
1598-
isa<TupleType>(ty) ||
1599-
isa<AnyFunctionType>(ty) ||
1600-
(ty->isAnyExistentialType() && !ty->isObjCExistentialType()))
1601-
return true;
1602-
1593+
auto genericArgs = boundGenericTy->getGenericArgs();
1594+
if (genericArgs.size() != 1)
16031595
return false;
1604-
}
1596+
auto ty = genericArgs[0]->getCanonicalType();
1597+
if (ty->getStructOrBoundGenericStruct() || ty->getEnumOrBoundGenericEnum() ||
1598+
isa<BuiltinVectorType>(ty) || isa<BuiltinIntegerType>(ty) ||
1599+
isa<BuiltinFloatType>(ty) || isa<TupleType>(ty) ||
1600+
isa<AnyFunctionType>(ty) ||
1601+
(ty->isAnyExistentialType() && !ty->isObjCExistentialType()))
1602+
return true;
1603+
16051604
return false;
16061605
}
16071606

@@ -1641,6 +1640,8 @@ SILInstruction *SILCombiner::visitApplyInst(ApplyInst *AI) {
16411640
if (SF->hasSemanticsAttr(semantics::ARRAY_GET_CONTIGUOUSARRAYSTORAGETYPE)) {
16421641
auto silTy = AI->getType();
16431642
auto storageTy = AI->getType().getASTType();
1643+
1644+
// getContiguousArrayStorageType<Int> => ContiguousArrayStorage<Int>
16441645
if (shouldReplaceCallByMetadataConstructor(storageTy)) {
16451646
auto metatype = Builder.createMetatype(AI->getLoc(), silTy);
16461647
AI->replaceAllUsesWith(metatype);
@@ -1650,7 +1651,6 @@ SILInstruction *SILCombiner::visitApplyInst(ApplyInst *AI) {
16501651
}
16511652
}
16521653

1653-
16541654
// (apply (thin_to_thick_function f)) to (apply f)
16551655
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(AI->getCallee())) {
16561656
// We currently don't remove any possible retain associated with the thick

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
#define DEBUG_TYPE "sil-combine"
1414

1515
#include "SILCombiner.h"
16+
#include "swift/AST/SemanticAttrs.h"
1617
#include "swift/Basic/STLExtras.h"
18+
#include "swift/SIL/BasicBlockBits.h"
1719
#include "swift/SIL/DebugUtils.h"
1820
#include "swift/SIL/DynamicCasts.h"
1921
#include "swift/SIL/InstructionUtils.h"
2022
#include "swift/SIL/PatternMatch.h"
2123
#include "swift/SIL/Projection.h"
22-
#include "swift/SIL/BasicBlockBits.h"
2324
#include "swift/SIL/SILBuilder.h"
2425
#include "swift/SIL/SILInstruction.h"
2526
#include "swift/SIL/SILVisitor.h"
@@ -2148,6 +2149,43 @@ SILInstruction *SILCombiner::visitFixLifetimeInst(FixLifetimeInst *fli) {
21482149
return nullptr;
21492150
}
21502151

2152+
static Optional<SILType>
2153+
shouldReplaceCallByContiguousArrayStorageAnyObject(SILFunction &F,
2154+
CanType storageMetaTy) {
2155+
auto metaTy = dyn_cast<MetatypeType>(storageMetaTy);
2156+
if (!metaTy || metaTy->getRepresentation() != MetatypeRepresentation::Thick)
2157+
return None;
2158+
2159+
auto storageTy = metaTy.getInstanceType()->getCanonicalType();
2160+
if (!storageTy->is_ContiguousArrayStorage())
2161+
return None;
2162+
2163+
auto boundGenericTy = dyn_cast<BoundGenericType>(storageTy);
2164+
if (!boundGenericTy)
2165+
return None;
2166+
2167+
// On SwiftStdlib 5.7 we can replace the call.
2168+
auto &ctxt = storageMetaTy->getASTContext();
2169+
auto deployment = AvailabilityContext::forDeploymentTarget(ctxt);
2170+
if (!deployment.isContainedIn(ctxt.getSwift57Availability()))
2171+
return None;
2172+
2173+
auto genericArgs = boundGenericTy->getGenericArgs();
2174+
if (genericArgs.size() != 1)
2175+
return None;
2176+
2177+
auto ty = genericArgs[0]->getCanonicalType();
2178+
if (!ty->getClassOrBoundGenericClass() && !ty->isObjCExistentialType())
2179+
return None;
2180+
2181+
auto anyObjectTy = ctxt.getAnyObjectType();
2182+
auto arrayStorageTy =
2183+
BoundGenericClassType::get(ctxt.get_ContiguousArrayStorageDecl(), nullptr,
2184+
{anyObjectTy})
2185+
->getCanonicalType();
2186+
return F.getTypeLowering(arrayStorageTy).getLoweredType();
2187+
}
2188+
21512189
SILInstruction *
21522190
SILCombiner::
21532191
visitAllocRefDynamicInst(AllocRefDynamicInst *ARDI) {
@@ -2209,6 +2247,32 @@ visitAllocRefDynamicInst(AllocRefDynamicInst *ARDI) {
22092247
ARDI->getTailAllocatedTypes(),
22102248
getCounts(ARDI));
22112249
}
2250+
} else if (auto *AI = dyn_cast<ApplyInst>(MDVal)) {
2251+
SILFunction *SF = AI->getReferencedFunctionOrNull();
2252+
if (!SF)
2253+
return nullptr;
2254+
2255+
if (!SF->hasSemanticsAttr(semantics::ARRAY_GET_CONTIGUOUSARRAYSTORAGETYPE))
2256+
return nullptr;
2257+
2258+
auto use = AI->getSingleUse();
2259+
if (!use || use->getUser() != ARDI)
2260+
return nullptr;
2261+
2262+
auto silTy = AI->getType();
2263+
auto storageTy = AI->getType().getASTType();
2264+
// getContiguousArrayStorageType<SomeClass> =>
2265+
// ContiguousArrayStorage<AnyObject>
2266+
auto instanceTy = shouldReplaceCallByContiguousArrayStorageAnyObject(
2267+
*AI->getFunction(), storageTy);
2268+
if (!instanceTy)
2269+
return nullptr;
2270+
NewInst = Builder.createAllocRef(
2271+
ARDI->getLoc(), *instanceTy, ARDI->isObjC(), false,
2272+
ARDI->getTailAllocatedTypes(), getCounts(ARDI));
2273+
NewInst = Builder.createUncheckedRefCast(ARDI->getLoc(), NewInst,
2274+
ARDI->getType());
2275+
return NewInst;
22122276
}
22132277
if (NewInst && NewInst->getType() != ARDI->getType()) {
22142278
// In case the argument was an upcast of the metatype, we have to upcast the
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend -target x86_64-apple-macosx99.99 -parse-as-library -O -module-name=test %s -emit-sil | %FileCheck %s
2+
// RUN: %target-swift-frontend -target x86_64-apple-macosx12.3 -parse-as-library -O -module-name=test %s -emit-sil | %FileCheck %s --check-prefix=NOOPTCLASS
3+
4+
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
5+
// REQUIRES: OS=macosx
6+
7+
// CHECK: sil @$s4test12makeArrayInt1xSaySiGSi_tF
8+
// CHECK: alloc_ref [tail_elems $Int * {{.*}} : $Builtin.Word] $_ContiguousArrayStorage<Int>
9+
// NOOPTCLASS: sil @$s4test12makeArrayInt1xSaySiGSi_tF
10+
// NOOPTCLASS: alloc_ref [tail_elems $Int * {{.*}} : $Builtin.Word] $_ContiguousArrayStorage<Int>
11+
public func makeArrayInt(x: Int) -> [Int] {
12+
return [0, 1, x]
13+
}
14+
15+
// CHECK: sil @$s4test14makeArrayClass1xSayAA1CCGAE_tF
16+
// CHECK: alloc_ref [tail_elems $C * {{.*}} : $Builtin.Word] $_ContiguousArrayStorage<AnyObject>
17+
// NOOPTCLASS: sil @$s4test14makeArrayClass1xSayAA1CCGAE_tF
18+
// NOOPTCLASS: function_ref @$ss29getContiguousArrayStorageType3fors01
19+
// NOOPTCLASS: alloc_ref_dynamic [tail_elems $C * {{.*}} : $Builtin.Word]
20+
public class C {}
21+
public func makeArrayClass(x: C) -> [C] {
22+
return [x, x, x]
23+
}

test/SILOptimizer/stack_promotion_escaping.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ final public class Escaper {
1313

1414
// CHECK-LABEL: sil [noinline] @$s4test7EscaperC15badStuffHappensyyF : $@convention(method) (@guaranteed Escaper) -> () {
1515
// CHECK: %2 = alloc_ref $Item
16-
// CHECK: alloc_ref_dynamic [stack] [tail_elems $Item * %{{[0-9]+}} : $Builtin.Word]{{.*}} $_ContiguousArrayStorage<Item>
16+
// CHECK: alloc_ref{{(_dynamic)?}} [stack] [tail_elems $Item * %{{[0-9]+}} : $Builtin.Word]{{.*}} $_ContiguousArrayStorage<{{(Item|AnyObject)}}>
1717
// CHECK: return
1818
@inline(never)
1919
public func badStuffHappens() {

test/SILOptimizer/static_arrays.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ func takeUnsafePointer(ptr : UnsafePointer<SwiftClass>, len: Int) {
237237
// CHECK-LABEL: sil @{{.*}}passArrayOfClasses
238238
// CHECK: bb0(%0 : $SwiftClass, %1 : $SwiftClass, %2 : $SwiftClass):
239239
// CHECK-NOT: bb1(
240-
// CHECK: alloc_ref_dynamic {{.*}}[tail_elems $SwiftClass *
240+
// CHECK: alloc_ref{{(_dynamic)?}} {{.*}}[tail_elems $SwiftClass *
241241
// CHECK-NOT: bb1(
242242
// CHECK: return
243243
public func passArrayOfClasses(a: SwiftClass, b: SwiftClass, c: SwiftClass) {

0 commit comments

Comments
 (0)