| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -diagnostic-constant-propagation | %FileCheck %s |
| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -performance-constant-propagation | %FileCheck %s |
| |
| 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 |
| } |
| |
| // 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) () -> () { |
| bb0: |
| %1 = integer_literal $Builtin.Int1, 1 |
| %2 = integer_literal $Builtin.Int1, 0 |
| %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 |
| %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: 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 |
| } |
| |
| // 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_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.Int2048, 1 // user: %2 |
| %2 = builtin "s_to_s_checked_trunc_Int2048_Int64"(%0 : $Builtin.Int2048) : $(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.Int2048, 2 // user: %8 |
| %8 = builtin "s_to_s_checked_trunc_Int2048_Int64"(%6 : $Builtin.Int2048) : $(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.Int2048, 1 |
| %5 = builtin "s_to_u_checked_trunc_Int2048_Word"(%3 : $Builtin.Int2048) : $(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.Int2048, 0 |
| %11 = builtin "s_to_u_checked_trunc_Int2048_Word"(%9 : $Builtin.Int2048) : $(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.Int2048, 1 |
| %17 = builtin "s_to_u_checked_trunc_Int2048_Word"(%15 : $Builtin.Int2048) : $(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.Int2048, 0 |
| %27 = builtin "s_to_s_checked_trunc_Int2048_Word"(%25 : $Builtin.Int2048) : $(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 take_always AnObject in %31 : $*AnObject to Value in %2 : $*Value |
| %32 = alloc_stack $AnObject |
| dealloc_stack %32: $*AnObject |
| dealloc_stack %31 : $*AnObject |
| br bb1 |
| } |