Skip to content

Commit ea8f43a

Browse files
committed
SILCombine: remove unneeded reference counting instructions from global_value
Delete all reference count instructions on a global_value if the only other uses are projections (ref_element_addr and ref_tail_addr).
1 parent 2e0bda5 commit ea8f43a

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ class SILCombiner :
301301

302302
SILInstruction *visitMarkDependenceInst(MarkDependenceInst *MDI);
303303
SILInstruction *visitClassifyBridgeObjectInst(ClassifyBridgeObjectInst *CBOI);
304+
SILInstruction *visitGlobalValueInst(GlobalValueInst *globalValue);
304305
SILInstruction *visitConvertFunctionInst(ConvertFunctionInst *CFI);
305306
SILInstruction *
306307
visitConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *Cvt);

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,3 +2283,40 @@ SILCombiner::visitClassifyBridgeObjectInst(ClassifyBridgeObjectInst *cboi) {
22832283

22842284
return nullptr;
22852285
}
2286+
2287+
/// Returns true if reference counting and debug_value users of a global_value
2288+
/// can be deleted.
2289+
static bool checkGlobalValueUsers(SILValue val,
2290+
SmallVectorImpl<SILInstruction *> &toDelete) {
2291+
for (Operand *use : val->getUses()) {
2292+
SILInstruction *user = use->getUser();
2293+
if (isa<RefCountingInst>(user) || isa<DebugValueInst>(user)) {
2294+
toDelete.push_back(user);
2295+
continue;
2296+
}
2297+
if (auto *upCast = dyn_cast<UpcastInst>(user)) {
2298+
if (!checkGlobalValueUsers(upCast, toDelete))
2299+
return false;
2300+
continue;
2301+
}
2302+
// Projection instructions don't access the object header, so they don't
2303+
// prevent deleting reference counting instructions.
2304+
if (isa<RefElementAddrInst>(user) || isa<RefTailAddrInst>(user))
2305+
continue;
2306+
return false;
2307+
}
2308+
return true;
2309+
}
2310+
2311+
SILInstruction *
2312+
SILCombiner::visitGlobalValueInst(GlobalValueInst *globalValue) {
2313+
// Delete all reference count instructions on a global_value if the only other
2314+
// users are projections (ref_element_addr and ref_tail_addr).
2315+
SmallVector<SILInstruction *, 8> toDelete;
2316+
if (!checkGlobalValueUsers(globalValue, toDelete))
2317+
return nullptr;
2318+
for (SILInstruction *inst : toDelete) {
2319+
eraseInstFromFunction(*inst);
2320+
}
2321+
return nullptr;
2322+
}

test/SILOptimizer/sil_combine.sil

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4203,4 +4203,26 @@ bb1(%result : $Builtin.NativeObject):
42034203

42044204
bb2(%error : $Error):
42054205
unreachable
4206-
}
4206+
}
4207+
4208+
sil_global private @outlined_global : $_ContiguousArrayStorage<Int>
4209+
4210+
// CHECK-LABEL: sil @test_global_value
4211+
// CHECK-NOT: retain
4212+
// CHECK-NOT: release
4213+
// CHECK-NOT: debug_value
4214+
// CHECK: } // end sil function 'test_global_value'
4215+
sil @test_global_value : $@convention(thin) () -> Int {
4216+
bb0:
4217+
%0 = global_value @outlined_global : $_ContiguousArrayStorage<Int>
4218+
strong_retain %0 : $_ContiguousArrayStorage<Int>
4219+
debug_value %0 : $_ContiguousArrayStorage<Int>, let, name "x"
4220+
%2 = upcast %0 : $_ContiguousArrayStorage<Int> to $__ContiguousArrayStorageBase
4221+
strong_retain %2 : $__ContiguousArrayStorageBase
4222+
%13 = ref_tail_addr [immutable] %2 : $__ContiguousArrayStorageBase, $Int
4223+
%16 = load %13 : $*Int
4224+
strong_release %2 : $__ContiguousArrayStorageBase
4225+
strong_release %0 : $_ContiguousArrayStorage<Int>
4226+
return %16 : $Int
4227+
} // end sil function 'test_global_value'
4228+

0 commit comments

Comments
 (0)