Files
swift-mirror/test/SILOptimizer/allocboxtostack_localapply_ossa.sil
Erik Eckstein 6714a72256 Optimizer: re-implement and improve the AllocBoxToStack pass
This pass replaces `alloc_box` with `alloc_stack` if the box is not escaping.
The original implementation had some limitations. It could not handle cases of local functions which are called multiple times or even recursively, e.g.

```
public func foo() -> Int {
  var i = 1

  func localFunction() { i += 1 }

  localFunction()
  localFunction()
  return i
}

```

The new implementation (done in Swift) fixes this problem with a new algorithm.
It's not only more powerful, but also simpler: the new pass has less than half lines of code than the old pass.

The pass is invoked in the mandatory pipeline and later in the optimizer pipeline.
The new implementation provides a module-pass for the mandatory pipeline (whereas the "regular" pass is a function pass).
This is required because the mandatory pass needs to remove originals of specialized closures, which cannot be done from a function-pass.
In the old implementation this was done with a hack by adding a semantic attribute and deleting the function later in the pipeline.

I still kept the sources of the old pass for being able to bootstrap the compiler without a host compiler.

rdar://142756547
2025-06-20 08:15:04 +02:00

551 lines
24 KiB
Plaintext

// RUN: %target-sil-opt -enable-copy-propagation=requested-passes-only -enable-lexical-lifetimes=false %s -allocbox-to-stack -sil-deadfuncelim | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
import SwiftShims
sil hidden [noinline] [ossa] [Onone] @$blackhole : $@convention(thin) <T> (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testapply :
// CHECK-NOT: alloc_box
// CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x"
// CHECK-LABEL: } // end sil function '$testapply'
sil [noinline] [ossa] @$testapply : $@convention(thin) () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = function_ref @$testapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%6 = apply %5(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
destroy_value %0 : ${ var Int64 }
%8 = tuple ()
return %8 : $()
}
sil private [noinline] [ossa] @$testapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = begin_access [read] [dynamic] %1 : $*Int64
%4 = load [trivial] %3 : $*Int64
end_access %3 : $*Int64
%6 = alloc_stack $Int64
store %4 to [trivial] %6 : $*Int64
%8 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%9 = apply %8<Int64>(%6) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %6 : $*Int64
%11 = tuple ()
return %11 : $()
}
sil private [noinline] [ossa] @$testapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testtryapply :
// CHECK-NOT: alloc_box
// CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x"
// CHECK-LABEL: } // end sil function '$testtryapply'
sil [noinline] [ossa] @$testtryapply : $@convention(thin) () -> @error any Error {
bb0:
%1 = alloc_box ${ var Int64 }, var, name "x"
%2 = project_box %1 : ${ var Int64 }, 0
%3 = integer_literal $Builtin.Int64, 0
%4 = struct $Int64 (%3 : $Builtin.Int64)
store %4 to [trivial] %2 : $*Int64
%6 = function_ref @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error
try_apply %6(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2
bb1(%8 : $()):
destroy_value %1 : ${ var Int64 }
%10 = tuple ()
return %10 : $()
bb2(%12 : $Error):
destroy_value %1 : ${ var Int64 }
throw %12 : $Error
}
sil private [noinline] [ossa] @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error {
bb0(%0 : @guaranteed ${ var Int64 }):
%2 = project_box %0 : ${ var Int64 }, 0
%4 = begin_access [read] [dynamic] %2 : $*Int64
%5 = load [trivial] %4 : $*Int64
end_access %4 : $*Int64
%7 = alloc_stack $Int64
store %5 to [trivial] %7 : $*Int64
%9 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%10 = apply %9<Int64>(%7) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %7 : $*Int64
%12 = tuple ()
return %12 : $()
}
sil private [noinline] [ossa] @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error {
bb0(%0 : @guaranteed ${ var Int64 }):
%2 = project_box %0 : ${ var Int64 }, 0
%4 = function_ref @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error
try_apply %4(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2
bb1(%6 : $()):
%7 = tuple ()
return %7 : $()
bb2(%9 : $Error):
throw %9 : $Error
}
// CHECK-LABEL: sil [noinline] [ossa] @$testpartialapply :
// CHECK-NOT: alloc_box
// CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x"
// CHECK-LABEL: } // end sil function '$testpartialapply'
sil [noinline] [ossa] @$testpartialapply : $@convention(thin) () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = function_ref @$testpartialapplyclosure : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%6 = apply %5(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
destroy_value %0 : ${ var Int64 }
%8 = tuple ()
return %8 : $()
}
sil private [noinline] [ossa] @$testpartialapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = begin_access [read] [dynamic] %1 : $*Int64
%4 = load [trivial] %3 : $*Int64
end_access %3 : $*Int64
%6 = alloc_stack $Int64
store %4 to [trivial] %6 : $*Int64
%8 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%9 = apply %8<Int64>(%6) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %6 : $*Int64
%11 = tuple ()
return %11 : $()
}
sil private [noinline] [ossa] @$testpartialapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testpartialapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%5 = tuple ()
return %5 : $()
}
sil private [ossa] @$testpartialapplyclosure : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testpartialapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testtwoboxes :
// CHECK-NOT: alloc_box
// CHECK: [[STK1:%.*]] = alloc_stack $Int64, var, name "x"
// CHECK: [[STK2:%.*]] = alloc_stack $Int64, var, name "y"
// CHECK-LABEL: } // end sil function '$testtwoboxes'
sil [noinline] [ossa] @$testtwoboxes : $@convention(thin) () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = alloc_box ${ var Int64 }, var, name "y"
%6 = project_box %5 : ${ var Int64 }, 0
%7 = integer_literal $Builtin.Int64, 0
%8 = struct $Int64 (%7 : $Builtin.Int64)
store %8 to [trivial] %6 : $*Int64
%10 = function_ref @$testtwoboxesbas : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> ()
%11 = apply %10(%0, %5) : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> ()
destroy_value %5 : ${ var Int64 }
destroy_value %0 : ${ var Int64 }
%14 = tuple ()
return %14 : $()
}
sil private [noinline] [ossa] @$testtwoboxesbar : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }, %1 : @guaranteed ${ var Int64 }):
%2 = project_box %0 : ${ var Int64 }, 0
%4 = project_box %1 : ${ var Int64 }, 0
%6 = begin_access [read] [dynamic] %2 : $*Int64
%7 = load [trivial] %6 : $*Int64
end_access %6 : $*Int64
%9 = alloc_stack $Int64
store %7 to [trivial] %9 : $*Int64
%11 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%12 = apply %11<Int64>(%9) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %9 : $*Int64
%14 = begin_access [read] [dynamic] %4 : $*Int64
%15 = load [trivial] %14 : $*Int64
end_access %14 : $*Int64
%17 = alloc_stack $Int64
store %15 to [trivial] %17 : $*Int64
%19 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%20 = apply %19<Int64>(%17) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %17 : $*Int64
%22 = tuple ()
return %22 : $()
}
sil private [noinline] [ossa] @$testtwoboxesbas : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }, %1 : @guaranteed ${ var Int64 }):
%2 = project_box %0 : ${ var Int64 }, 0
%4 = project_box %1 : ${ var Int64 }, 0
%6 = function_ref @$testtwoboxesbar : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> ()
%7 = apply %6(%0, %1) : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> ()
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testboxescapes :
// CHECK: alloc_box ${ var Int64 }, var, name "x"
// CHECK-LABEL: } // end sil function '$testboxescapes'
sil [noinline] [ossa] @$testboxescapes : $@convention(thin) () -> @owned @callee_guaranteed () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = function_ref @$testboxescapesbas : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> ()
%6 = apply %5(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> ()
destroy_value %0 : ${ var Int64 }
return %6 : $@callee_guaranteed () -> ()
}
sil private [noinline] [ossa] @$testboxescapesbar : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testboxescapesclosure : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%copy = copy_value %0 : ${ var Int64 }
%5 = partial_apply [callee_guaranteed] %3(%copy) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
return %5 : $@callee_guaranteed () -> ()
}
sil private [ossa] @$testboxescapesclosure : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = load [trivial] %1 : $*Int64
%4 = tuple ()
return %4 : $()
}
sil private [noinline] [ossa] @$testboxescapesbas : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testboxescapesbar : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @owned @callee_guaranteed () -> ()
return %4 : $@callee_guaranteed () -> ()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testrecur :
// CHECK: alloc_stack $Int64, var, name "x"
// CHECK-LABEL: } // end sil function '$testrecur'
sil [noinline] [ossa] @$testrecur : $@convention(thin) () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = function_ref @$testrecurbas : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%6 = apply %5(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%7 = function_ref @$testrecurbar : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%8 = apply %7(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
destroy_value %0 : ${ var Int64 }
%10 = tuple ()
return %10 : $()
}
sil private [noinline] [ossa] @$testrecurbar : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = begin_access [read] [dynamic] %1 : $*Int64
%4 = load [trivial] %3 : $*Int64
end_access %3 : $*Int64
%6 = alloc_stack $Int64
store %4 to [trivial] %6 : $*Int64
%8 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%9 = apply %8<Int64>(%6) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %6 : $*Int64
%11 = function_ref @$testrecurbas : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%12 = apply %11(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%13 = tuple ()
return %13 : $()
}
sil private [noinline] [ossa] @$testrecurbas : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testrecurbar : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil [noinline] [ossa] @$testbeginapply :
// CHECK-NOT: alloc_box
// CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x"
// CHECK-LABEL: } // end sil function '$testbeginapply'
sil [noinline] [ossa] @$testbeginapply : $@convention(thin) () -> () {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = function_ref @$testbeginapplybas : $@yield_once @convention(thin) (@guaranteed { var Int64 }) -> @yields ()
(%addr, %token) = begin_apply %5(%0) : $@yield_once @convention(thin) (@guaranteed { var Int64 }) -> @yields ()
end_apply %token as $()
destroy_value %0 : ${ var Int64 }
%8 = tuple ()
return %8 : $()
}
sil private [noinline] [ossa] @$testbeginapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = begin_access [read] [dynamic] %1 : $*Int64
%4 = load [trivial] %3 : $*Int64
end_access %3 : $*Int64
%6 = alloc_stack $Int64
store %4 to [trivial] %6 : $*Int64
%8 = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%9 = apply %8<Int64>(%6) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %6 : $*Int64
%11 = tuple ()
return %11 : $()
}
sil private [noinline] [ossa] @$testbeginapplybas : $@yield_once @convention(thin) (@guaranteed { var Int64 }) -> @yields () {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%3 = function_ref @$testbeginapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%4 = apply %3(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> ()
%5 = tuple ()
yield %5 : $(), resume bb1, unwind bb2
bb1:
%rv = tuple()
return %rv : $()
bb2:
unwind
}
struct Int {
var _value: Builtin.Int64
}
// Test to make sure AppliesToSpecialize in AllocBoxToStack is populated correctly when there are common function calls for multiple allox_boxes.
// Order of function calls constructed in PromotedOperands: bar common bas common.
// AppliesToSpecialize should have the order: bar bas common.
// Only then, the functions get specialized correctly, and we won't see an assert in checkNoPromotedBoxInApply.
// CHECK-LABEL: sil [noinline] [ossa] @$testdfs1 :
// CHECK-NOT: alloc_box ${ var Int64 }, var, name "x"
// CHECK-NOT: alloc_box ${ var Int64 }, var, name "y"
// CHECK-LABEL:} // end sil function '$testdfs1'
sil [noinline] [ossa] @$testdfs1 : $@convention(thin) () -> Int64 {
bb0:
%0 = alloc_box ${ var Int64 }, var, name "x"
%1 = project_box %0 : ${ var Int64 }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int64
%5 = alloc_box ${ var Int64 }, var, name "y"
%6 = project_box %5 : ${ var Int64 }, 0
%7 = integer_literal $Builtin.Int64, 0
%8 = struct $Int64 (%7 : $Builtin.Int64)
store %8 to [trivial] %6 : $*Int64
%10 = function_ref @$testdfs1common : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> Int64
%11 = apply %10(%0, %5) : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> Int64
destroy_value %5 : ${ var Int64 }
destroy_value %0 : ${ var Int64 }
return %11 : $Int64
}
sil private [noinline] [ossa] @$testdfs1common : $@convention(thin) (@guaranteed { var Int64 }, @guaranteed { var Int64 }) -> Int64 {
bb0(%0 : @guaranteed ${ var Int64 }, %1 : @guaranteed ${ var Int64 }):
%proj1 = project_box %0 : ${ var Int64 }, 0
%proj2 = project_box %1 : ${ var Int64 }, 0
%barfunc = function_ref @$testdfs1bar : $@convention(thin) (@guaranteed { var Int64 }) -> Int64
%res1 = apply %barfunc(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> Int64
%basfunc = function_ref @$testdfs1bas : $@convention(thin) (@guaranteed { var Int64 }) -> Int64
%res2 = apply %basfunc(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> Int64
%func = function_ref @$blackhole : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%tmp1 = apply %func<Int64>(%proj1) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%tmp2 = apply %func<Int64>(%proj2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%res = load [trivial] %proj1 : $*Int64
return %res : $Int64
}
sil private [noinline] [ossa] @$testdfs1bar : $@convention(thin) (@guaranteed { var Int64 }) -> Int64 {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%4 = load [trivial] %1 : $*Int64
return %4 : $Int64
}
sil private [noinline] [ossa] @$testdfs1bas : $@convention(thin) (@guaranteed { var Int64 }) -> Int64 {
bb0(%0 : @guaranteed ${ var Int64 }):
%1 = project_box %0 : ${ var Int64 }, 0
%4 = load [trivial] %1 : $*Int64
return %4 : $Int64
}
// CHECK-LABEL: sil [noinline] [ossa] @$testdfs2 :
// CHECK: alloc_stack $Int, var, name "x"
// CHECK: alloc_stack $Int, var, name "y"
// CHECK-LABEL: } // end sil function '$testdfs2'
sil [noinline] [ossa] @$testdfs2 : $@convention(thin) () -> Int {
bb0:
%0 = alloc_box ${ var Int }, var, name "x"
%1 = project_box %0 : ${ var Int }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int (%2 : $Builtin.Int64)
store %3 to [trivial] %1 : $*Int
%5 = alloc_box ${ var Int }, var, name "y"
%6 = project_box %5 : ${ var Int }, 0
%7 = integer_literal $Builtin.Int64, 0
%8 = struct $Int (%7 : $Builtin.Int64)
store %8 to [trivial] %6 : $*Int
%10 = function_ref @$testdfs2local1 : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%11 = apply %10(%0, %5) : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%12 = function_ref @$testdfs2local2 : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%13 = apply %12(%0, %5) : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%14 = struct_extract %11 : $Int, #Int._value
%15 = struct_extract %13 : $Int, #Int._value
%16 = integer_literal $Builtin.Int1, -1
%17 = builtin "sadd_with_overflow_Int64"(%14 : $Builtin.Int64, %15 : $Builtin.Int64, %16 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
(%18, %19) = destructure_tuple %17 : $(Builtin.Int64, Builtin.Int1)
cond_fail %19 : $Builtin.Int1, "arithmetic overflow"
%21 = struct $Int (%18 : $Builtin.Int64)
destroy_value %5 : ${ var Int }
destroy_value %0 : ${ var Int }
return %21 : $Int
}
// CHECK-LABEL: sil private [noinline] [ossa] @$s12$testdfs2barTf0s_n : $@convention(thin) (@inout_aliasable Int) -> Int {
sil private [noinline] [ossa] @$testdfs2bar : $@convention(thin) (@guaranteed { var Int }) -> Int {
bb0(%0 : @guaranteed ${ var Int }):
%1 = project_box %0 : ${ var Int }, 0
%4 = load [trivial] %1 : $*Int
return %4 : $Int
}
// CHECK-LABEL: sil private [noinline] [ossa] @$s12$testdfs2basTf0s_n : $@convention(thin) (@inout_aliasable Int) -> Int {
sil private [noinline] [ossa] @$testdfs2bas : $@convention(thin) (@guaranteed { var Int }) -> Int {
bb0(%0 : @guaranteed ${ var Int }):
%1 = project_box %0 : ${ var Int }, 0
%4 = load [trivial] %1 : $*Int
return %4 : $Int
}
// CHECK-LABEL: sil private [noinline] [ossa] @$s20$testdfs2innercommonTf0ss_n : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int) -> Int {
sil private [noinline] [ossa] @$testdfs2innercommon : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int {
bb0(%0 : @guaranteed ${ var Int }, %1 : @guaranteed ${ var Int }):
%2 = project_box %0 : ${ var Int }, 0
%4 = project_box %1 : ${ var Int }, 0
%8 = function_ref @$testdfs2bar : $@convention(thin) (@guaranteed { var Int }) -> Int
%9 = apply %8(%0) : $@convention(thin) (@guaranteed { var Int }) -> Int
%11 = function_ref @$testdfs2bas : $@convention(thin) (@guaranteed { var Int }) -> Int
%12 = apply %11(%1) : $@convention(thin) (@guaranteed { var Int }) -> Int
return %12 : $Int
}
// CHECK-LABEL: sil private [noinline] [ossa] @$s15$testdfs2local1Tf0ss_n : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int) -> Int {
sil private [noinline] [ossa] @$testdfs2local1 : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int {
bb0(%0 : @guaranteed ${ var Int }, %1 : @guaranteed ${ var Int }):
%2 = project_box %0 : ${ var Int }, 0
%4 = project_box %1 : ${ var Int }, 0
%7 = function_ref @$testdfs2innercommon : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%8 = apply %7(%0, %1) : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
return %8 : $Int
}
// CHECK-LABEL: sil private [noinline] [ossa] @$s15$testdfs2local2Tf0ss_n : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int) -> Int {
sil private [noinline] [ossa] @$testdfs2local2 : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int {
bb0(%0 : @guaranteed ${ var Int }, %1 : @guaranteed ${ var Int }):
%2 = project_box %0 : ${ var Int }, 0
%4 = project_box %1 : ${ var Int }, 0
%7 = function_ref @$testdfs2innercommon : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
%8 = apply %7(%0, %1) : $@convention(thin) (@guaranteed { var Int }, @guaranteed { var Int }) -> Int
return %8 : $Int
}
class C {}
sil @getC : $@convention(thin) () -> (@owned C)
sil [ossa] @borrow_c_box : $@convention(thin) (@guaranteed { var C }) -> () {
entry(%box : @guaranteed ${var C}):
%retval = tuple ()
return %retval : $()
}
// CHECK-LABEL: sil [ossa] @test_copy_applied : {{.*}} {
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply
// CHECK: [[COPY:%[^,]+]] = copy_value [[CLOSURE]]
// CHECK: destroy_value [[CLOSURE]]
// CHECK: apply [[COPY]]()
// CHECK: destroy_addr
// CHECK: dealloc_stack
// CHECK-LABEL: } // end sil function 'test_copy_applied'
sil [ossa] @test_copy_applied : $@convention(thin) () -> () {
bb0:
%box = alloc_box ${ var C }, var, name "x"
%addr = project_box %box : ${ var C }, 0
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
%c = apply %getC() : $@convention(thin) () -> (@owned C)
store %c to [init] %addr : $*C
%borrow_int_box = function_ref @borrow_c_box : $@convention(thin) (@guaranteed { var C }) -> ()
%closure = partial_apply [callee_guaranteed] %borrow_int_box(%box) : $@convention(thin) (@guaranteed { var C }) -> ()
%copy = copy_value %closure : $@callee_guaranteed () -> ()
destroy_value %closure : $@callee_guaranteed () -> ()
apply %copy() : $@callee_guaranteed () -> ()
destroy_value %copy : $@callee_guaranteed () -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK-LABEL: sil [ossa] @test_move_applied : {{.*}} {
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply
// CHECK: [[MOVE:%[^,]+]] = move_value [[CLOSURE]]
// CHECK: apply [[MOVE]]()
// CHECK: destroy_addr
// CHECK: dealloc_stack
// CHECK-LABEL: } // end sil function 'test_move_applied'
sil [ossa] @test_move_applied : $@convention(thin) () -> () {
bb0:
%box = alloc_box ${ var C }, var, name "x"
%addr = project_box %box : ${ var C }, 0
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
%c = apply %getC() : $@convention(thin) () -> (@owned C)
store %c to [init] %addr : $*C
%borrow_int_box = function_ref @borrow_c_box : $@convention(thin) (@guaranteed { var C }) -> ()
%closure = partial_apply [callee_guaranteed] %borrow_int_box(%box) : $@convention(thin) (@guaranteed { var C }) -> ()
%move = move_value %closure : $@callee_guaranteed () -> ()
apply %move() : $@callee_guaranteed () -> ()
destroy_value %move : $@callee_guaranteed () -> ()
%retval = tuple ()
return %retval : $()
}