Revision d9b2fe601b793741633d77606c4618e63612fbb2 authored by Chris Lattner on 10 January 2016, 04:17:56 UTC, committed by Chris Lattner on 10 January 2016, 04:17:56 UTC
1 parent 0fbbf59
Raw File
inline_heuristics.sil
// RUN: rm -rf %t && mkdir -p %t
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -debug-only=sil-inliner -sil-inline-test-threshold=1 2>%t/log | FileCheck %s
// RUN: FileCheck -check-prefix=LOG %s < %t/log
// REQUIRES: asserts

// This test checks the inline heuristics based on the debug log output of
// the performance inliner.
// Checking the final sil is just a goodie.


sil_stage canonical

import Builtin
import Swift
import SwiftShims

struct Cont {
	var cl: (Int32) -> Int32
}

struct Cont2 {
	var tp: (Int32, (Int32) -> Int32)
}

enum E {
	case A
	case B((Int32) -> Int32)
}


// CHECK-LABEL: sil @testDirectClosure
// CHECK: [[C:%[0-9]+]] = thin_to_thick_function
// CHECK: apply [[C]](
// CHECK: return

// LOG-LABEL: Visiting Function: testDirectClosure 
// LOG: Eligible callee: takeDirectClosure
// LOG: Boost: apply const function

sil @testDirectClosure : $@convention(thin) () -> Int32 {
bb0:
  %0 = function_ref @takeDirectClosure : $@convention(thin) (@owned @callee_owned (Int32) -> Int32) -> Int32
  %1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
  %2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_owned (Int32) -> Int32
  %3 = apply %0(%2) : $@convention(thin) (@owned @callee_owned (Int32) -> Int32) -> Int32
  return %3 : $Int32
}

sil @takeDirectClosure : $@convention(thin) (@owned @callee_owned (Int32) -> Int32) -> Int32 {
bb0(%0 : $@callee_owned (Int32) -> Int32):
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %1 = integer_literal $Builtin.Int32, 27
  %2 = struct $Int32 (%1 : $Builtin.Int32)
  %3 = apply %0(%2) : $@callee_owned (Int32) -> Int32
  return %3 : $Int32
}


// CHECK-LABEL: sil @testStructClosure
// CHECK: [[C:%[0-9]+]] = struct_extract
// CHECK: apply [[C]](
// CHECK: return

// LOG-LABEL: Visiting Function: testStructClosure
// LOG: Eligible callee: takeStructClosure
// LOG: Boost: apply const function

sil @testStructClosure : $@convention(thin) () -> Int32 {
bb0:
  %0 = function_ref @takeStructClosure : $@convention(thin) (@owned Cont) -> Int32
  %1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
  %2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_owned (Int32) -> Int32
  %3 = struct $Cont (%2 : $@callee_owned (Int32) -> Int32)
  %4 = apply %0(%3) : $@convention(thin) (@owned Cont) -> Int32
  return %4 : $Int32
}

sil @takeStructClosure : $@convention(thin) (@owned Cont) -> Int32 {
bb0(%0 : $Cont):
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %1 = struct_extract %0 : $Cont, #Cont.cl
  %2 = integer_literal $Builtin.Int32, 27
  %3 = struct $Int32 (%2 : $Builtin.Int32)
  %4 = apply %1(%3) : $@callee_owned (Int32) -> Int32
  return %4 : $Int32
}


// CHECK-LABEL: sil @testStructAddrClosure
// CHECK: [[C:%[0-9]+]] = load
// CHECK: apply [[C]](
// CHECK: return

// LOG-LABEL: Visiting Function: testStructAddrClosure
// LOG: Eligible callee: takeStructAddrClosure
// LOG: Boost: apply const function

sil @testStructAddrClosure : $@convention(thin) () -> Int32 {
bb0:
  %0 = alloc_stack $Cont
  %1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
  %2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_owned (Int32) -> Int32
  %3 = struct $Cont (%2 : $@callee_owned (Int32) -> Int32)
  store %3 to %0 : $*Cont
  %5 = function_ref @takeStructAddrClosure : $@convention(thin) (@inout Cont) -> Int32
  %6 = apply %5(%0) : $@convention(thin) (@inout Cont) -> Int32
  %7 = struct_element_addr %0 : $*Cont, #Cont.cl
  %8 = load %7 : $*@callee_owned (Int32) -> Int32
  strong_release %8 : $@callee_owned (Int32) -> Int32
  dealloc_stack %0 : $*Cont
  return %6 : $Int32
}

