Skip to content

Commit c62b452

Browse files
committed
IRGen: don't initialized a global_object static object if not needed.
We don't need to initialize the global object if it's never used for something which can access the object header. This let's e.g. lookup-tables to be compiled with zero Array-overhead. rdar://59874359
1 parent ea8f43a commit c62b452

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,6 +2634,23 @@ void IRGenSILFunction::visitGlobalAddrInst(GlobalAddrInst *i) {
26342634
setLoweredAddress(i, addr);
26352635
}
26362636

2637+
/// Returns true if \p val has no other uses than ref_element_addr or
2638+
/// ref_tail_addr.
2639+
static bool hasOnlyProjections(SILValue val) {
2640+
for (Operand *use : val->getUses()) {
2641+
SILInstruction *user = use->getUser();
2642+
if (auto *upCast = dyn_cast<UpcastInst>(user)) {
2643+
if (!hasOnlyProjections(upCast))
2644+
return false;
2645+
continue;
2646+
}
2647+
if (isa<RefElementAddrInst>(user) || isa<RefTailAddrInst>(user))
2648+
continue;
2649+
return false;
2650+
}
2651+
return true;
2652+
}
2653+
26372654
void IRGenSILFunction::visitGlobalValueInst(GlobalValueInst *i) {
26382655
SILGlobalVariable *var = i->getReferencedGlobal();
26392656
assert(var->isInitializedObject() &&
@@ -2645,17 +2662,19 @@ void IRGenSILFunction::visitGlobalValueInst(GlobalValueInst *i) {
26452662

26462663
llvm::Value *Ref = IGM.getAddrOfSILGlobalVariable(var, ti,
26472664
NotForDefinition).getAddress();
2648-
2649-
auto ClassType = loweredTy.getASTType();
2650-
llvm::Value *Metadata =
2651-
emitClassHeapMetadataRef(*this, ClassType, MetadataValueType::TypeMetadata,
2652-
MetadataState::Complete);
2653-
llvm::Value *CastAddr = Builder.CreateBitCast(Ref, IGM.RefCountedPtrTy);
2654-
llvm::Value *InitRef = emitInitStaticObjectCall(Metadata, CastAddr, "staticref");
2655-
InitRef = Builder.CreateBitCast(InitRef, Ref->getType());
2656-
2665+
// We don't need to initialize the global object if it's never used for
2666+
// something which can access the object header.
2667+
if (!hasOnlyProjections(i)) {
2668+
auto ClassType = loweredTy.getASTType();
2669+
llvm::Value *Metadata =
2670+
emitClassHeapMetadataRef(*this, ClassType, MetadataValueType::TypeMetadata,
2671+
MetadataState::Complete);
2672+
llvm::Value *CastAddr = Builder.CreateBitCast(Ref, IGM.RefCountedPtrTy);
2673+
llvm::Value *InitRef = emitInitStaticObjectCall(Metadata, CastAddr, "staticref");
2674+
Ref = Builder.CreateBitCast(InitRef, Ref->getType());
2675+
}
26572676
Explosion e;
2658-
e.add(InitRef);
2677+
e.add(Ref);
26592678
setLoweredExplosion(i, e);
26602679
}
26612680

test/SILOptimizer/static_arrays.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-swift-frontend -primary-file %s -O -sil-verify-all -Xllvm -sil-disable-pass=FunctionSignatureOpts -module-name=test -emit-sil | %FileCheck %s
2+
// RUN: %target-swift-frontend -primary-file %s -O -sil-verify-all -Xllvm -sil-disable-pass=FunctionSignatureOpts -module-name=test -emit-ir | %FileCheck %s -check-prefix=CHECK-LLVM
23

34
// Also do an end-to-end test to check all components, including IRGen.
45
// RUN: %empty-directory(%t)
@@ -98,9 +99,18 @@
9899
// CHECK: return
99100
public let globalVariable = [ 100, 101, 102 ]
100101

101-
// CHECK-LABEL: sil {{.*}}arrayLookup{{.*}} : $@convention(thin) (Int) -> Int {
102-
// CHECK: global_value @{{.*}}arrayLookup{{.*}}
103-
// CHECK: return
102+
// CHECK-LABEL: sil [noinline] @$s4test11arrayLookupyS2iF
103+
// CHECK: global_value @$s4test11arrayLookupyS2iFTv_
104+
// CHECK-NOT: retain
105+
// CHECK-NOT: release
106+
// CHECK: } // end sil function '$s4test11arrayLookupyS2iF'
107+
108+
// CHECK-LLVM-LABEL: define {{.*}} @"$s4test11arrayLookupyS2iF"
109+
// CHECK-LLVM-NOT: call
110+
// CHECK-LLVM: [[E:%[0-9]+]] = getelementptr {{.*}} @"$s4test11arrayLookupyS2iFTv_"
111+
// CHECK-LLVM-NEXT: [[L:%[0-9]+]] = load {{.*}} [[E]]
112+
// CHECK-LLVM-NEXT: ret {{.*}} [[L]]
113+
// CHECK-LLVM: }
104114
@inline(never)
105115
public func arrayLookup(_ i: Int) -> Int {
106116
let lookupTable = [10, 11, 12]

0 commit comments

Comments
 (0)