[swift-dev] High-level SIL Optimization: How do I get a FuncRef from the stdlib?

Arnold Schwaighofer aschwaighofer at apple.com
Wed Nov 16 18:11:03 CST 2016


> On Nov 16, 2016, at 2:58 PM, Ben Ng <me at benng.me> wrote:
> 
> Correct, that is what I am trying to do.
> 
>> On Nov 16, 2016, at 12:22 PM, Arnold Schwaighofer <aschwaighofer at apple.com> wrote:
>> 
>>  // Really, by the time you look at this in array value prop
>>  // this call should have been inline and you would see a call
>>  // to:
>>  // a.append(contentsOf: [1])
> 
> I do not understand this comment; I thought that inlining of stdlib functions happened after high-level SIL optimizations are run. Is my understanding incorrect?


Inlining of functions with @_semantics is delayed until after high-level SIL optimizations are run. Other functions are inlined.

  https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/Passes.cpp#L221
  https://github.com/apple/swift/blob/master/lib/SILOptimizer/Transforms/PerformanceInliner.cpp#L722


I recommend looking at the SIL function dump in ArrayElementValuePropagation of an example function after adding @semantics(“array.mutate_unknown”) to “append(contentsOf:)”.


$ git diff HEAD~
diff --git a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
index 76328a6..cb976f7 100644
--- a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
+++ b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
@@ -259,6 +259,8 @@ public:
   void run() override {
     auto &Fn = *getFunction();
 
+    Fn.dump();
+
     bool Changed = false;
 
     // Propagate the elements an of array value to its users.
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index f00cc23..2acfd06 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -1344,6 +1344,7 @@ extension ${Self} : RangeReplaceableCollection, _ArrayProtocol {
   /// - Parameter newElements: The elements to append to the array.
   ///
   /// - Complexity: O(*n*), where *n* is the length of the resulting array.
+  @_semantics("array.mutate_unknown")
   public mutating func append<C : Collection>(contentsOf newElements: C)
     where C.Iterator.Element == Element {
 

# Rebuild the compiler and stdlib (without stdlib assertions).
$ swift/utils/build-script -r  --assertions --no-swift-stdlib-assertions


$ cat TestArray.swift 
@inline(never)
public func test() {
  var a = [1, 2, 3]
  a += [1]
  print(a)
}

$ bin/swiftc -O 2>&1 | less
...
sil shared [_semantics "array.mutate_unknown"] @_TTSg5Si_GSaSi_GSaSi_s10Collections___TFSa6appenduRd__s10CollectionxzWd__8Iterator7Element_rfT10contentsOfqd___T_ : $@convention(method) (@owned Array<I
nt>, @inout Array<Int>) -> () {

…
// testArray() -> ()
sil [noinline] @_TF9TestArray9testArrayFT_T_ : $@convention(thin) () -> () {
bb0:
  %0 = alloc_stack $Array<Int>, var, name "a", loc "TestArray.swift":3:7, scope 2 // users: %54, %32, %60, %23, %43
  %1 = integer_literal $Builtin.Word, 3, loc "TestArray.swift":3:12, scope 2 // user: %4
  %2 = integer_literal $Builtin.Int64, 3, scope 5 // user: %3
  %3 = struct $Int (%2 : $Builtin.Int64), scope 5 // users: %22, %7
  %4 = alloc_ref [tail_elems $Int * %1 : $Builtin.Word] $_ContiguousArrayStorage<Int>, scope 5 // user: %7
  %5 = metatype $@thin Array<Int>.Type, scope 5   // users: %25, %7
  // function_ref specialized static Array._adoptStorage(_ContiguousArrayStorage<A>, count : Int) -> ([A], UnsafeMutablePointer<A>)
  %6 = function_ref @_TTSg5Si___TZFSa13_adoptStoragefTGCs23_ContiguousArrayStoragex_5countSi_TGSax_GSpx__ : $@convention(method) (@owned _ContiguousArrayStorage<Int>, Int, @thin Array<Int>.Type) -> (@
owned Array<Int>, UnsafeMutablePointer<Int>), scope 5 // users: %25, %7
  %7 = apply %6(%4, %3, %5) : $@convention(method) (@owned _ContiguousArrayStorage<Int>, Int, @thin Array<Int>.Type) -> (@owned Array<Int>, UnsafeMutablePointer<Int>), scope 5 // users: %9, %8
  %8 = tuple_extract %7 : $(Array<Int>, UnsafeMutablePointer<Int>), 0, scope 5 // user: %23
  %9 = tuple_extract %7 : $(Array<Int>, UnsafeMutablePointer<Int>), 1, scope 5 // user: %10
  %10 = struct_extract %9 : $UnsafeMutablePointer<Int>, #UnsafeMutablePointer._rawValue, scope 5 // user: %11
  %11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int, loc "TestArray.swift":3:12, scope 2 // users: %14, %21, %16
  %12 = integer_literal $Builtin.Int64, 1, loc "TestArray.swift":3:12, scope 2 // user: %13
  %13 = struct $Int (%12 : $Builtin.Int64), loc "TestArray.swift":3:12, scope 2 // users: %37, %30, %25, %14
  store %13 to %11 : $*Int, loc "TestArray.swift":3:12, scope 2 // id: %14
  %15 = integer_literal $Builtin.Word, 1, loc "TestArray.swift":3:15, scope 2 // users: %34, %24, %16
  %16 = index_addr %11 : $*Int, %15 : $Builtin.Word, loc "TestArray.swift":3:15, scope 2 // user: %19
  %17 = integer_literal $Builtin.Int64, 2, loc "TestArray.swift":3:15, scope 2 // user: %18
  %18 = struct $Int (%17 : $Builtin.Int64), loc "TestArray.swift":3:15, scope 2 // user: %19
  store %18 to %16 : $*Int, loc "TestArray.swift":3:15, scope 2 // id: %19
  %20 = integer_literal $Builtin.Word, 2, loc "TestArray.swift":3:18, scope 2 // user: %21
  %21 = index_addr %11 : $*Int, %20 : $Builtin.Word, loc "TestArray.swift":3:18, scope 2 // user: %22
  store %3 to %21 : $*Int, loc "TestArray.swift":3:18, scope 2 // id: %22
  store %8 to %0 : $*Array<Int>, loc "TestArray.swift":3:18, scope 2 // id: %23
  %24 = alloc_ref [tail_elems $Int * %15 : $Builtin.Word] $_ContiguousArrayStorage<Int>, scope 7 // user: %25
  %25 = apply %6(%24, %13, %5) : $@convention(method) (@owned _ContiguousArrayStorage<Int>, Int, @thin Array<Int>.Type) -> (@owned Array<Int>, UnsafeMutablePointer<Int>), scope 7 // users: %27, %26
  %26 = tuple_extract %25 : $(Array<Int>, UnsafeMutablePointer<Int>), 0, scope 7 // user: %32
  %27 = tuple_extract %25 : $(Array<Int>, UnsafeMutablePointer<Int>), 1, scope 7 // user: %28
  %28 = struct_extract %27 : $UnsafeMutablePointer<Int>, #UnsafeMutablePointer._rawValue, scope 7 // user: %29
  %29 = pointer_to_address %28 : $Builtin.RawPointer to [strict] $*Int, loc "TestArray.swift":4:9, scope 2 // user: %30
  store %13 to %29 : $*Int, loc "TestArray.swift":4:9, scope 2 // id: %30
  // function_ref specialized Array.append<A where ...> (contentsOf : A1) -> ()
  %31 = function_ref @_TTSg5Si_GSaSi_GSaSi_s10Collections___TFSa6appenduRd__s10CollectionxzWd__8Iterator7Element_rfT10contentsOfqd___T_ : $@convention(method) (@owned Array<Int>, @inout Array<Int>) -> (), scope 10 // user: %32
  %32 = apply %31(%26, %0) : $@convention(method) (@owned Array<Int>, @inout Array<Int>) -> (), scope 10


More information about the swift-dev mailing list