sil @takeStructAddrClosure : $@convention(thin) (@inout Cont) -> Int32 {
bb0(%0 : $*Cont):
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %1 = struct_element_addr %0 : $*Cont, #Cont.cl
  %2 = load %1 : $*@callee_owned (Int32) -> Int32
  %3 = integer_literal $Builtin.Int32, 27
  %4 = struct $Int32 (%3 : $Builtin.Int32)
  strong_retain %2 : $@callee_owned (Int32) -> Int32
  %6 = apply %2(%4) : $@callee_owned (Int32) -> Int32
  return %6 : $Int32
}


// CHECK-LABEL: sil @testTupleClosure
// CHECK: [[C:%[0-9]+]] = tuple_extract
// CHECK: apply [[C]](
// CHECK: return

// LOG-LABEL: Visiting Function: testTupleClosure
// LOG: Eligible callee: takeTupleClosure
// LOG: Boost: apply const function

sil @testTupleClosure : $@convention(thin) () -> Int32 {
bb0:
  %0 = function_ref @takeTupleClosure : $@convention(thin) (@owned Cont2) -> Int32
  %1 = integer_literal $Builtin.Int32, 27
  %2 = struct $Int32 (%1 : $Builtin.Int32)
  %3 = function_ref @closure : $@convention(thin) (Int32) -> Int32
  %4 = thin_to_thick_function %3 : $@convention(thin) (Int32) -> Int32 to $@callee_owned (Int32) -> Int32
  %5 = tuple (%2 : $Int32, %4 : $@callee_owned (Int32) -> Int32)
  %6 = struct $Cont2 (%5 : $(Int32, @callee_owned (Int32) -> Int32))
  %7 = apply %0(%6) : $@convention(thin) (@owned Cont2) -> Int32
  return %7 : $Int32
}


sil @takeTupleClosure : $@convention(thin) (@owned Cont2) -> Int32 {
bb0(%0 : $Cont2):
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %1 = struct_extract %0 : $Cont2, #Cont2.tp
  %2 = tuple_extract %1 : $(Int32, @callee_owned (Int32) -> Int32), 1
  %3 = integer_literal $Builtin.Int32, 27
  %4 = struct $Int32 (%3 : $Builtin.Int32)
  %5 = apply %2(%4) : $@callee_owned (Int32) -> Int32
  return %5 : $Int32
}

// CHECK-LABEL: sil @testEnumClosure
// CHECK: [[C:%[0-9]+]] = unchecked_enum_data
// CHECK: apply [[C]](
// CHECK: return

// LOG-LABEL: Visiting Function: testEnumClosure
// LOG: Eligible callee: takeEnumClosure
// LOG: Boost: apply const function

sil @testEnumClosure : $@convention(thin) () -> Int32 {
bb0:
  %0 = function_ref @takeEnumClosure : $@convention(thin) (@owned E) -> Int32
  %1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
  %2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_owned (Int32) -> Int32
  %3 = enum $E, #E.B!enumelt.1, %2 : $@callee_owned (Int32) -> Int32
  %4 = apply %0(%3) : $@convention(thin) (@owned E) -> Int32
  return %4 : $Int32
}


sil @takeEnumClosure : $@convention(thin) (@owned E) -> Int32 {
bb0(%0 : $E):
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %1 = unchecked_enum_data %0 : $E, #E.B!enumelt.1
  %2 = integer_literal $Builtin.Int32, 27
  %3 = struct $Int32 (%2 : $Builtin.Int32)
  %4 = apply %1(%3) : $@callee_owned (Int32) -> Int32
  return %4 : $Int32
}

// The closure which is used by all tests above.

sil shared @closure : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
  %1 = integer_literal $Builtin.Int32, 1
  %2 = struct_extract %0 : $Int32, #Int32._value
  %3 = integer_literal $Builtin.Int1, -1
  %4 = builtin "sadd_with_overflow_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32, %3 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
  %5 = tuple_extract %4 : $(Builtin.Int32, Builtin.Int1), 0
  %6 = tuple_extract %4 : $(Builtin.Int32, Builtin.Int1), 1
  cond_fail %6 : $Builtin.Int1
  %8 = struct $Int32 (%5 : $Builtin.Int32)
  return %8 : $Int32
}

// CHECK-LABEL: sil @testCondBr
// CHECK-NOT: apply
// CHECK: builtin "assert_configuration"()
// CHECK-NOT: apply
// CHECK: return %{{.*}} : $()

