Skip to content

Commit 40e805d

Browse files
committed
libswift: simplify ReleaseDevirtualizer.swift
1 parent d7144c0 commit 40e805d

File tree

1 file changed

+26
-61
lines changed

1 file changed

+26
-61
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ReleaseDevirtualizer.swift

Lines changed: 26 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -102,47 +102,43 @@ private func tryDevirtualizeReleaseOfObject(
102102
}
103103

104104
private func stripRCIdentityPreservingInsts(_ value: Value) -> Value? {
105-
switch value {
105+
guard let inst = value as? Instruction else { return nil }
106+
107+
switch inst {
106108
// First strip off RC identity preserving casts.
107-
case let inst as Instruction where inst is UpcastInst ||
108-
inst is UncheckedRefCastInst ||
109-
inst is InitExistentialRefInst ||
110-
inst is OpenExistentialRefInst ||
111-
inst is RefToBridgeObjectInst ||
112-
inst is BridgeObjectToRefInst ||
113-
inst is ConvertFunctionInst ||
114-
inst is UncheckedEnumDataInst:
109+
case is UpcastInst,
110+
is UncheckedRefCastInst,
111+
is InitExistentialRefInst,
112+
is OpenExistentialRefInst,
113+
is RefToBridgeObjectInst,
114+
is BridgeObjectToRefInst,
115+
is ConvertFunctionInst,
116+
is UncheckedEnumDataInst:
115117
return inst.operands[0].value
116118

117119
// Then if we have a struct_extract that is extracting a non-trivial member
118120
// from a struct with no other non-trivial members, a ref count operation on
119121
// the struct is equivalent to a ref count operation on the extracted
120122
// member. Strip off the extract.
121123
case let sei as StructExtractInst where sei.isFieldOnlyNonTrivialField:
122-
return sei.operands[0].value
124+
return sei.operand
123125

124-
// If we have a struct instruction with only one non-trivial stored field, the
125-
// only reference count that can be modified is the non-trivial field. Return
126-
// the non-trivial field.
127-
case let si as StructInst:
128-
return si.uniqueNonTrivialOperand
126+
// If we have a struct or tuple instruction with only one non-trivial operand, the
127+
// only reference count that can be modified is the non-trivial operand. Return
128+
// the non-trivial operand.
129+
case is StructInst, is TupleInst:
130+
return inst.uniqueNonTrivialOperand
129131

130132
// If we have an enum instruction with a payload, strip off the enum to
131133
// expose the enum's payload.
132134
case let ei as EnumInst where !ei.operands.isEmpty:
133-
return ei.operands[0].value
135+
return ei.operand
134136

135137
// If we have a tuple_extract that is extracting the only non trivial member
136138
// of a tuple, a retain_value on the tuple is equivalent to a retain_value on
137139
// the extracted value.
138140
case let tei as TupleExtractInst where tei.isEltOnlyNonTrivialElt:
139-
return tei.operands[0].value
140-
141-
// If we are forming a tuple and the tuple only has one element with reference
142-
// semantics, a retain_value on the tuple is equivalent to a retain value on
143-
// the tuple operand.
144-
case let ti as TupleInst:
145-
return ti.uniqueNonTrivialOperand
141+
return tei.operand
146142

147143
default:
148144
return nil
@@ -156,11 +152,8 @@ private extension Instruction {
156152
var candidateElt: Value?
157153
let function = self.function
158154

159-
// For each operand...
160155
for op in operands {
161-
// If the operand is not trivial...
162156
if !op.value.type.isTrivial(in: function) {
163-
// And we have not found a `candidateElt` yet, set index to `op` and continue.
164157
if candidateElt == nil {
165158
candidateElt = op.value
166159
continue
@@ -178,38 +171,16 @@ private extension Instruction {
178171
private extension TupleExtractInst {
179172
var isEltOnlyNonTrivialElt: Bool {
180173
let function = self.function
181-
// If the elt we are extracting is trivial, we cannot be a non-trivial
182-
// field... return false.
174+
183175
if type.isTrivial(in: function) {
184176
return false
185177
}
186178

187-
// Ok, we know that the elt we are extracting is non-trivial. Make sure that
188-
// we have no other non-trivial elts.
189179
let opType = operand.type
190-
let fieldNo = self.fieldIndex
191-
192-
// For each element index of the tuple...
193-
for (i, eltType) in opType.tupleElements.enumerated() {
194-
// If the element index is the one we are extracting, skip it...
195-
if i == fieldNo {
196-
continue
197-
}
198-
199-
// Otherwise check if we have a non-trivial type. If we don't have one,
200-
// continue.
201-
if eltType.isTrivial(in: function) {
202-
continue
203-
}
204180

205-
// If we do have a non-trivial type, return false. We have multiple
206-
// non-trivial types violating our condition.
207-
return false
208-
}
209-
210-
// We checked every other elt of the tuple and did not find any
211-
// non-trivial elt except for ourselves. Return `true``.
212-
return true
181+
return opType.tupleElements.filter {
182+
!$0.isTrivial(in: function)
183+
}.count == 1
213184
}
214185
}
215186

@@ -223,14 +194,8 @@ private extension StructExtractInst {
223194

224195
let structType = operand.type
225196

226-
for (i, fieldType) in structType.getStructFields(in: function).enumerated() {
227-
if i == fieldIndex || fieldType.isTrivial(in: function) {
228-
continue
229-
}
230-
231-
return false
232-
}
233-
234-
return true
197+
return structType.getStructFields(in: function).filter {
198+
!$0.isTrivial(in: function)
199+
}.count == 1
235200
}
236201
}

0 commit comments

Comments
 (0)