Skip to content

Commit 34ae1d9

Browse files
committed
SILCombine: remove release_value of a value_to_bridge_object
Needed to remove unneeded reference counting for String literals.
1 parent f12ac4c commit 34ae1d9

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,31 @@ SILInstruction *SILCombiner::visitIndexAddrInst(IndexAddrInst *IA) {
997997
return Builder.createIndexAddr(IA->getLoc(), base2, newIndex);
998998
}
999999

1000+
/// Walks over all fields of an aggregate and checks if a reference count
1001+
/// operation for \p value is required. This differs from a simple `isTrivial`
1002+
/// check, because it treats a value_to_bridge_object instruction as "trivial".
1003+
static bool isTrivial(SILValue value, SILFunction *function) {
1004+
SmallVector<ValueBase *, 32> workList;
1005+
SmallPtrSet<ValueBase *, 16> visited;
1006+
workList.push_back(value);
1007+
while (!workList.empty()) {
1008+
SILValue v = workList.pop_back_val();
1009+
if (v->getType().isTrivial(*function))
1010+
continue;
1011+
if (isa<ValueToBridgeObjectInst>(v))
1012+
continue;
1013+
if (isa<StructInst>(v) || isa<TupleInst>(v)) {
1014+
for (SILValue op : cast<SingleValueInstruction>(v)->getOperandValues()) {
1015+
if (visited.insert(op).second)
1016+
workList.push_back(op);
1017+
}
1018+
continue;
1019+
}
1020+
return false;
1021+
}
1022+
return true;
1023+
}
1024+
10001025
SILInstruction *SILCombiner::visitReleaseValueInst(ReleaseValueInst *RVI) {
10011026
assert(!RVI->getFunction()->hasOwnership());
10021027

@@ -1031,7 +1056,7 @@ SILInstruction *SILCombiner::visitReleaseValueInst(ReleaseValueInst *RVI) {
10311056
RVI->getAtomicity());
10321057

10331058
// ReleaseValueInst of a trivial type is a no-op.
1034-
if (OperandTy.isTrivial(*RVI->getFunction()))
1059+
if (isTrivial(Operand, RVI->getFunction()))
10351060
return eraseInstFromFunction(*RVI);
10361061

10371062
// Do nothing for non-trivial non-reference types.

test/SILOptimizer/sil_combine.sil

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3825,6 +3825,36 @@ bb0(%0 : $Builtin.Int64):
38253825
return %2 : $Builtin.BridgeObject
38263826
}
38273827

3828+
struct MyStringObj {
3829+
@_hasStorage var a: UInt64
3830+
@_hasStorage var b: Builtin.BridgeObject
3831+
}
3832+
3833+
struct MyStringGuts {
3834+
@_hasStorage var o: MyStringObj
3835+
}
3836+
3837+
struct MyString {
3838+
@_hasStorage var g: MyStringGuts
3839+
}
3840+
3841+
// CHECK-LABEL: sil @optimize_arc_with_value_to_bridge_object2
3842+
// CHECK: bb0(%0 : $UInt64):
3843+
// CHECK-NEXT: tuple
3844+
// CHECK-NEXT: return
3845+
// CHECK: } // end sil function 'optimize_arc_with_value_to_bridge_object2'
3846+
sil @optimize_arc_with_value_to_bridge_object2 : $@convention(thin) (UInt64) -> () {
3847+
bb0(%0 : $UInt64):
3848+
%1 = integer_literal $Builtin.Int64, -1945555039024054272
3849+
%2 = value_to_bridge_object %1 : $Builtin.Int64
3850+
%3 = struct $MyStringObj (%0 : $UInt64, %2 : $Builtin.BridgeObject)
3851+
%4 = struct $MyStringGuts (%3 : $MyStringObj)
3852+
%5 = struct $MyString (%4 : $MyStringGuts)
3853+
release_value %5 : $MyString
3854+
%7 = tuple ()
3855+
return %7 : $()
3856+
}
3857+
38283858
// CHECK-LABEL: sil @optimize_stringObject_bit_operations
38293859
// CHECK: bb0:
38303860
// CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 4611686018427387904

0 commit comments

Comments
 (0)