// RUN: %target-sil-opt -enable-sil-verify-all %s -diagnostic-constant-propagation | %FileCheck %s // RUN: %target-sil-opt -enable-sil-verify-all %s -performance-constant-propagation | %FileCheck %s import Swift import Builtin struct UInt { var value: Builtin.Word } struct Int { var value: Builtin.Word } struct Bool { var value: Builtin.Int1 } struct Int64 { var value: Builtin.Int64 } struct UInt64 { var value: Builtin.Int64 } sil @count_leading_zeros_corner_case : $@convention(thin) () -> Builtin.Int64 { bb0: %zero64 = integer_literal $Builtin.Int64, 0 %zero1 = integer_literal $Builtin.Int1, 0 %ctlz = builtin "int_ctlz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64 return %ctlz : $Builtin.Int64 // CHECK-LABEL: sil @count_leading_zeros_corner_case // CHECK-NOT: integer_literal $Builtin.Int64, 0 // CHECK-NOT: integer_literal $Builtin.Int1, 0 // CHECK-NOT: builtin // CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 64 // CHECK-NEXT: return [[RES]] : $Builtin.Int64 } sil @count_leading_zeros : $@convention(thin) () -> Builtin.Int64 { bb0: %zero64 = integer_literal $Builtin.Int64, 2 %zero1 = integer_literal $Builtin.Int1, 0 %ctlz = builtin "int_ctlz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64 return %ctlz : $Builtin.Int64 // CHECK-LABEL: sil @count_leading_zeros // CHECK-NOT: integer_literal $Builtin.Int64, 2 // CHECK-NOT: integer_literal $Builtin.Int1, 0 // CHECK-NOT: builtin // CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 62 // CHECK-NEXT: return [[RES]] : $Builtin.Int64 } sil @count_trailing_zeros_corner_case : $@convention(thin) () -> Builtin.Int64 { bb0: %zero64 = integer_literal $Builtin.Int64, 0 %zero1 = integer_literal $Builtin.Int1, 0 %cttz = builtin "int_cttz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64 return %cttz : $Builtin.Int64 // CHECK-LABEL: sil @count_trailing_zeros_corner_case // CHECK-NOT: integer_literal $Builtin.Int64, 0 // CHECK-NOT: integer_literal $Builtin.Int1, 0 // CHECK-NOT: builtin // CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 64 // CHECK-NEXT: return [[RES]] : $Builtin.Int64 } sil @count_trailing_zeros : $@convention(thin) () -> Builtin.Int64 { bb0: %zero64 = integer_literal $Builtin.Int64, 2 %zero1 = integer_literal $Builtin.Int1, 0 %cttz = builtin "int_cttz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64 return %cttz : $Builtin.Int64 // CHECK-LABEL: sil @count_trailing_zeros // CHECK-NOT: integer_literal $Builtin.Int64, 2 // CHECK-NOT: integer_literal $Builtin.Int1, 0 // CHECK-NOT: builtin // CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 1 // CHECK-NEXT: return [[RES]] : $Builtin.Int64 } // Compute an expression using a chain of arithmetic with overflow instructions: 2 * (2 + 3) - 3 sil @fold_arithmetic_with_overflow : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, 2 %110 = integer_literal $Builtin.Int64, 3 %18 = builtin "int_sadd_with_overflow_Int64"(%0 : $Builtin.Int64, %110 : $Builtin.Int64) : $(Builtin.Int64, Builtin.Int1) %19 = tuple_extract %18 : $(Builtin.Int64, Builtin.Int1), 0 %20 = builtin "int_smul_with_overflow_Int64"(%0 : $Builtin.Int64, %19 : $Builtin.Int64) : $(Builtin.Int64, Builtin.Int1) %21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 0 %22 = builtin "int_ssub_with_overflow_Int64"(%21 : $Builtin.Int64, %110 : $Builtin.Int64) : $(Builtin.Int64, Builtin.Int1) %23 = tuple_extract %22 : $(Builtin.Int64, Builtin.Int1), 0 return %23 : $Builtin.Int64 // CHECK-LABEL: sil @fold_arithmetic_with_overflow // CHECK-NOT: integer_literal $Builtin.Int64, 2 // CHECK-NOT: integer_literal $Builtin.Int64, 3 // CHECK-NOT: integer_literal $Builtin.Int64, 0 // CHECK-NOT: builtin // CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 7 // CHECK-NEXT: return [[RES]] : $Builtin.Int64 } // Fold casts. (This test assumes that DCE does not run, otherwise the unreachable blocks will get removed.) sil @fold_trunc : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int128, 22 %2 = builtin "trunc_Int128_Int64"(%0 : $Builtin.Int128) : $Builtin.Int64 br bb4(%2 : $Builtin.Int64) bb1: %3 = integer_literal $Builtin.Int8, 23 %5 = builtin "sext_Int8_Int64"(%3 : $Builtin.Int8) : $Builtin.Int64 br bb4(%5 : $Builtin.Int64) bb2: %6 = integer_literal $Builtin.Int8, 24 %8 = builtin "zext_Int8_Int64"(%6 : $Builtin.Int8) : $Builtin.Int64 br bb4(%8 : $Builtin.Int64) bb4(%100 : $Builtin.Int64): return %100 : $Builtin.Int64 // CHECK-LABEL: sil @fold_trunc // CHECK-NOT: integer_literal $Builtin.Int128, 22 // CHECK: integer_literal $Builtin.Int64, 22 // CHECK-NOT: integer_literal $Builtin.Int8, 23 // CHECK: integer_literal $Builtin.Int64, 23 // CHECK-NOT: integer_literal $Builtin.Int8, 24 // CHECK: integer_literal $Builtin.Int64, 24 } sil @test_tuple_extract_folding : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, 5 %1 = integer_literal $Builtin.Int1, 0 %2 = tuple (%0 : $Builtin.Int64, %1 : $Builtin.Int1) %3 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int1), 0 return %3 : $Builtin.Int64 // CHECK-LABEL: sil @test_tuple_extract_folding // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 5 // CHECK-NEXT: return %0 : $Builtin.Int64 // CHECK-NEXT: } } sil @test_struct_extract_folding_first : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, 2 %1 = struct $Int64 (%0 : $Builtin.Int64) %2 = struct_extract %1 : $Int64, #Int64.value return %2 : $Builtin.Int64 // CHECK-LABEL: sil @test_struct_extract_folding_first // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 2 // CHECK-NEXT: return %0 : $Builtin.Int64 // CHECK-NEXT: } } struct TwoValueStruct { var a : Builtin.Int64 var b : Builtin.Int64 } sil @test_struct_extract_folding_second : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, 2 %1 = integer_literal $Builtin.Int64, 20 %2 = struct $TwoValueStruct (%0 : $Builtin.Int64, %1 : $Builtin.Int64) %3 = struct_extract %2 : $TwoValueStruct, #TwoValueStruct.b return %3 : $Builtin.Int64 // CHECK-LABEL: sil @test_struct_extract_folding_second // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 20 // CHECK-NEXT: return %0 : $Builtin.Int64 // CHECK-NEXT: } } sil @test_struct_extract_folding_third : $() -> Bool { bb0: %0 = integer_literal $Builtin.Int64, 200 %a = integer_literal $Builtin.Int1, 1 %1 = struct $Bool (%a : $Builtin.Int1) %2 = tuple (%0 : $Builtin.Int64, %1 : $Bool) %3 = tuple_extract %2 : $(Builtin.Int64, Bool), 1 return %3 : $Bool // CHECK-LABEL: sil @test_struct_extract_folding_third // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int1, -1 // CHECK-NEXT: %1 = struct $Bool // CHECK-NEXT: return %1 : $Bool // CHECK-NEXT: } } sil @testChainingCCP : $@convention(thin) () -> Builtin.Int1 { bb0: %2 = integer_literal $Builtin.Int64, 0 %3 = struct $Int64 (%2 : $Builtin.Int64) %4 = struct_extract %3 : $Int64, #Int64.value %5 = builtin "trunc_Int64_Int1"(%4 : $Builtin.Int64) : $Builtin.Int1 return %5 : $Builtin.Int1 // CHECK-LABEL: sil @testChainingCCP // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int1, 0 // CHECK-NEXT: return %0 : $Builtin.Int1 // CHECK-NEXT: } } sil @testDivision : $@convention(thin) () -> Builtin.Int8 { bb0: %1 = integer_literal $Builtin.Int8, 6 %2 = integer_literal $Builtin.Int8, 3 %3 = builtin "sdiv_Int8"(%1: $Builtin.Int8, %2: $Builtin.Int8) : $Builtin.Int8 return %3 : $Builtin.Int8 // CHECK-LABEL: sil @testDivision // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 2 // CHECK-NEXT: return %0 : $Builtin.Int8 // CHECK-NEXT: } } sil @testRem : $@convention(thin) () -> Builtin.Int64 { bb0: %1 = integer_literal $Builtin.Int64, 10 %2 = integer_literal $Builtin.Int64, 2 %3 = builtin "urem_Int64"(%1 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 return %3 : $Builtin.Int64 // CHECK-LABEL: sil @testRem // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 0 // CHECK-NEXT: return %0 : $Builtin.Int64 // CHECK-NEXT: } } sil @testFoldingNonNegativeSignedInt : $@convention(thin) (Builtin.Int64) -> () { bb0(%0 : $Builtin.Int64): %zero = integer_literal $Builtin.Int64, 0 %non_neg = builtin "assumeNonNegative_Int64"(%0 : $Builtin.Int64) : $Builtin.Int64 %compare_slt = builtin "cmp_slt_Int64"(%non_neg : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %compare_sgt = builtin "cmp_sgt_Int64"(%zero : $Builtin.Int64, %non_neg : $Builtin.Int64) : $Builtin.Int1 %compare_sge = builtin "cmp_sge_Int64"(%non_neg : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %compare_sle = builtin "cmp_sle_Int64"(%zero : $Builtin.Int64, %non_neg : $Builtin.Int64) : $Builtin.Int1 %5 = tuple () return %5 : $() // CHECK-LABEL: sil @testFoldingNonNegativeSignedInt // CHECK: bb // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: tuple // CHECK-NEXT: return } sil @testFoldingIntBinaryPredicates : $@convention(thin) (Builtin.Int32) -> () { bb0(%0 : $Builtin.Int32): %1 = integer_literal $Builtin.Int1, 1 %2 = integer_literal $Builtin.Int1, 0 // This is Int32.Max %3 = integer_literal $Builtin.Int32, 2147483647 %4 = builtin "cmp_eq_Int1"(%1 : $Builtin.Int1, %2 : $Builtin.Int1) : $Builtin.Int1 %11 = integer_literal $Builtin.Int32, 21 %12 = integer_literal $Builtin.Int32, 12 %14 = builtin "cmp_ne_Int32"(%11 : $Builtin.Int32, %12 : $Builtin.Int32) : $Builtin.Int1 %16 = builtin "cmp_sgt_Int32"(%12 : $Builtin.Int32, %11 : $Builtin.Int32) : $Builtin.Int1 %17 = builtin "cmp_ult_Int32"(%12 : $Builtin.Int32, %11 : $Builtin.Int32) : $Builtin.Int1 // Int32.Max < x %18 = builtin "cmp_slt_Int32"(%3 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 // x > Int32.Max %19 = builtin "cmp_sgt_Int32"(%0 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // Int32.Max >= x %20 = builtin "cmp_sge_Int32"(%3 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 // x <= Int32.Max %21 = builtin "cmp_sle_Int32"(%0 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 %5 = tuple () return %5 : $() // CHECK-LABEL: sil @testFoldingIntBinaryPredicates // CHECK: bb // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: tuple // CHECK-NEXT: return } sil @testFoldingUnsignedIntComparisons : $@convention(thin) (Builtin.Int32) -> () { bb0(%0 : $Builtin.Int32): %2 = integer_literal $Builtin.Int1, 0 %3 = integer_literal $Builtin.Int32, 0 // unsigned value is never less then 0 %18 = builtin "cmp_ult_Int32"(%0 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // unsigned value is always >= 0 %19 = builtin "cmp_uge_Int32"(%0 : $Builtin.Int32, %3 : $Builtin.Int32) : $Builtin.Int1 // 0 is always <= an unsigned value %20 = builtin "cmp_ule_Int32"(%3 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 // 0 is never greater than an unsigned value %21 = builtin "cmp_ugt_Int32"(%3 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 %5 = tuple () return %5 : $() // CHECK-LABEL: sil @testFoldingUnsignedIntComparisons // CHECK: bb0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: tuple // CHECK-NEXT: return } // fold_binary_bitwise sil @fold_binary_bitwise : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, 1 // users: %7, %6, %5 %1 = integer_literal $Builtin.Int64, 0 // users: %7, %6, %5 %5 = builtin "and_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int64 %6 = builtin "or_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int64 %7 = builtin "xor_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int64 // user: %8 return %7 : $Builtin.Int64 // id: %8 // CHECK-LABEL: sil @fold_binary_bitwise // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 0 // CHECK_NEXT: %1 = integer_literal $Builtin.Int64, 1 // CHECK_NEXT: %2 = integer_literal $Builtin.Int64, 1 // CHECK_NEXT: return %2 : $Builtin.Int64 } // For any x of the same size as Int.max and n>=1 , (x>>n) is always <= Int.max, // that is (x>>n) <= Int.max and Int.max >= (x>>n) are true. // At the same time (x>>n) > Int.max and Int.max < (x>>n) is always false. sil @fold_cmp_lshr_with_IntMax : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { bb0(%0 : $Builtin.Int64): %1 = integer_literal $Builtin.Int64, 9223372036854775807 %2 = integer_literal $Builtin.Int64, 1 %3 = integer_literal $Builtin.Int64, 3 %4 = integer_literal $Builtin.Int64, 0 %5 = integer_literal $Builtin.Int64, -2 // x >> 1 %9 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 %10 = builtin "cmp_sge_Int64"(%1 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int1 %11 = builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int1 %12 = builtin "cmp_sle_Int64"(%9 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %13 = builtin "cmp_ule_Int64"(%9 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %20 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int1 %21 = builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int1 %22 = builtin "cmp_sgt_Int64"(%9 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %23 = builtin "cmp_ugt_Int64"(%9 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // x >> 3 %29 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int64 %30 = builtin "cmp_sge_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 %31 = builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 %32 = builtin "cmp_sle_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %33 = builtin "cmp_ule_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %40 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 %41 = builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 %42 = builtin "cmp_sgt_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %43 = builtin "cmp_ugt_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // Check that this peephole does not happen if the shift amount is < 1 // x >> 0 (i.e. x shifted by something < 1) %59 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %4 : $Builtin.Int64) : $Builtin.Int64 %60 = builtin "cmp_sge_Int64"(%1 : $Builtin.Int64, %59 : $Builtin.Int64) : $Builtin.Int1 %61 = builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %59 : $Builtin.Int64) : $Builtin.Int1 %62 = builtin "cmp_sle_Int64"(%59 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %63 = builtin "cmp_ule_Int64"(%59 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %70 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %59 : $Builtin.Int64) : $Builtin.Int1 %71 = builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %59 : $Builtin.Int64) : $Builtin.Int1 %72 = builtin "cmp_sgt_Int64"(%59 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %73 = builtin "cmp_ugt_Int64"(%59 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // x >> -2 (i.e. x shifted by something < 1) %79 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 %80 = builtin "cmp_sge_Int64"(%1 : $Builtin.Int64, %79 : $Builtin.Int64) : $Builtin.Int1 %81 = builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %79 : $Builtin.Int64) : $Builtin.Int1 %82 = builtin "cmp_sle_Int64"(%79 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %83 = builtin "cmp_ule_Int64"(%79 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %90 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %79 : $Builtin.Int64) : $Builtin.Int1 %91 = builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %79 : $Builtin.Int64) : $Builtin.Int1 %92 = builtin "cmp_sgt_Int64"(%79 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 %93 = builtin "cmp_ugt_Int64"(%79 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 return %4 : $Builtin.Int64 // CHECK-LABEL: sil @fold_cmp_lshr_with_IntMax // CHECK: bb0 // CHECK-NEXT: integer_literal $Builtin.Int64, 9223372036854775807 // CHECK-NEXT: integer_literal $Builtin.Int64, 0 // CHECK-NEXT: integer_literal $Builtin.Int64, -2 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: builtin "lshr_Int64"(%0 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %20 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: builtin "cmp_ule_Int64"(%20 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %20 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: builtin "cmp_ugt_Int64"(%20 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: builtin "lshr_Int64"(%0 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int64 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: builtin "cmp_uge_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: builtin "cmp_ule_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: builtin "cmp_ult_Int64"(%1 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: integer_literal $Builtin.Int1, 0 // CHECK-NEXT: builtin "cmp_ugt_Int64"(%29 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // CHECK-NEXT: return %2 : $Builtin.Int64 } // fold_shifts sil @fold_shifts : $@convention(thin) () -> Builtin.Int64 { bb0: %0 = integer_literal $Builtin.Int64, -32 // users: %9, %8 %1 = integer_literal $Builtin.Int64, 32 // users: %11, %10 %2 = integer_literal $Builtin.Int64, 3 // users: %11, %10, %9, %8 %3 = integer_literal $Builtin.Int64, 1 // user: %12 %4 = integer_literal $Builtin.Int64, 5 // user: %12 %8 = builtin "ashr_Int64"(%0 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 %9 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 %10 = builtin "ashr_Int64"(%1 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 %11 = builtin "lshr_Int64"(%1 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int64 %12 = builtin "shl_Int64"(%3 : $Builtin.Int64, %4 : $Builtin.Int64) : $Builtin.Int64 // user: %13 return %12 : $Builtin.Int64 // id: %13 // CHECK-LABEL: sil @fold_shifts // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, -4 // CHECK-NEXT: %1 = integer_literal $Builtin.Int64, 2305843009213693948 // CHECK-NEXT: %2 = integer_literal $Builtin.Int64, 4 // CHECK-NEXT: %3 = integer_literal $Builtin.Int64, 4 // CHECK-NEXT: %4 = integer_literal $Builtin.Int64, 32 // CHECK-NEXT: return %4 : $Builtin.Int64 } // Fold x < 0 into false, if x is known to be a result of an unsigned // operation with overflow checks enabled. // At the same time x >= 0 is always true under the same conditions. sil @fold_unsigned_op_with_overflow_lt_zero : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64 { bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64): %zero = integer_literal $Builtin.Int64, 0 %2 = integer_literal $Builtin.Int1, -1 %uadd_result = builtin "uadd_with_overflow_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2: $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) %uadd_with_overflow_result = tuple_extract %uadd_result : $(Builtin.Int64, Builtin.Int1), 0 %uadd_overflow = tuple_extract %uadd_result : $(Builtin.Int64, Builtin.Int1), 1 cond_fail %uadd_overflow : $Builtin.Int1 %compare_slt_uadd_result = builtin "cmp_slt_Int64"(%uadd_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %compare_sge_uadd_result = builtin "cmp_sge_Int64"(%uadd_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %usub_result = builtin "usub_with_overflow_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2: $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) %usub_with_overflow_result = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 0 %usub_overflow = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 1 cond_fail %uadd_overflow : $Builtin.Int1 %compare_slt_usub_result = builtin "cmp_slt_Int64"(%usub_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %compare_sge_usub_result = builtin "cmp_sge_Int64"(%usub_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %umul_result = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2: $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) %umul_with_overflow_result = tuple_extract %umul_result : $(Builtin.Int64, Builtin.Int1), 0 %umul_overflow = tuple_extract %umul_result : $(Builtin.Int64, Builtin.Int1), 1 cond_fail %umul_overflow : $Builtin.Int1 %compare_slt_umul_result = builtin "cmp_slt_Int64"(%umul_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 %compare_sge_umul_result = builtin "cmp_sge_Int64"(%umul_with_overflow_result : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1 return %uadd_with_overflow_result : $Builtin.Int64 // CHECK-LABEL: sil @fold_unsigned_op_with_overflow_lt_zero // CHECK: builtin "uadd_with_overflow_Int64" // CHECK: integer_literal $Builtin.Int1, 0 // CHECK: integer_literal $Builtin.Int1, -1 // CHECK: builtin "usub_with_overflow_Int64" // CHECK: integer_literal $Builtin.Int1, 0 // CHECK: integer_literal $Builtin.Int1, -1 // CHECK: builtin "umul_with_overflow_Int64" // CHECK: integer_literal $Builtin.Int1, 0 // CHECK: integer_literal $Builtin.Int1, -1 // CHECK-NEXT: return {{.*}}$Builtin.Int64 } // fold_float_operations sil @fold_float_operations : $@convention(thin) () -> Builtin.FPIEEE64 { bb0: %4 = float_literal $Builtin.FPIEEE64, 0x402E4CCCCCCCCCCD // 15.15 %11 = float_literal $Builtin.FPIEEE64, 0x400A666666666666 // 3.2999999999999998 // user: %12 %8 = builtin "fadd_FPIEEE64"(%4 : $Builtin.FPIEEE64, %11 : $Builtin.FPIEEE64) : $Builtin.FPIEEE64 %9 = builtin "fdiv_FPIEEE64"(%4 : $Builtin.FPIEEE64, %11 : $Builtin.FPIEEE64) : $Builtin.FPIEEE64 %10 = builtin "fsub_FPIEEE64"(%4 : $Builtin.FPIEEE64, %11 : $Builtin.FPIEEE64) : $Builtin.FPIEEE64 %13 = builtin "fmul_FPIEEE64"(%4 : $Builtin.FPIEEE64, %11 : $Builtin.FPIEEE64) : $Builtin.FPIEEE64 return %13 : $Builtin.FPIEEE64 // CHECK-LABEL: sil @fold_float_operations // CHECK: bb0: // CHECK-NEXT: %0 = float_literal $Builtin.FPIEEE64, 0x4032733333333333 // CHECK-NEXT: %1 = float_literal $Builtin.FPIEEE64, 0x40125D1745D1745D // CHECK-NEXT: %2 = float_literal $Builtin.FPIEEE64, 0x4027B33333333334 // CHECK-NEXT: %3 = float_literal $Builtin.FPIEEE64, 0x4048FF5C28F5C28F // CHECK-NEXT: return %3 : $Builtin.FPIEEE64 } // rdar://15729207 - Verify that constant folding doesn't leave around obviously // dead cond_fail instructions. sil @fold_condfail_instructions : $@convention(thin) () -> Int64 { bb0: %0 = integer_literal $Builtin.IntLiteral, 1 // user: %2 %2 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1) // user: %3 %3 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int1), 0 // user: %4 %4 = struct $Int64 (%3 : $Builtin.Int64) // users: %14, %5 %6 = integer_literal $Builtin.IntLiteral, 2 // user: %8 %8 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%6 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1) // user: %9 %9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 0 // user: %10 %10 = struct $Int64 (%9 : $Builtin.Int64) // users: %15, %11 %12 = integer_literal $Builtin.Int1, -1 // user: %16 %14 = struct_extract %4 : $Int64, #Int64.value // user: %16 %15 = struct_extract %10 : $Int64, #Int64.value // user: %16 %16 = builtin "sadd_with_overflow_Int64"(%14 : $Builtin.Int64, %15 : $Builtin.Int64, %12 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // users: %18, %17 %17 = tuple_extract %16 : $(Builtin.Int64, Builtin.Int1), 0 // user: %19 %18 = tuple_extract %16 : $(Builtin.Int64, Builtin.Int1), 1 // user: %20 %19 = struct $Int64 (%17 : $Builtin.Int64) // user: %21 cond_fail %18 : $Builtin.Int1 // id: %20 return %19 : $Int64 // id: %21 // CHECK-LABEL: sil @fold_condfail_instructions // CHECK: bb0 // CHECK-NEXT: integer_literal{{.*}}3 // CHECK-NEXT: struct // CHECK-NEXT: return } // Make sure that we properly handle functions eliminated by CCP by removing // from the worklist. If we don't the following (reduced) test case will blow // up. // CHECK-LABEL: sil @properly_handle_eliminated_instructions_in_worklist : $@convention(method) (Bool, @inout UInt) -> () { sil @properly_handle_eliminated_instructions_in_worklist : $@convention(method) (Bool, @inout UInt) -> () { bb0(%0 : $Bool, %1 : $*UInt): %2 = load %1 : $*UInt %3 = integer_literal $Builtin.IntLiteral, 1 %5 = builtin "s_to_u_checked_trunc_IntLiteral_Word"(%3 : $Builtin.IntLiteral) : $(Builtin.Word, Builtin.Int1) %6 = tuple_extract %5 : $(Builtin.Word, Builtin.Int1), 0 %7 = tuple_extract %5 : $(Builtin.Word, Builtin.Int1), 1 %8 = struct $UInt (%6 : $Builtin.Word) %9 = integer_literal $Builtin.IntLiteral, 0 %11 = builtin "s_to_u_checked_trunc_IntLiteral_Word"(%9 : $Builtin.IntLiteral) : $(Builtin.Word, Builtin.Int1) %12 = tuple_extract %11 : $(Builtin.Word, Builtin.Int1), 0 %13 = tuple_extract %11 : $(Builtin.Word, Builtin.Int1), 1 %14 = struct $UInt (%12 : $Builtin.Word) %15 = integer_literal $Builtin.IntLiteral, 1 %17 = builtin "s_to_u_checked_trunc_IntLiteral_Word"(%15 : $Builtin.IntLiteral) : $(Builtin.Word, Builtin.Int1) %18 = tuple_extract %17 : $(Builtin.Word, Builtin.Int1), 0 %19 = tuple_extract %17 : $(Builtin.Word, Builtin.Int1), 1 %20 = struct $UInt (%18 : $Builtin.Word) %22 = struct_extract %14 : $UInt, #UInt.value %23 = struct_extract %20 : $UInt, #UInt.value %25 = integer_literal $Builtin.IntLiteral, 0 %27 = builtin "s_to_s_checked_trunc_IntLiteral_Word"(%25 : $Builtin.IntLiteral) : $(Builtin.Word, Builtin.Int1) %28 = tuple_extract %27 : $(Builtin.Word, Builtin.Int1), 0 %29 = tuple_extract %27 : $(Builtin.Word, Builtin.Int1), 1 %30 = struct $Int (%28 : $Builtin.Word) %31 = struct_extract %30 : $Int, #Int.value %32 = builtin "trunc_Word_Int1"(%31 : $Builtin.Word) : $Builtin.Int1 %33 = struct $Bool (%32 : $Builtin.Int1) %34 = struct_extract %33 : $Bool, #Bool.value %35 = builtin "usub_with_overflow_Word"(%22 : $Builtin.Word, %23 : $Builtin.Word, %34 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1) %36 = tuple_extract %35 : $(Builtin.Word, Builtin.Int1), 0 %37 = tuple_extract %35 : $(Builtin.Word, Builtin.Int1), 1 %38 = struct $UInt (%36 : $Builtin.Word) %39 = struct $Bool (%37 : $Builtin.Int1) %40 = tuple (%38 : $UInt, %39 : $Bool) %41 = tuple_extract %40 : $(UInt, Bool), 0 %42 = tuple_extract %40 : $(UInt, Bool), 1 %44 = struct_extract %8 : $UInt, #UInt.value %45 = struct_extract %41 : $UInt, #UInt.value %46 = builtin "xor_Word"(%44 : $Builtin.Word, %45 : $Builtin.Word) : $Builtin.Word %47 = struct $UInt (%46 : $Builtin.Word) %49 = struct_extract %2 : $UInt, #UInt.value %50 = struct_extract %47 : $UInt, #UInt.value %51 = builtin "and_Word"(%49 : $Builtin.Word, %50 : $Builtin.Word) : $Builtin.Word %52 = struct $UInt (%51 : $Builtin.Word) %53 = tuple () return %53 : $() } // CHECK-LABEL: sil @constant_expect_hint // CHECK: bb0: // CHECK-NEXT: [[INT1:%[0-9]+]] = integer_literal $Builtin.Int1, 0 // CHECK-NEXT: [[INT2:%[0-9]+]] = integer_literal $Builtin.Int32, 5 // CHECK-NEXT: [[INT3:%[0-9]+]] = integer_literal $Builtin.Int64, 32 // CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ([[INT1]] : $Builtin.Int1, [[INT2]] : $Builtin.Int32, [[INT3]] : $Builtin.Int64) // CHECK-NEXT: return [[TUPLE]] // CHECK-NEXT: } sil @constant_expect_hint : $@convention(thin) () -> (Builtin.Int1, Builtin.Int32, Builtin.Int64) { bb0: %0 = integer_literal $Builtin.Int1, 0 %1 = integer_literal $Builtin.Int32, 5 %2 = integer_literal $Builtin.Int64, 32 %3 = integer_literal $Builtin.Int1, 1 %4 = integer_literal $Builtin.Int32, 400 %5 = integer_literal $Builtin.Int64, 5000 %9 = builtin "int_expect_Int1"(%0 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1 %10 = builtin "int_expect_Int32"(%1 : $Builtin.Int32, %4 : $Builtin.Int32) : $Builtin.Int32 %11 = builtin "int_expect_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 %12 = tuple (%9 : $Builtin.Int1, %10 : $Builtin.Int32, %11 : $Builtin.Int64) return %12 : $(Builtin.Int1, Builtin.Int32, Builtin.Int64) } // CHECK-LABEL: sil @constant_fold_indexing_inst_of_0 : $@convention(thin) (Builtin.RawPointer) -> (Builtin.Int8, Builtin.Int8) { // CHECK: bb0 // CHECK-NEXT: pointer_to_address // CHECK-NEXT: pointer_to_address // CHECK-NEXT: load // CHECK-NEXT: load // CHECK-NEXT: tuple // CHECK-NEXT: return sil @constant_fold_indexing_inst_of_0 : $@convention(thin) (Builtin.RawPointer) -> (Builtin.Int8, Builtin.Int8) { bb0(%0 : $Builtin.RawPointer): %1 = integer_literal $Builtin.Word, 0 %2 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Builtin.Int8 %3 = index_addr %2 : $*Builtin.Int8, %1 : $Builtin.Word %4 = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word %5 = pointer_to_address %4 : $Builtin.RawPointer to [strict] $*Builtin.Int8 %6 = load %3 : $*Builtin.Int8 %7 = load %5 : $*Builtin.Int8 %8 = tuple(%6 : $Builtin.Int8, %7 : $Builtin.Int8) return %8 : $(Builtin.Int8, Builtin.Int8) } // CHECK-LABEL: sil @constant_assume_non_negative // CHECK: bb0: // CHECK-NEXT: [[I:%[0-9]+]] = integer_literal $Builtin.Word, 27 // CHECK-NEXT: return [[I]] // CHECK-NEXT: } sil @constant_assume_non_negative : $@convention(thin) () -> Builtin.Word { %0 = integer_literal $Builtin.Word, 27 %1 = builtin "assumeNonNegative_Word"(%0 : $Builtin.Word) : $Builtin.Word return %0 : $Builtin.Word } // CHECK-LABEL: sil @constant_fold_fptrunc // CHECK: bb0: // CHECK-NEXT: %0 = float_literal // CHECK-NEXT: %1 = tuple () // CHECK-NEXT: return // CHECK-NEXT: } sil @constant_fold_fptrunc : $@convention(thin) () -> () { bb0: %0 = float_literal $Builtin.FPIEEE80, 0x4000C90E5604189374BC // 3.14149999999999999991 // user: %1 %1 = builtin "fptrunc_FPIEEE80_FPIEEE64"(%0 : $Builtin.FPIEEE80) : $Builtin.FPIEEE64 // user: %2 %3 = tuple () return %3 : $() // id: %3 } struct Value {} class AnObject {} // CHECK-LABEL: sil @replace_unconditional_check_cast_failure // CHECK: bb2: // CHECK: alloc_stack $AnObject // CHECK: store undef to %0 // CHECK: dealloc_stack // CHECK: builtin "int_trap"() // CHECK: unreachable sil @replace_unconditional_check_cast_failure : $@convention(thin) (Builtin.Int1, @guaranteed AnObject) -> (@out Value) { bb0(%2 : $*Value, %0 : $Builtin.Int1, %1 : $AnObject): cond_br %0, bb1, bb2 bb1: %3 = tuple() return %3 : $() bb2: %31 = alloc_stack $AnObject store %1 to %31 : $*AnObject strong_retain %1 : $AnObject unconditional_checked_cast_addr AnObject in %31 : $*AnObject to Value in %2 : $*Value %32 = alloc_stack $AnObject dealloc_stack %32: $*AnObject dealloc_stack %31 : $*AnObject br bb1 } public protocol P { } public protocol PP { } struct X : P { } struct Y: P { var x : T } class Z: P { init() } // Do not optimize casts to unrelated protocols. // CHECK-LABEL: sil @dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential // CHECK: unconditional_checked_cast_addr // CHECK: end sil function 'dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential' sil @dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential : $@convention(thin) (@in X) -> (@out PP) { bb0(%0 : $*PP, %1 : $*X): unconditional_checked_cast_addr X in %1 : $*X to PP in %0 : $*PP %2 = tuple () return %2 : $() } // Do not optimize casts between existentials. // CHECK-LABEL: sil @dont_replace_unconditional_check_cast_addr_for_existential_to_existential // CHECK: unconditional_checked_cast_addr // CHECK: end sil function 'dont_replace_unconditional_check_cast_addr_for_existential_to_existential' sil @dont_replace_unconditional_check_cast_addr_for_existential_to_existential : $@convention(thin) (@in PP) -> (@out P) { bb0(%0 : $*P, %1 : $*PP): unconditional_checked_cast_addr PP in %1 : $*PP to P in %0 : $*P %2 = tuple () return %2 : $() } // Check that an unconditional_checked_cast_addr from a non-existential loadable type to a protocol // can be replaced by a more efficient code sequence if it is statitcally known that this // type conforms to this protocol. // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential // CHECK-NOT: store // CHECK: copy_addr // CHECK-NOT: destroy_addr // CHECK-NOT: unconditional_checked_cast_addr sil @replace_unconditional_check_cast_addr_for_type_to_existential : $@convention(thin) (@in X) -> (@out P) { bb0(%0 : $*P, %1 : $*X): unconditional_checked_cast_addr X in %1 : $*X to P in %0 : $*P %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_class_to_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr sil @replace_unconditional_check_cast_addr_for_class_to_existential : $@convention(thin) (@in Z) -> (@out P) { bb0(%0 : $*P, %1 : $*Z): unconditional_checked_cast_addr Z in %1 : $*Z to P in %0 : $*P %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr sil @replace_unconditional_check_cast_addr_for_archetype_to_existential : $@convention(thin) (@in X) -> (@out P) { bb0(%0 : $*P, %1 : $*X): unconditional_checked_cast_addr X in %1 : $*X to P in %0 : $*P %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_generic_type_to_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr sil @replace_unconditional_check_cast_addr_for_generic_type_to_existential : $@convention(thin) (@in Y) -> (@out P) { bb0(%0 : $*P, %1 : $*Y): unconditional_checked_cast_addr Y in %1 : $*Y to P in %0 : $*P %2 = tuple () return %2 : $() } protocol Q : class { } class V : Q { init() } class W: Q { var x : T init() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_class_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK-NOT: retain_value // CHECK: init_existential_ref // CHECK-NOT: retain_value // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_for_type_to_class_existential : $@convention(thin) (@in V) -> (@out Q) { bb0(%0 : $*Q, %1 : $*V): unconditional_checked_cast_addr V in %1 : $*V to Q in %0 : $*Q %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_class_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK-NOT: retain_value // CHECK: init_existential_ref // CHECK-NOT: retain_value // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_for_archetype_to_class_existential : $@convention(thin) (@in X) -> (@out Q) { bb0(%0 : $*Q, %1 : $*X): unconditional_checked_cast_addr X in %1 : $*X to Q in %0 : $*Q %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_to_class_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK-NOT: retain_value // CHECK: init_existential_ref // CHECK-NOT: retain_value // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_to_class_existential : $@convention(thin) (@in W) -> (@out Q) { bb0(%0 : $*Q, %1 : $*W): unconditional_checked_cast_addr W in %1 : $*W to Q in %0 : $*Q %2 = tuple () return %2 : $() } public protocol MyError : Error { } public class E1 : MyError { init() } public class E2 : MyError { init() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential : $@convention(thin) (@in E1) -> (@out MyError) { bb0(%0 : $*MyError, %1 : $*E1): unconditional_checked_cast_addr E1 in %1 : $*E1 to MyError in %0 : $*MyError %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_myerror_existentia // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_for_archetype_to_myerror_existential : $@convention(thin) (@in X) -> (@out MyError) { bb0(%0 : $*MyError, %1 : $*X): unconditional_checked_cast_addr X in %1 : $*X to MyError in %0 : $*MyError %2 = tuple () return %2 : $() } // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_to_myerror_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: init_existential_addr // CHECK-NOT: unconditional_checked_cast_addr // CHECK: return sil @replace_unconditional_check_cast_addr_to_myerror_existential : $@convention(thin) (@in E2) -> (@out MyError) { bb0(%0 : $*MyError, %1 : $*E2): unconditional_checked_cast_addr E2 in %1 : $*E2 to MyError in %0 : $*MyError %2 = tuple () return %2 : $() } // Check casts to Error. // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_error_existential // CHECK-NOT: unconditional_checked_cast_addr // CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $Error, $E1 // CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $Error // CHECK: copy_addr [take] %1 to [initialization] [[PROJ]] // CHECK: store [[ALLOC_BOX]] to %0 : $*Error // CHECK: return sil @replace_unconditional_check_cast_addr_for_type_to_error_existential : $@convention(thin) (@in E1) -> (@out Error) { bb0(%0 : $*Error, %1 : $*E1): unconditional_checked_cast_addr E1 in %1 : $*E1 to Error in %0 : $*Error %2 = tuple () return %2 : $() } // Test constant folding of Builtin.globalStringTablePointer. // CHECK-LABEL: sil @replace_global_string_table_pointer // CHECK: [[STRING_LIT:%.*]] = string_literal utf8 "constant" // CHECK-NOT: builtin "globalStringTablePointer" // CHECK: [[IMMORTAL_PTR:%.*]] = struct $UnsafePointer ([[STRING_LIT]] : $Builtin.RawPointer) // CHECK: return [[IMMORTAL_PTR]] sil @replace_global_string_table_pointer : $@convention(thin) () -> UnsafePointer { bb0: %0 = string_literal utf8 "constant" %1 = integer_literal $Builtin.Word, 8 %2 = integer_literal $Builtin.Int1, -1 %3 = metatype $@thin String.Type // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String %6 = builtin "globalStringTablePointer"(%5 : $String) : $Builtin.RawPointer %7 = struct $UnsafePointer (%6 : $Builtin.RawPointer) release_value %5 : $String return %7 : $UnsafePointer } // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) // The semantics attribute is used by the constant folder. sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // CHECK-LABEL: sil @string_ptr_to_int_round_trip : $@convention(thin) () -> Builtin.RawPointer { // CHECK-NOT: builtin // CHECK: } // end sil function 'string_ptr_to_int_round_trip' sil @string_ptr_to_int_round_trip : $@convention(thin) () -> Builtin.RawPointer { bb0: %0 = string_literal utf8 "constant" %1 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word %2 = builtin "inttoptr_Word"(%1 : $Builtin.Word) : $Builtin.RawPointer return %2 : $Builtin.RawPointer } // CHECK-LABEL: sil @string_ptr_to_int_round_trip_2 : $@convention(thin) () -> Builtin.Word { // CHECK-NOT: builtin // CHECK: } // end sil function 'string_ptr_to_int_round_trip_2' sil @string_ptr_to_int_round_trip_2 : $@convention(thin) () -> Builtin.Word { bb0: %0 = integer_literal $Builtin.Word, 0 %1 = builtin "inttoptr_Word"(%0 : $Builtin.Word) : $Builtin.RawPointer %2 = builtin "ptrtoint_Word"(%1 : $Builtin.RawPointer) : $Builtin.Word return %2 : $Builtin.Word } // CHECK-LABEL: sil @string_ptr_to_int_round_trip_no_match : $@convention(thin) () -> Builtin.Int32 { // CHECK: builtin // CHECK: builtin // CHECK: } // end sil function 'string_ptr_to_int_round_trip_no_match' sil @string_ptr_to_int_round_trip_no_match : $@convention(thin) () -> Builtin.Int32 { bb0: %0 = integer_literal $Builtin.Word, 0 %1 = builtin "inttoptr_Word"(%0 : $Builtin.Word) : $Builtin.RawPointer %2 = builtin "ptrtoint_Int32"(%1 : $Builtin.RawPointer) : $Builtin.Int32 return %2 : $Builtin.Int32 } // Make sure that we perform the transformation, but do not eliminate the int1, // since we do not know what it is. // // CHECK-LABEL: sil @cond_fail_test : $@convention(thin) (Builtin.Int1) -> () { // CHECK-NOT: builtin // CHECK: cond_fail // CHECK-NOT: builtin // CHECK: } // end sil function 'cond_fail_test' sil @cond_fail_test : $@convention(thin) (Builtin.Int1) -> () { bb0(%0 : $Builtin.Int1): %1 = string_literal utf8 "constant" %2 = builtin "condfail_message"(%0 : $Builtin.Int1, %1 : $Builtin.RawPointer) : $() %9999 = tuple() return %9999 : $() } // CHECK-LABEL: sil @simplify_struct_test : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { // CHECK-NOT: struct // CHECK: } // end sil function 'simplify_struct_test' sil @simplify_struct_test : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { bb0(%0 : $Builtin.Int64): %1 = struct $Int64 (%0 : $Builtin.Int64) %2 = struct_extract %1 : $Int64, #Int64.value return %2 : $Builtin.Int64 } // CHECK-LABEL: sil @simplify_tuple_test : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { // CHECK-NOT: tuple // CHECK: } // end sil function 'simplify_tuple_test' sil @simplify_tuple_test : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { bb0(%0 : $Builtin.Int64): %1 = tuple(%0 : $Builtin.Int64, %0 : $Builtin.Int64) %2 = tuple_extract %1 : $(Builtin.Int64, Builtin.Int64), 0 return %2 : $Builtin.Int64 } // CHECK-LABEL: sil [canonical] @isConcrete_true : $@convention(thin) (@thin UInt.Type) -> Builtin.Int1 { // CHECK: bb0( // CHECK-NEXT: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1 // CHECK-NEXT: return [[RESULT]] // CHECK-NEXT: } // end sil function 'isConcrete_true' sil [canonical] @isConcrete_true : $@convention(thin) (@thin UInt.Type) -> Builtin.Int1 { bb0(%0 : $@thin UInt.Type): %1 = builtin "isConcrete"(%0 : $@thin UInt.Type) : $Builtin.Int1 return %1 : $Builtin.Int1 } // CHECK-LABEL: sil [canonical] @isConcrete_false : $@convention(thin) (@thin T.Type) -> Builtin.Int1 { // CHECK: bb0( // CHECK-NEXT: [[RESULT:%.*]] = builtin "isConcrete"( // CHECK-NEXT: return [[RESULT]] // CHECK-NEXT: } // end sil function 'isConcrete_false' sil [canonical] @isConcrete_false : $@convention(thin) (@thin T.Type) -> Builtin.Int1 { bb0(%0 : $@thin T.Type): %1 = builtin "isConcrete"(%0 : $@thin T.Type) : $Builtin.Int1 return %1 : $Builtin.Int1 } class AClass {} class BClass : AClass {} // CHECK-LABEL: sil @test_checked_cast_br_thick_class_type // CHECK: [[METATYPE:%.*]] = metatype $@thick BClass.Type // CHECK: [[SUPER:%.*]] = upcast [[METATYPE]] : $@thick BClass.Type to $@thick AClass.Type // CHECK: br bb1([[SUPER]] : $@thick AClass.Type) sil @test_checked_cast_br_thick_class_type : $@convention(thin) (@thin P.Protocol) -> Builtin.Int1 { bb0(%0 : $@thin P.Protocol): %2 = metatype $@thick BClass.Type checked_cast_br %2 : $@thick BClass.Type to AClass.Type, bb1, bb2 bb1(%5 : $@thick AClass.Type): debug_value %5 : $@thick AClass.Type, let, name "type" %6 = integer_literal $Builtin.Int1, -1 br bb3(%6 : $Builtin.Int1) bb2: %9 = integer_literal $Builtin.Int1, 0 br bb3(%9 : $Builtin.Int1) bb3(%11 : $Builtin.Int1): return %11 : $Builtin.Int1 }