Skip to content

Commit c4096bc

Browse files
committed
Swift Optimizer: simplify builtin "once"
If the callee is side effect-free we can remove the whole builtin "once".
1 parent 9b51e69 commit c4096bc

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ extension BuiltinInst : OnoneSimplifyable {
2222
optimizeIsConcrete(allowArchetypes: false, context)
2323
case .IsSameMetatype:
2424
optimizeIsSameMetatype(context)
25+
case .Once:
26+
optimizeBuiltinOnce(context)
2527
default:
2628
if let literal = constantFold(context) {
2729
uses.replaceAll(with: literal, context)
@@ -65,6 +67,29 @@ private extension BuiltinInst {
6567

6668
uses.replaceAll(with: result, context)
6769
}
70+
71+
func optimizeBuiltinOnce(_ context: SimplifyContext) {
72+
guard let callee = calleeOfOnce, callee.isDefinition else {
73+
return
74+
}
75+
// If the callee is side effect-free we can remove the whole builtin "once".
76+
// We don't use the callee's memory effects but instead look at all callee instructions
77+
// because memory effects are not computed in the Onone pipeline, yet.
78+
// This is no problem because the callee (usually a global init function )is mostly very small,
79+
// or contains the side-effect instruction `alloc_global` right at the beginning.
80+
if callee.instructions.contains(where: { $0.mayReadOrWriteMemory || $0.hasUnspecifiedSideEffects }) {
81+
return
82+
}
83+
context.erase(instruction: self)
84+
}
85+
86+
var calleeOfOnce: Function? {
87+
let callee = operands[1].value
88+
if let fri = callee as? FunctionRefInst {
89+
return fri.referencedFunction
90+
}
91+
return nil
92+
}
6893
}
6994

7095
private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Function) -> Bool? {

test/SILOptimizer/simplify_builtin.sil

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,61 @@ bb0:
264264
%4 = builtin "is_same_metatype"(%2 : $@thick Any.Type, %3 : $@thick Any.Type) : $Builtin.Int1
265265
return %4 : $Builtin.Int1
266266
}
267+
268+
sil_global hidden [let] @g : $Int32
269+
270+
sil [global_init_once_fn] @side_effect_free_init : $@convention(c) () -> () {
271+
bb0:
272+
%1 = global_addr @g : $*Int32
273+
%2 = integer_literal $Builtin.Int32, 10
274+
%3 = struct $Int32 (%2 : $Builtin.Int32)
275+
%6 = tuple ()
276+
return %6 : $()
277+
}
278+
279+
sil [global_init_once_fn] @init_with_side_effect : $@convention(c) () -> () {
280+
bb0:
281+
alloc_global @g
282+
%1 = global_addr @g : $*Int32
283+
%2 = integer_literal $Builtin.Int32, 10
284+
%3 = struct $Int32 (%2 : $Builtin.Int32)
285+
store %3 to %1 : $*Int32
286+
%6 = tuple ()
287+
return %6 : $()
288+
}
289+
290+
sil [global_init_once_fn] @unknown_init : $@convention(c) () -> ()
291+
292+
// CHECK-LABEL: sil @remove_builtin_once :
293+
// CHECK-NOT: builtin
294+
// CHECK: } // end sil function 'remove_builtin_once'
295+
sil @remove_builtin_once : $@convention(thin) (Builtin.RawPointer) -> () {
296+
bb0(%0 : $Builtin.RawPointer):
297+
%1 = function_ref @side_effect_free_init : $@convention(c) () -> ()
298+
%2 = builtin "once"(%0 : $Builtin.RawPointer, %1 : $@convention(c) () -> ()) : $()
299+
%3 = tuple ()
300+
return %3 : $()
301+
}
302+
303+
// CHECK-LABEL: sil @dont_remove_builtin_once_side_effect :
304+
// CHECK: builtin
305+
// CHECK: } // end sil function 'dont_remove_builtin_once_side_effect'
306+
sil @dont_remove_builtin_once_side_effect : $@convention(thin) (Builtin.RawPointer) -> () {
307+
bb0(%0 : $Builtin.RawPointer):
308+
%1 = function_ref @init_with_side_effect : $@convention(c) () -> ()
309+
%2 = builtin "once"(%0 : $Builtin.RawPointer, %1 : $@convention(c) () -> ()) : $()
310+
%3 = tuple ()
311+
return %3 : $()
312+
}
313+
314+
// CHECK-LABEL: sil @dont_remove_builtin_once_unknown :
315+
// CHECK: builtin
316+
// CHECK: } // end sil function 'dont_remove_builtin_once_unknown'
317+
sil @dont_remove_builtin_once_unknown : $@convention(thin) (Builtin.RawPointer) -> () {
318+
bb0(%0 : $Builtin.RawPointer):
319+
%1 = function_ref @unknown_init : $@convention(c) () -> ()
320+
%2 = builtin "once"(%0 : $Builtin.RawPointer, %1 : $@convention(c) () -> ()) : $()
321+
%3 = tuple ()
322+
return %3 : $()
323+
}
324+

0 commit comments

Comments
 (0)