Commits
Chris Lattner committed b84fd184198
implement support for full conditional init/assign processing of tuple elements,
generating the appropriate shifting and or'ing of bits in our liveness mask to
treat each tuple element separately. This allows us to compile something like:
func test(cond : Bool) {
var x : (SomeClass, SomeClass)
if cond {
x.0 = getSomeClass()
} else {
x.1 = getSomeClass()
}
x.0 = getSomeClass()
x.1 = x.0
}
into:
sil @_T1t4testFT4condSb_T_ : $@thin (Bool) -> () {
bb0(%0 : $Bool):
%1 = builtin_function_ref "or_Int2" : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // users: %40, %24, %15, %57
%2 = alloc_stack $Builtin.Int2 // var x // users: %41, %39, %25, %23, %16, %14, %58, %56, %45, %31, %7, %64
%3 = alloc_stack $Bool // var cond // users: %62, %4
store %0 to %3#1 : $*Bool // id: %4
%5 = alloc_stack $(SomeClass, SomeClass) // var x // users: %52, %35, %61, %60, %12, %21, %30, %43, %44
%6 = integer_literal $Builtin.Int2, 0 // user: %7
store %6 to %2#1 : $*Builtin.Int2 // id: %7
%8 = struct_extract %0 : $Bool, #value // user: %9
cond_br %8, bb1, bb2 // id: %9
bb1: // Preds: bb0
// function_ref t.getSomeClass () -> t.SomeClass
%10 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %11
%11 = apply %10() : $@thin () -> @owned SomeClass // user: %17
%12 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %17
%13 = integer_literal $Builtin.Int2, 1 // user: %15
%14 = load %2#1 : $*Builtin.Int2 // user: %15
%15 = apply %1(%14, %13) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %16
store %15 to %2#1 : $*Builtin.Int2 // id: %16
store %11 to %12 : $*SomeClass // id: %17
br bb3 // id: %18
bb2: // Preds: bb0
// function_ref t.getSomeClass () -> t.SomeClass
%19 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %20
%20 = apply %19() : $@thin () -> @owned SomeClass // user: %26
%21 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %26
%22 = integer_literal $Builtin.Int2, -2 // user: %24
%23 = load %2#1 : $*Builtin.Int2 // user: %24
%24 = apply %1(%23, %22) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %25
store %24 to %2#1 : $*Builtin.Int2 // id: %25
store %20 to %21 : $*SomeClass // id: %26
br bb3 // id: %27
bb3: // Preds: bb2 bb1
// function_ref t.getSomeClass () -> t.SomeClass
%28 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %29
%29 = apply %28() : $@thin () -> @owned SomeClass // user: %42
%30 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %42
%31 = load %2#1 : $*Builtin.Int2 // user: %33
%32 = builtin_function_ref "trunc_Int2_Int1" : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %33
%33 = apply %32(%31) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %34
cond_br %33, bb4, bb5 // id: %34
bb4: // Preds: bb3
%35 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %36
destroy_addr %35 : $*SomeClass // id: %36
br bb5 // id: %37
bb5: // Preds: bb3 bb4
%38 = integer_literal $Builtin.Int2, 1 // user: %40
%39 = load %2#1 : $*Builtin.Int2 // user: %40
%40 = apply %1(%39, %38) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %41
store %40 to %2#1 : $*Builtin.Int2 // id: %41
store %29 to %30 : $*SomeClass // id: %42
%43 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %59
%44 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %59
%45 = load %2#1 : $*Builtin.Int2 // user: %48
%46 = builtin_function_ref "lshr_Int2" : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %48
%47 = integer_literal $Builtin.Int2, 1 // user: %48
%48 = apply %46(%45, %47) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %50
%49 = builtin_function_ref "trunc_Int2_Int1" : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %50
%50 = apply %49(%48) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %51
cond_br %50, bb6, bb7 // id: %51
bb6: // Preds: bb5
%52 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %53
destroy_addr %52 : $*SomeClass // id: %53
br bb7 // id: %54
bb7: // Preds: bb5 bb6
%55 = integer_literal $Builtin.Int2, -2 // user: %57
%56 = load %2#1 : $*Builtin.Int2 // user: %57
%57 = apply %1(%56, %55) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %58
store %57 to %2#1 : $*Builtin.Int2 // id: %58
copy_addr %43 to [initialization] %44 : $*SomeClass // id: %59
destroy_addr %5#1 : $*(SomeClass, SomeClass) // id: %60
dealloc_stack %5#0 : $*@local_storage (SomeClass, SomeClass) // id: %61
dealloc_stack %3#0 : $*@local_storage Bool // id: %62
%63 = tuple () // user: %65
dealloc_stack %2#0 : $*@local_storage Builtin.Int2 // id: %64
return %63 : $() // id: %65
}
Which ends up producing this LLVM IR at -O3:
define void @_T1t4testFT4condSb_T_(i1) #0 {
entry:
%1 = tail call noalias %swift.refcounted* @swift_allocObject(...
%2 = tail call noalias %swift.refcounted* @swift_allocObject(...
tail call void @swift_release(%swift.refcounted* %2) #0
tail call void @swift_release(%swift.refcounted* %1) #0
ret void
}
Swift SVN r10700