// RUN: %target-swift-frontend -Xllvm -sil-print-types -emit-sil -enable-copy-propagation=false %s | %FileCheck %s // Using -enable-copy-propagation=false to pattern match against older SIL // output. At least until -enable-copy-propagation has been around // long enough in the same form to be worth rewriting CHECK lines. // REQUIRES: swift_in_compiler class OtherClass {} class FirstClass { var x: OtherClass // CHECK-LABEL: sil hidden @$s24definite_init_root_class10FirstClassC1nACSgs5Int32V_tcfc : $@convention(method) (Int32, @owned FirstClass) -> @owned Optional init?(n: Int32) { // CHECK: [[EI:%.*]] = end_init_let_ref %1 // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int1, 0 // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int32, 0 // CHECK: [[N:%.*]] = struct_extract %0 : $Int32, #Int32._value // CHECK: [[CMP:%.*]] = builtin "cmp_eq_Int32"([[N]] : $Builtin.Int32, [[ZERO]] : $Builtin.Int32) : $Builtin.Int1 // CHECK: cond_br [[CMP]], bb1, bb2 if n == 0 { return nil } // CHECK: bb1: // CHECK: br bb5 // CHECK: bb2: // CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $FirstClass, #FirstClass.x // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass // CHECK: end_access [[X_ACCESS]] : $*OtherClass x = OtherClass() // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int32, 1 // CHECK: [[N:%.*]] = struct_extract %0 : $Int32, #Int32._value // CHECK: [[CMP:%.*]] = builtin "cmp_eq_Int32"([[N]] : $Builtin.Int32, [[ONE]] : $Builtin.Int32) : $Builtin.Int1 // CHECK: cond_br [[CMP]], bb3, bb4 if n == 1 { return nil } // CHECK: bb3: // CHECK: br bb5 // CHECK: bb4: // CHECK: [[RESULT:%.*]] = enum $Optional, #Optional.some!enumelt, [[EI]] : $FirstClass // CHECK: br bb12([[RESULT]] : $Optional) // CHECK: bb5([[BIT:%.*]] : $Builtin.Int1): // CHECK: cond_br [[BIT]], bb6, bb7 // CHECK: bb6: // CHECK: strong_release [[EI]] : $FirstClass // CHECK: br bb11 // CHECK: bb7: // CHECK: cond_br [[BIT]], bb8, bb9 // CHECK: bb8: // CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $FirstClass, #FirstClass.x // CHECK: [[X_ACCESS:%.*]] = begin_access [deinit] [static] [[X_ADDR]] : $*OtherClass // CHECK: destroy_addr [[X_ACCESS]] : $*OtherClass // CHECK: end_access [[X_ACCESS]] : $*OtherClass // CHECK: br bb10 // CHECK: bb9: // CHECK: br bb10 // CHECK: [[METATYPE:%.*]] = metatype $@thick FirstClass.Type // CHECK: dealloc_partial_ref [[EI]] : $FirstClass, [[METATYPE]] : $@thick FirstClass.Type // CHECK: br bb11 // CHECK: bb11: // CHECK: [[NIL:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK: br bb12([[NIL]] : $Optional) // CHECK: bb12([[RESULT:%.*]] : $Optional): // CHECK: return [[RESULT]] : $Optional } } class SecondClass { var x: OtherClass var y: OtherClass // CHECK-LABEL: sil hidden @$s24definite_init_root_class11SecondClassC1nACSgs5Int32V_tcfc : $@convention(method) (Int32, @owned SecondClass) -> @owned Optional { init?(n: Int32) { // CHECK: [[EI:%.*]] = end_init_let_ref %1 // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int2, 0 // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int32, 0 // CHECK: [[N:%.*]] = struct_extract %0 : $Int32, #Int32._value // CHECK: [[CMP:%.*]] = builtin "cmp_eq_Int32"([[N]] : $Builtin.Int32, [[ZERO]] : $Builtin.Int32) : $Builtin.Int1 // CHECK: cond_br [[CMP]], bb1, bb2 if n == 0 { return nil } // CHECK: bb1: // CHECK: br bb7 // CHECK: bb2: // CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.x // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass // CHECK: end_access [[X_ACCESS]] : $*OtherClass x = OtherClass() // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int32, 1 // CHECK: [[N:%.*]] = struct_extract %0 : $Int32, #Int32._value // CHECK: [[CMP:%.*]] = builtin "cmp_eq_Int32"([[N]] : $Builtin.Int32, [[ONE]] : $Builtin.Int32) : $Builtin.Int1 // CHECK: cond_br [[CMP]], bb3, bb4 if n == 1 { return nil } // CHECK: bb3: // CHECK: br bb7 // CHECK: bb4: // CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[Y_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.y // CHECK: [[Y_ACCESS:%.*]] = begin_access [init] [static] [[Y_ADDR]] : $*OtherClass // CHECK: [[THREE:%.*]] = integer_literal $Builtin.Int2, -1 // CHECK: store [[OTHER]] to [[Y_ACCESS]] : $*OtherClass // CHECK: end_access [[Y_ACCESS]] : $*OtherClass y = OtherClass() // CHECK: [[TWO:%.*]] = integer_literal $Builtin.Int32, 2 // CHECK: [[N:%.*]] = struct_extract %0 : $Int32, #Int32._value // CHECK: [[CMP:%.*]] = builtin "cmp_eq_Int32"([[N]] : $Builtin.Int32, [[TWO]] : $Builtin.Int32) : $Builtin.Int1 // CHECK: cond_br [[CMP]], bb5, bb6 if n == 2 { return nil } // CHECK: bb5: // CHECK: br bb7 // CHECK: bb6: // CHECK: [[RESULT:%.*]] = enum $Optional, #Optional.some!enumelt, [[EI]] : $SecondClass // CHECK: br bb17([[RESULT]] : $Optional) // CHECK: bb7([[BITS:%.*]] : $Builtin.Int2): // CHECK: [[THREE:%.*]] = integer_literal $Builtin.Int2, -1 // CHECK: [[BIT:%.*]] = builtin "cmp_eq_Int2"([[BITS]] : $Builtin.Int2, [[THREE]] : $Builtin.Int2) : $Builtin.Int1 // CHECK: cond_br [[BIT]], bb8, bb9 // CHECK: bb8: // CHECK: strong_release [[EI]] : $SecondClass // CHECK: br bb16 // CHECK: bb9: // CHECK: [[BIT:%.*]] = builtin "trunc_Int2_Int1"([[BITS]] : $Builtin.Int2) : $Builtin.Int1 // CHECK: cond_br [[BIT]], bb10, bb11 // CHECK: bb10: // CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.x // CHECK: [[X_ACCESS:%.*]] = begin_access [deinit] [static] [[X_ADDR]] : $*OtherClass // CHECK: destroy_addr [[X_ACCESS]] : $*OtherClass // CHECK: end_access [[X_ACCESS]] : $*OtherClass // CHECK: br bb12 // CHECK: bb11: // CHECK: br bb12 // CHECK: bb12: // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1 // CHECK: [[TMP:%.*]] = builtin "lshr_Int2"([[BITS]] : $Builtin.Int2, [[ONE]] : $Builtin.Int2) : $Builtin.Int2 // CHECK: [[BIT:%.*]] = builtin "trunc_Int2_Int1"([[TMP]] : $Builtin.Int2) : $Builtin.Int1 // CHECK: cond_br [[BIT]], bb13, bb14 // CHECK: bb13: // CHECK: [[Y_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.y // CHECK: [[Y_ACCESS:%.*]] = begin_access [deinit] [static] [[Y_ADDR]] : $*OtherClass // CHECK: destroy_addr [[Y_ACCESS]] : $*OtherClass // CHECK: end_access [[Y_ACCESS]] : $*OtherClass // CHECK: br bb15 // CHECK: bb14: // CHECK: br bb15 // CHECK: bb15: // CHECK: [[METATYPE:%.*]] = metatype $@thick SecondClass.Type // CHECK: dealloc_partial_ref [[EI]] : $SecondClass, [[METATYPE]] : $@thick SecondClass.Type // CHECK: br bb16 // CHECK: bb16: // CHECK: [[NIL:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK: br bb17([[NIL]] : $Optional) // CHECK: bb17([[RESULT:%.*]] : $Optional): // CHECK: return [[RESULT]] : $Optional } }