// LOG-LABEL: Visiting Function: testCondBr
// LOG: Eligible callee: condBrCallee
// LOG: Take bb1 of cond_br

sil @testCondBr : $@convention(thin) () -> () {
bb0:

  %0 = function_ref @condBrCallee : $@convention(thin) (Int32) -> Int32
  %1 = integer_literal $Builtin.Int32, 27
  %2 = struct $Int32 (%1 : $Builtin.Int32)
  %3 = apply %0(%2) : $@convention(thin) (Int32) -> Int32
  %4 = tuple ()
  return %4 : $()
}

sil @condBrCallee : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
  %1 = integer_literal $Builtin.Int32, 27
  %2 = struct_extract %0 : $Int32, #Int32._value
  %3 = builtin "cmp_eq_Word"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
  cond_br %3, bb1, bb2

bb1:
  br bb3(%0 : $Int32)

bb2:
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %6 = struct $Int32 (%1 : $Builtin.Int32)
  br bb3(%6 : $Int32)

bb3(%8 : $Int32):
  return %8 : $Int32
}

// CHECK-LABEL: sil @testSwitchValue
// CHECK-NOT: apply
// CHECK: builtin "assert_configuration"()
// CHECK-NOT: apply
// CHECK: return %{{.*}} : $()

// LOG-LABEL: Visiting Function: testSwitchValue
// LOG: Eligible callee: switchValueCallee
// LOG: Take bb2 of switch_value

sil @testSwitchValue : $@convention(thin) () -> () {
bb0:

  %0 = function_ref @switchValueCallee : $@convention(thin) (Int32) -> Int32
  %1 = integer_literal $Builtin.Int32, 28
  %2 = struct $Int32 (%1 : $Builtin.Int32)
  %3 = apply %0(%2) : $@convention(thin) (Int32) -> Int32
  %4 = tuple ()
  return %4 : $()
}

sil @switchValueCallee : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
  %1 = integer_literal $Builtin.Int32, 27
  %2 = integer_literal $Builtin.Int32, 28
  %3 = struct_extract %0 : $Int32, #Int32._value
  switch_value %3 : $Builtin.Int32, case %1 : bb1, case %2 : bb2, default bb3

bb1:
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  br bb4(%1 : $Builtin.Int32)

bb2:
  br bb4(%2 : $Builtin.Int32)

bb3:
  // make inline costs = 2
  %c3 = builtin "assert_configuration"() : $Builtin.Int32
  %c4 = builtin "assert_configuration"() : $Builtin.Int32

  br bb4(%1 : $Builtin.Int32)

bb4(%8 : $Builtin.Int32):
  %9 = struct $Int32 (%8 : $Builtin.Int32)
  return %9 : $Int32
}

// CHECK-LABEL: sil @testSwitchEnum
// CHECK-NOT: apply
// CHECK: builtin "assert_configuration"()
// CHECK-NOT: apply
// CHECK: return %{{.*}} : $()

// LOG-LABEL: Visiting Function: testSwitchEnum
// LOG: Eligible callee: switchEnumCallee
// LOG: Take bb1 of switch_enum


sil @testSwitchEnum : $@convention(thin) () -> () {
bb0:
  %0 = function_ref @switchEnumCallee : $@convention(thin) (Optional<Int32>) -> Int32
  %1 = integer_literal $Builtin.Int32, 27
  %2 = struct $Int32 (%1 : $Builtin.Int32)
  %3 = enum $Optional<Int32>, #Optional.Some!enumelt.1, %2 : $Int32
  %4 = apply %0(%3) : $@convention(thin) (Optional<Int32>) -> Int32
  %5 = tuple ()
  return %5 : $()
}

sil @switchEnumCallee : $@convention(thin) (Optional<Int32>) -> Int32 {
bb0(%0 : $Optional<Int32>):
  switch_enum %0 : $Optional<Int32>, case #Optional.Some!enumelt.1: bb1, case #Optional.None!enumelt: bb2

bb1:
  %2 = unchecked_enum_data %0 : $Optional<Int32>, #Optional.Some!enumelt.1
  br bb3(%2 : $Int32)

bb2:
  // make inline costs = 2
  %c1 = builtin "assert_configuration"() : $Builtin.Int32
  %c2 = builtin "assert_configuration"() : $Builtin.Int32

  %4 = integer_literal $Builtin.Int32, 0
  %5 = struct $Int32 (%4 : $Builtin.Int32)
  br bb3(%5 : $Int32)

bb3(%7 : $Int32):
  return %7 : $Int32
}

back to top