Skip to content

Commit 47a7acd

Browse files
committed
LICM: hoist builtin "once" calls out of loops
`builtin "once"` calls are a result of inlining global accessors
1 parent 260e68b commit 47a7acd

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

lib/SILOptimizer/LoopTransforms/LICM.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ static bool mayWriteTo(AliasAnalysis *AA, BasicCalleeAnalysis *BCA,
224224
/// Returns true if \p sideEffectInst cannot be reordered with a call to a
225225
/// global initializer.
226226
static bool mayConflictWithGlobalInit(AliasAnalysis *AA,
227-
SILInstruction *sideEffectInst, ApplyInst *globalInitCall) {
227+
SILInstruction *sideEffectInst, SILInstruction *globalInitCall) {
228228
if (auto *SI = dyn_cast<StoreInst>(sideEffectInst)) {
229229
return AA->mayReadOrWriteMemory(globalInitCall, SI->getDest());
230230
}
@@ -239,7 +239,7 @@ static bool mayConflictWithGlobalInit(AliasAnalysis *AA,
239239
/// the call.
240240
static bool mayConflictWithGlobalInit(AliasAnalysis *AA,
241241
InstSet &sideEffectInsts,
242-
ApplyInst *globalInitCall,
242+
SILInstruction *globalInitCall,
243243
SILBasicBlock *preHeader, PostDominanceInfo *PD) {
244244
if (!PD->dominates(globalInitCall->getParent(), preHeader))
245245
return true;
@@ -263,7 +263,7 @@ static bool mayConflictWithGlobalInit(AliasAnalysis *AA,
263263
/// block).
264264
static bool mayConflictWithGlobalInit(AliasAnalysis *AA,
265265
ArrayRef<SILInstruction *> sideEffectInsts,
266-
ApplyInst *globalInitCall) {
266+
SILInstruction *globalInitCall) {
267267
for (auto *seInst : sideEffectInsts) {
268268
assert(seInst->getParent() == globalInitCall->getParent());
269269
if (mayConflictWithGlobalInit(AA, seInst, globalInitCall))
@@ -864,7 +864,12 @@ void LoopTreeOptimization::analyzeCurrentLoop(
864864

865865
// Interesting instructions in the loop:
866866
SmallVector<ApplyInst *, 8> ReadOnlyApplies;
867-
SmallVector<ApplyInst *, 8> globalInitCalls;
867+
868+
// Contains either:
869+
// * an apply to the addressor of the global
870+
// * a builtin "once" of the global initializer
871+
SmallVector<SILInstruction *, 8> globalInitCalls;
872+
868873
SmallVector<LoadInst *, 8> Loads;
869874
SmallVector<StoreInst *, 8> Stores;
870875
SmallVector<FixLifetimeInst *, 8> FixLifetimes;
@@ -918,16 +923,27 @@ void LoopTreeOptimization::analyzeCurrentLoop(
918923
// Check against side-effects within the same block.
919924
// Side-effects in other blocks are checked later (after we
920925
// scanned all blocks of the loop).
921-
!mayConflictWithGlobalInit(AA, sideEffectsInBlock, AI))
922-
globalInitCalls.push_back(AI);
926+
!mayConflictWithGlobalInit(AA, sideEffectsInBlock, &Inst))
927+
globalInitCalls.push_back(&Inst);
923928
}
924929
// check for array semantics and side effects - same as default
925930
LLVM_FALLTHROUGH;
926931
}
927932
default:
928933
if (auto fullApply = FullApplySite::isa(&Inst)) {
929934
fullApplies.push_back(fullApply);
935+
} else if (auto *bi = dyn_cast<BuiltinInst>(&Inst)) {
936+
switch (bi->getBuiltinInfo().ID) {
937+
case BuiltinValueKind::Once:
938+
case BuiltinValueKind::OnceWithContext:
939+
if (!mayConflictWithGlobalInit(AA, sideEffectsInBlock, &Inst))
940+
globalInitCalls.push_back(&Inst);
941+
break;
942+
default:
943+
break;
944+
}
930945
}
946+
931947
checkSideEffects(Inst, sideEffects, sideEffectsInBlock);
932948
if (canHoistUpDefault(&Inst, Loop, DomTree, RunsOnHighLevelSIL)) {
933949
HoistUp.insert(&Inst);
@@ -959,7 +975,7 @@ void LoopTreeOptimization::analyzeCurrentLoop(
959975
postDomTree = PDA->get(Preheader->getParent());
960976
}
961977
if (postDomTree->getRootNode()) {
962-
for (ApplyInst *ginitCall : globalInitCalls) {
978+
for (SILInstruction *ginitCall : globalInitCalls) {
963979
// Check against side effects which are "before" (i.e. post-dominated
964980
// by) the global initializer call.
965981
if (!mayConflictWithGlobalInit(AA, sideEffects, ginitCall, Preheader,

test/SILOptimizer/licm.sil

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,3 +1474,59 @@ bb3:
14741474
%21 = tuple ()
14751475
return %21 : $()
14761476
}
1477+
1478+
sil_global private @g_token : $Builtin.Word
1479+
sil_global @gi : $Int
1480+
1481+
sil @g_init : $@convention(c) () -> ()
1482+
1483+
// CHECK-LABEL: sil @hoist_builtin_once :
1484+
// CHECK: function_ref
1485+
// CHECK: builtin "once"
1486+
// CHECK: br bb1
1487+
// CHECK: bb1:
1488+
// CHECK-NOT: builtin
1489+
// CHECK: cond_br
1490+
// CHECK: } // end sil function 'hoist_builtin_once'
1491+
sil @hoist_builtin_once : $@convention(thin) () -> () {
1492+
bb0:
1493+
br bb1
1494+
1495+
bb1:
1496+
%1 = global_addr @g_token : $*Builtin.Word
1497+
%2 = address_to_pointer %1 : $*Builtin.Word to $Builtin.RawPointer
1498+
%3 = function_ref @g_init : $@convention(c) () -> ()
1499+
%4 = builtin "once"(%2 : $Builtin.RawPointer, %3 : $@convention(c) () -> ()) : $()
1500+
cond_br undef, bb1, bb2
1501+
1502+
bb2:
1503+
%r1 = tuple ()
1504+
return %r1 : $()
1505+
}
1506+
1507+
// CHECK-LABEL: sil @dont_hoist_builtin_once_memory_conflict :
1508+
// CHECK: function_ref
1509+
// CHECK: br bb1
1510+
// CHECK: bb1:
1511+
// CHECK: builtin "once"
1512+
// CHECK: cond_br
1513+
// CHECK: } // end sil function 'dont_hoist_builtin_once_memory_conflict'
1514+
sil @dont_hoist_builtin_once_memory_conflict : $@convention(thin) (Int) -> () {
1515+
bb0(%0 : $Int):
1516+
br bb1
1517+
1518+
bb1:
1519+
%1 = global_addr @gi : $*Int
1520+
store %0 to %1 : $*Int
1521+
%3 = global_addr @g_token : $*Builtin.Word
1522+
%4 = address_to_pointer %3 : $*Builtin.Word to $Builtin.RawPointer
1523+
%5 = function_ref @g_init : $@convention(c) () -> ()
1524+
%6 = builtin "once"(%4 : $Builtin.RawPointer, %5 : $@convention(c) () -> ()) : $()
1525+
cond_br undef, bb1, bb2
1526+
1527+
bb2:
1528+
%r1 = tuple ()
1529+
return %r1 : $()
1530+
}
1531+
1532+

0 commit comments

Comments
 (0)