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