Skip to content

Commit 19b828b

Browse files
committed
StringOptimization: handle inlined global accessors.
In case a global accessor is inlined, the `global_addr` and it's `builtin "once"` call is visible in the SIL instead of the call to the global initializer.
1 parent 56c09c3 commit 19b828b

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

lib/SILOptimizer/Transforms/StringOptimization.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -581,25 +581,43 @@ StringOptimization::getStringFromStaticLet(SILValue value) {
581581
auto *load = dyn_cast<LoadInst>(value);
582582
if (!load)
583583
return StringInfo::unknown();
584-
585-
auto *pta = dyn_cast<PointerToAddressInst>(load->getOperand());
586-
if (!pta)
587-
return StringInfo::unknown();
588-
589-
auto *addressorCall = dyn_cast<ApplyInst>(pta->getOperand());
590-
if (!addressorCall)
591-
return StringInfo::unknown();
592-
593-
SILFunction *addressorFunc = addressorCall->getReferencedFunctionOrNull();
594-
if (!addressorFunc)
595-
return StringInfo::unknown();
596-
597-
// The addressor function has a builtin.once call to the initializer.
598-
BuiltinInst *onceCall = nullptr;
599-
SILFunction *initializer = findInitializer(addressorFunc, onceCall);
600-
if (!initializer)
584+
585+
SILFunction *initializer = nullptr;
586+
auto *globalAddr = dyn_cast<GlobalAddrInst>(load->getOperand());
587+
if (globalAddr) {
588+
// The global accessor is inlined.
589+
590+
// Usually the global_addr is immediately preceeded by a call to
591+
// `builtin "once"` which initializes the global.
592+
SILInstruction *prev = globalAddr->getPreviousInstruction();
593+
if (!prev)
594+
return StringInfo::unknown();
595+
auto *bi = dyn_cast<BuiltinInst>(prev);
596+
if (!bi || bi->getBuiltinInfo().ID != BuiltinValueKind::Once)
597+
return StringInfo::unknown();
598+
initializer = getCalleeOfOnceCall(bi);
599+
} else {
600+
// The global accessor is not inlined, yet.
601+
602+
auto *pta = dyn_cast<PointerToAddressInst>(load->getOperand());
603+
if (!pta)
604+
return StringInfo::unknown();
605+
606+
auto *addressorCall = dyn_cast<ApplyInst>(pta->getOperand());
607+
if (!addressorCall)
608+
return StringInfo::unknown();
609+
610+
SILFunction *addressorFunc = addressorCall->getReferencedFunctionOrNull();
611+
if (!addressorFunc)
612+
return StringInfo::unknown();
613+
614+
// The addressor function has a builtin.once call to the initializer.
615+
BuiltinInst *onceCall = nullptr;
616+
initializer = findInitializer(addressorFunc, onceCall);
617+
}
618+
if (!initializer || !initializer->isGlobalInitOnceFunction())
601619
return StringInfo::unknown();
602-
620+
603621
if (initializer->size() != 1)
604622
return StringInfo::unknown();
605623

@@ -618,7 +636,10 @@ StringOptimization::getStringFromStaticLet(SILValue value) {
618636
}
619637
if (!gAddr || !gAddr->getReferencedGlobal()->isLet())
620638
return StringInfo::unknown();
621-
639+
640+
if (globalAddr && globalAddr->getReferencedGlobal() != gAddr->getReferencedGlobal())
641+
return StringInfo::unknown();
642+
622643
Operand *gUse = gAddr->getSingleUse();
623644
auto *store = dyn_cast<StoreInst>(gUse->getUser());
624645
if (!store || store->getDest() != gAddr)

0 commit comments

Comments
 (0)