mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* access * accessed * accesses * accessor * acquiring * across * activated * additive * address * addresses' * aggregated * analysis * and * appropriately * archetype * argument * associated * availability * barriers * because * been * beginning * belongs * beneficial * blocks * borrow * builtin * cannot * canonical * canonicalize * clazz * cleanup * coalesceable * coalesced * comparisons * completely * component * computed * concrete * conjunction * conservatively * constituent * construct * consuming * containing * covered * creates * critical * dataflow * declaration * defined * defining * definition * deinitialization * deliberately * dependencies * dependent * deserialized * destroy * deterministic * deterministically * devirtualizes * diagnostic * diagnostics * differentiation * disable * discipline * dominate * dominates * don't * element * eliminate * eliminating * elimination * embedded * encounter * epilogue * epsilon * escape * escaping * essential * evaluating * evaluation * evaluator * executing * existential * existentials * explicit * expression * extended * extension * extract * for * from * function * generic * guarantee * guaranteed * happened * heuristic * however * identifiable * immediately * implementation * improper * include * infinite * initialize * initialized * initializer * inside * instruction * interference * interferes * interleaved * internal * intersection * intractable * intrinsic * invalidates * irreducible * irrelevant * language * lifetime * literal * looks * materialize * meaning * mergeable * might * mimics * modification * modifies * multiple * mutating * necessarily * necessary * needsmultiplecopies * nonetheless * nothing * occurred * occurs * optimization * optimizing * original * outside * overflow * overlapping * overridden * owned * ownership * parallel * parameter * paths * patterns * pipeline * plottable * possible * potentially * practically * preamble * precede * preceding * predecessor * preferable * preparation * probably * projection * properties * property * protocol * reabstraction * reachable * recognized * recursive * recursively * redundant * reentrancy * referenced * registry * reinitialization * reload * represent * requires * response * responsible * retrieving * returned * returning * returns * rewriting * rewritten * sample * scenarios * scope * should * sideeffects * similar * simplify * simplifycfg * somewhat * spaghetti * specialization * specializations * specialized * specially * statistically * substitute * substitution * succeeds * successful * successfully * successor * superfluous * surprisingly * suspension * swift * targeted * that * that our * the * therefore * this * those * threshold * through * transform * transformation * truncated * ultimate * unchecked * uninitialized * unlikely * unmanaged * unoptimized key * updataflow * usefulness * utilities * villain * whenever * writes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
797 lines
42 KiB
Plaintext
797 lines
42 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -remove-redundant-overflow-checks | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
sil [noinline] @sink_unsigned_int : $@convention(thin) () -> ()
|
|
sil [noinline] @sink_signed_int : $@convention(thin) () -> ()
|
|
|
|
// CHECK-LABEL: @sub_signed_branch_cond
|
|
sil hidden @sub_signed_branch_cond : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 2 // users: %3, %12
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %3, %7, %12, %17
|
|
%3 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb2, bb1 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 1 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // users: %7, %12, %17
|
|
%7 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %8 : $Builtin.Int1 // id: %9
|
|
%10 = function_ref @sink_unsigned_int : $@convention(thin) () -> () // users: %11, %15, %20
|
|
%11 = apply %10() : $@convention(thin) () -> ()
|
|
%12 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
%15 = apply %10() : $@convention(thin) () -> ()
|
|
|
|
// CHECK that we do not remove the '3' because it is not guarder by the branch.
|
|
// CHECK: integer_literal $Builtin.Int64, 3
|
|
// CHECK: cond_fail
|
|
%16 = integer_literal $Builtin.Int64, 3 // user: %17
|
|
%17 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %16 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %18
|
|
%18 = tuple_extract %17 : $(Builtin.Int64, Builtin.Int1), 1 // user: %19
|
|
cond_fail %18 : $Builtin.Int1 // id: %19
|
|
%20 = apply %10() : $@convention(thin) () -> ()
|
|
br bb3 // id: %21
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%22 = tuple () // user: %23
|
|
// CHECK: return
|
|
return %22 : $() // id: %23
|
|
}
|
|
|
|
// CHECK-LABEL: @sub_signed_branch_cond2
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @sub_signed_branch_cond2: $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 2 // users: %3, %12
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %3, %7, %12, %17
|
|
%3 = builtin "cmp_sge_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb1, bb2 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 1 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // users: %7, %12, %17
|
|
%7 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
cond_fail %8 : $Builtin.Int1 // id: %9
|
|
%10 = function_ref @sink_unsigned_int : $@convention(thin) () -> () // users: %11, %15, %20
|
|
%11 = apply %10() : $@convention(thin) () -> ()
|
|
%12 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
%15 = apply %10() : $@convention(thin) () -> ()
|
|
%16 = integer_literal $Builtin.Int64, 3 // user: %17
|
|
%17 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %16 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %18
|
|
%18 = tuple_extract %17 : $(Builtin.Int64, Builtin.Int1), 1 // user: %19
|
|
cond_fail %13 : $Builtin.Int1 // id: %19
|
|
%20 = apply %10() : $@convention(thin) () -> ()
|
|
br bb3 // id: %21
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%22 = tuple () // user: %23
|
|
return %22 : $() // id: %23
|
|
}
|
|
|
|
// CHECK-LABEL: @sub_unsigned_branch_cond
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @sub_unsigned_branch_cond : $@convention(thin) (UInt64) -> () {
|
|
bb0(%0 : $UInt64):
|
|
%1 = integer_literal $Builtin.Int64, 2 // users: %3, %12
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %3, %7, %12, %17
|
|
%3 = builtin "cmp_ult_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb2, bb1 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 1 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // users: %7, %12, %17
|
|
%7 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
cond_fail %8 : $Builtin.Int1 // id: %9
|
|
%10 = function_ref @sink_signed_int : $@convention(thin) () -> () // users: %11, %15, %20
|
|
%11 = apply %10() : $@convention(thin) () -> ()
|
|
%12 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
%15 = apply %10() : $@convention(thin) () -> ()
|
|
%16 = integer_literal $Builtin.Int64, 3 // user: %17
|
|
%17 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %16 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %18
|
|
%18 = tuple_extract %17 : $(Builtin.Int64, Builtin.Int1), 1 // user: %19
|
|
cond_fail %13 : $Builtin.Int1 // id: %19
|
|
%20 = apply %10() : $@convention(thin) () -> ()
|
|
br bb3 // id: %21
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3: // Preds: bb0 bb1
|
|
%22 = tuple () // user: %23
|
|
return %22 : $() // id: %23
|
|
}
|
|
|
|
// CHECK-LABEL: @sub_unsigned_branch_cond2
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @sub_unsigned_branch_cond2 : $@convention(thin) (UInt64) -> () {
|
|
bb0(%0 : $UInt64):
|
|
%1 = integer_literal $Builtin.Int64, 2 // users: %3, %12
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %3, %7, %12, %17
|
|
%3 = builtin "cmp_uge_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb1, bb2 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 1 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // users: %7, %12, %17
|
|
%7 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
cond_fail %8 : $Builtin.Int1 // id: %9
|
|
%10 = function_ref @sink_signed_int : $@convention(thin) () -> () // users: %11, %15, %20
|
|
%11 = apply %10() : $@convention(thin) () -> ()
|
|
%12 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
%15 = apply %10() : $@convention(thin) () -> ()
|
|
%16 = integer_literal $Builtin.Int64, 3 // user: %17
|
|
%17 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %16 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %18
|
|
%18 = tuple_extract %17 : $(Builtin.Int64, Builtin.Int1), 1 // user: %19
|
|
cond_fail %13 : $Builtin.Int1 // id: %19
|
|
%20 = apply %10() : $@convention(thin) () -> ()
|
|
br bb3 // id: %21
|
|
|
|
bb2: // Preds: bb0 bb1
|
|
br bb3
|
|
|
|
bb3:
|
|
%22 = tuple () // user: %23
|
|
return %22 : $() // id: %23
|
|
}
|
|
|
|
// CHECK-LABEL: @unsigned_sub_previous_traps
|
|
// Keep the first cond-fail
|
|
// CHECK: cond_fail
|
|
// Keep the condfail with +10 because it is not guarded by the first condfail (+9)
|
|
// CHECK: cond_fail
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @unsigned_sub_previous_traps : $@convention(thin) (UInt64) -> () {
|
|
bb0(%0 : $UInt64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
%7 = function_ref @sink_signed_int : $@convention(thin) () -> () // users: %8, %13, %18, %23, %28, %29
|
|
%8 = apply %7() : $@convention(thin) () -> ()
|
|
%9 = integer_literal $Builtin.Int64, 2 // user: %10
|
|
%10 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %9 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%11 = tuple_extract %10 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
cond_fail %11 : $Builtin.Int1 // id: %12
|
|
%13 = apply %7() : $@convention(thin) () -> ()
|
|
%14 = integer_literal $Builtin.Int64, 3 // user: %15
|
|
%15 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %16
|
|
%16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1 // user: %17
|
|
cond_fail %16 : $Builtin.Int1 // id: %17
|
|
%18 = apply %7() : $@convention(thin) () -> ()
|
|
%19 = integer_literal $Builtin.Int64, 5 // user: %20
|
|
%20 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %19 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %21
|
|
%21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 1 // user: %22
|
|
cond_fail %21 : $Builtin.Int1 // id: %22
|
|
%23 = apply %7() : $@convention(thin) () -> ()
|
|
%24 = integer_literal $Builtin.Int64, 10 // user: %25
|
|
%25 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %24 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %26
|
|
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 1 // user: %27
|
|
cond_fail %26 : $Builtin.Int1 // id: %27
|
|
%28 = apply %7() : $@convention(thin) () -> ()
|
|
%29 = apply %7() : $@convention(thin) () -> ()
|
|
%30 = tuple () // user: %31
|
|
return %30 : $() // id: %31
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_sub_previous_traps
|
|
sil hidden @signed_sub_previous_traps : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
// Keep this condfail because it is the first one.
|
|
// CHECK: cond_fail
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
%7 = function_ref @sink_unsigned_int : $@convention(thin) () -> () // users: %8, %13, %18, %23, %28, %29
|
|
%8 = apply %7() : $@convention(thin) () -> ()
|
|
%9 = integer_literal $Builtin.Int64, 2 // user: %10
|
|
%10 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %9 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%11 = tuple_extract %10 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
cond_fail %11 : $Builtin.Int1 // id: %12
|
|
%13 = apply %7() : $@convention(thin) () -> ()
|
|
%14 = integer_literal $Builtin.Int64, 3 // user: %15
|
|
%15 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %16
|
|
%16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1 // user: %17
|
|
cond_fail %16 : $Builtin.Int1 // id: %17
|
|
%18 = apply %7() : $@convention(thin) () -> ()
|
|
%19 = integer_literal $Builtin.Int64, 5 // user: %20
|
|
%20 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %19 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %21
|
|
%21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 1 // user: %22
|
|
cond_fail %21 : $Builtin.Int1 // id: %22
|
|
%23 = apply %7() : $@convention(thin) () -> ()
|
|
%24 = integer_literal $Builtin.Int64, 10 // user: %25
|
|
%25 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %24 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %26
|
|
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 1 // user: %27
|
|
// Keep this condfail because it is not in the guarded range.
|
|
// CHECK: cond_fail
|
|
cond_fail %26 : $Builtin.Int1 // id: %27
|
|
%28 = apply %7() : $@convention(thin) () -> ()
|
|
%29 = apply %7() : $@convention(thin) () -> ()
|
|
%30 = tuple () // user: %31
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
return %30 : $() // id: %31
|
|
}
|
|
|
|
// CHECK-LABEL: @unsigned_add_previous_traps
|
|
sil hidden @unsigned_add_previous_traps : $@convention(thin) (UInt64) -> () {
|
|
bb0(%0 : $UInt64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
// Keep the first condfail.
|
|
//CHECK: cond_fail
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
%7 = function_ref @sink_signed_int : $@convention(thin) () -> () // users: %8, %13, %18, %23, %28, %29
|
|
%8 = apply %7() : $@convention(thin) () -> ()
|
|
%9 = integer_literal $Builtin.Int64, 2 // user: %10
|
|
%10 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %9 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%11 = tuple_extract %10 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
cond_fail %11 : $Builtin.Int1 // id: %12
|
|
%13 = apply %7() : $@convention(thin) () -> ()
|
|
%14 = integer_literal $Builtin.Int64, 3 // user: %15
|
|
%15 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %16
|
|
%16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1 // user: %17
|
|
cond_fail %16 : $Builtin.Int1 // id: %17
|
|
%18 = apply %7() : $@convention(thin) () -> ()
|
|
%19 = integer_literal $Builtin.Int64, 5 // user: %20
|
|
%20 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %19 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %21
|
|
%21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 1 // user: %22
|
|
cond_fail %21 : $Builtin.Int1 // id: %22
|
|
%23 = apply %7() : $@convention(thin) () -> ()
|
|
%24 = integer_literal $Builtin.Int64, 10 // user: %25
|
|
%25 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %24 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %26
|
|
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 1 // user: %27
|
|
// Keep the out-of-range condfail.
|
|
//CHECK: cond_fail
|
|
cond_fail %26 : $Builtin.Int1 // id: %27
|
|
%28 = apply %7() : $@convention(thin) () -> ()
|
|
%29 = apply %7() : $@convention(thin) () -> ()
|
|
%30 = tuple () // user: %31
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
return %30 : $() // id: %31
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_add_previous_traps
|
|
// Keep the first condfail
|
|
// CHECK: cond_fail
|
|
// Keep out-of-range condfail
|
|
// CHECK: cond_fail
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_add_previous_traps : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
%7 = function_ref @sink_unsigned_int : $@convention(thin) () -> () // users: %8, %13, %18, %23, %28, %29
|
|
%8 = apply %7() : $@convention(thin) () -> ()
|
|
%9 = integer_literal $Builtin.Int64, 2 // user: %10
|
|
%10 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %9 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%11 = tuple_extract %10 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
cond_fail %11 : $Builtin.Int1 // id: %12
|
|
%13 = apply %7() : $@convention(thin) () -> ()
|
|
%14 = integer_literal $Builtin.Int64, 3 // user: %15
|
|
%15 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %16
|
|
%16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1 // user: %17
|
|
cond_fail %16 : $Builtin.Int1 // id: %17
|
|
%18 = apply %7() : $@convention(thin) () -> ()
|
|
%19 = integer_literal $Builtin.Int64, 5 // user: %20
|
|
%20 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %19 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %21
|
|
%21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 1 // user: %22
|
|
cond_fail %21 : $Builtin.Int1 // id: %22
|
|
%23 = apply %7() : $@convention(thin) () -> ()
|
|
%24 = integer_literal $Builtin.Int64, 10 // user: %25
|
|
%25 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %24 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %26
|
|
%26 = tuple_extract %25 : $(Builtin.Int64, Builtin.Int1), 1 // user: %27
|
|
cond_fail %26 : $Builtin.Int1 // id: %27
|
|
%28 = apply %7() : $@convention(thin) () -> ()
|
|
%29 = apply %7() : $@convention(thin) () -> ()
|
|
%30 = tuple () // user: %31
|
|
return %30 : $() // id: %31
|
|
}
|
|
|
|
// CHECK-LABEL: @add1_signed_branch
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @add1_signed_branch : $@convention(thin) (Int64, Int64) -> () {
|
|
bb0(%0 : $Int64, %1 : $Int64):
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %8, %14
|
|
%3 = struct_extract %1 : $Int64, #Int64._value // user: %4
|
|
%4 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1 // user: %5
|
|
cond_br %4, bb1, bb2 // id: %5
|
|
|
|
bb1: // Preds: bb0
|
|
%6 = integer_literal $Builtin.Int64, 1 // user: %8
|
|
%7 = integer_literal $Builtin.Int1, -1 // users: %8, %14
|
|
%8 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %9
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %10
|
|
cond_fail %9 : $Builtin.Int1 // id: %10
|
|
%11 = function_ref @sink_unsigned_int : $@convention(thin) () -> () // users: %12, %17
|
|
%12 = apply %11() : $@convention(thin) () -> ()
|
|
%13 = integer_literal $Builtin.Int64, 2 // user: %14
|
|
%14 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %13 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %15
|
|
%15 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 1 // user: %16
|
|
cond_fail %9 : $Builtin.Int1 // id: %16
|
|
%17 = apply %11() : $@convention(thin) () -> ()
|
|
br bb3 // id: %18
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%19 = tuple () // user: %20
|
|
return %19 : $() // id: %20
|
|
}
|
|
|
|
// CHECK-LABEL: @add1_unsigned_branch
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @add1_unsigned_branch : $@convention(thin) (UInt64, UInt64) -> () {
|
|
bb0(%0 : $UInt64, %1 : $UInt64):
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %4, %8, %14
|
|
%3 = struct_extract %1 : $UInt64, #UInt64._value // user: %4
|
|
%4 = builtin "cmp_ult_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1 // user: %5
|
|
cond_br %4, bb1, bb2 // id: %5
|
|
|
|
bb1: // Preds: bb0
|
|
%6 = integer_literal $Builtin.Int64, 1 // user: %8
|
|
%7 = integer_literal $Builtin.Int1, -1 // users: %8, %14
|
|
%8 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %9
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %10
|
|
cond_fail %9 : $Builtin.Int1 // id: %10
|
|
%11 = function_ref @sink_signed_int : $@convention(thin) () -> () // users: %12, %17
|
|
%12 = apply %11() : $@convention(thin) () -> ()
|
|
%13 = integer_literal $Builtin.Int64, 2 // user: %14
|
|
%14 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %13 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %15
|
|
%15 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 1 // user: %16
|
|
cond_fail %9 : $Builtin.Int1 // id: %16
|
|
%17 = apply %11() : $@convention(thin) () -> ()
|
|
br bb3 // id: %18
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%19 = tuple () // user: %20
|
|
return %19 : $() // id: %20
|
|
}
|
|
|
|
// CHECK-LABEL: @remove_past_checks
|
|
sil hidden @remove_past_checks : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 1 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %8, %12, %16, %20
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %8, %12, %16, %20
|
|
// CHECK: sadd_with_overflow_Int64
|
|
%4 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
%7 = integer_literal $Builtin.Int64, 2 // user: %8
|
|
// CHECK: sadd_with_overflow_Int64
|
|
%8 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %7 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %9
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %10
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %9 : $Builtin.Int1 // id: %10
|
|
%11 = integer_literal $Builtin.Int64, 3 // user: %12
|
|
// CHECK: sadd_with_overflow_Int64
|
|
%12 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %11 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
%15 = integer_literal $Builtin.Int64, 4 // user: %16
|
|
// CHECK: sadd_with_overflow_Int64
|
|
%16 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %15 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %17
|
|
%17 = tuple_extract %16 : $(Builtin.Int64, Builtin.Int1), 1 // user: %18
|
|
// CHECK-NOT: cond_fail
|
|
cond_fail %17 : $Builtin.Int1 // id: %18
|
|
%19 = integer_literal $Builtin.Int64, 5 // user: %20
|
|
// CHECK: sadd_with_overflow_Int64
|
|
%20 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %19 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %21
|
|
%21 = tuple_extract %20 : $(Builtin.Int64, Builtin.Int1), 1 // user: %22
|
|
// We keep the last cond-fail, which is enough to guard all the others.
|
|
// CHECK: cond_fail
|
|
cond_fail %21 : $Builtin.Int1 // id: %22
|
|
%23 = tuple () // user: %24
|
|
// CHECK: return
|
|
return %23 : $() // id: %24
|
|
}
|
|
|
|
|
|
// Make sure we are not crashing on this one (and that we are not removing the condfails)
|
|
// This comes from the following test:
|
|
//func foo(x : Int64, y : Int8) {
|
|
// 3 + x
|
|
// 2 + y
|
|
//}
|
|
// CHECK-LABEL: @bitwidth_crash
|
|
// CHECK: cond_fail
|
|
// CHECK: cond_fail
|
|
// CHECK: return
|
|
sil hidden @bitwidth_crash : $@convention(thin) (Int64, Int8) -> () {
|
|
bb0(%0 : $Int64, %1 : $Int8):
|
|
%2 = integer_literal $Builtin.Int64, 3 // user: %5
|
|
%3 = struct_extract %0 : $Int64, #Int64._value // user: %5
|
|
%4 = integer_literal $Builtin.Int1, -1 // users: %5, %10
|
|
%5 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64, %4 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %6
|
|
%6 = tuple_extract %5 : $(Builtin.Int64, Builtin.Int1), 1 // user: %7
|
|
cond_fail %6 : $Builtin.Int1 // id: %7
|
|
%8 = integer_literal $Builtin.Int8, 2 // user: %10
|
|
%9 = struct_extract %1 : $Int8, #Int8._value // user: %10
|
|
%10 = builtin "sadd_with_overflow_Int8"(%8 : $Builtin.Int8, %9 : $Builtin.Int8, %4 : $Builtin.Int1) : $(Builtin.Int8, Builtin.Int1) // user: %11
|
|
%11 = tuple_extract %10 : $(Builtin.Int8, Builtin.Int1), 1 // user: %12
|
|
cond_fail %11 : $Builtin.Int1 // id: %12
|
|
%13 = tuple () // user: %14
|
|
return %13 : $() // id: %14
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_cmpeq_sub
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_cmpeq_sub : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 3 // users: %3, %12
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %3, %7, %12
|
|
%3 = builtin "cmp_ne_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb1, bb2 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 999 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // user: %7
|
|
%7 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
%9 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
br bb3 // id: %10
|
|
|
|
bb2: // Preds: bb0
|
|
%11 = integer_literal $Builtin.Int1, -1 // user: %12
|
|
%12 = builtin "ssub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %11 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
br bb3 // id: %15
|
|
|
|
bb3: // Preds: bb1 bb2
|
|
%16 = tuple () // user: %17
|
|
return %16 : $() // id: %17
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @unsigned_cmpeq_sub
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @unsigned_cmpeq_sub : $@convention(thin) (UInt64) -> () {
|
|
bb0(%0 : $UInt64):
|
|
%1 = integer_literal $Builtin.Int64, 3 // users: %3, %12
|
|
%2 = struct_extract %0 : $UInt64, #UInt64._value // users: %3, %7, %12
|
|
%3 = builtin "cmp_ne_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int1 // user: %4
|
|
cond_br %3, bb1, bb2 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
%5 = integer_literal $Builtin.Int64, 999 // user: %7
|
|
%6 = integer_literal $Builtin.Int1, -1 // user: %7
|
|
%7 = builtin "uadd_with_overflow_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %8
|
|
%8 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
%9 = tuple_extract %7 : $(Builtin.Int64, Builtin.Int1), 1 // user: %9
|
|
br bb3 // id: %10
|
|
|
|
bb2: // Preds: bb0
|
|
%11 = integer_literal $Builtin.Int1, -1 // user: %12
|
|
%12 = builtin "usub_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %11 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %13
|
|
%13 = tuple_extract %12 : $(Builtin.Int64, Builtin.Int1), 1 // user: %14
|
|
cond_fail %13 : $Builtin.Int1 // id: %14
|
|
br bb3 // id: %15
|
|
|
|
bb3: // Preds: bb1 bb2
|
|
%16 = tuple () // user: %17
|
|
return %16 : $() // id: %17
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @signed_mul_previous_traps
|
|
// Keep the first condfail but remove the second one.
|
|
// CHECK: cond_fail
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_mul_previous_traps : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "smul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, 2
|
|
%8 = builtin "smul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// We can remove this check.
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @unsigned_mul_previous_traps
|
|
// Keep the first condfail but remove the second one.
|
|
// CHECK: umul_with_overflow_Int64
|
|
// CHECK: cond_fail
|
|
// CHECK: umul_with_overflow_Int64
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @unsigned_mul_previous_traps : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
%4 = builtin "umul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, 2
|
|
%8 = builtin "umul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// We can remove this check.
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_mul_previous_traps_neg
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK: smul_with_overflow_Int64
|
|
// Make sure we keep the last overflow check.
|
|
// CHECK: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_mul_previous_traps_neg : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 9 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
|
|
// This is X * 9
|
|
// We can remove this check because the following check will guard us: abs(-100) > abs(9).
|
|
%4 = builtin "smul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, -100
|
|
%8 = builtin "smul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// This is -100 * X. We can't remove this check because abs(-100) > abs(9).
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_mul_previous_traps_abs_neg
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK: cond_fail
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_mul_previous_traps_abs_neg : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 1000 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
|
|
// This is X * 9
|
|
%4 = builtin "smul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, -100
|
|
%8 = builtin "smul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// This is -100 * X. We can remove this check because abs(-100) < abs(1000).
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @signed_mul_previous_traps_abs_neg2
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK: cond_fail
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_mul_previous_traps_abs_neg2 : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 1000 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
|
|
// This is X * 9
|
|
%4 = builtin "smul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, -100
|
|
%8 = builtin "smul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// This is -100 * X. We can remove this check because abs(-100) < abs(1000).
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_mul_traps_min_int
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK: cond_fail
|
|
// CHECK: smul_with_overflow_Int64
|
|
// CHECK: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_mul_traps_min_int : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = integer_literal $Builtin.Int64, 1 // user: %4
|
|
%2 = struct_extract %0 : $Int64, #Int64._value // users: %4, %10, %15, %20, %25
|
|
%3 = integer_literal $Builtin.Int1, -1 // users: %4, %10, %15, %20, %25
|
|
|
|
// This is X * 9
|
|
%4 = builtin "smul_with_overflow_Int64"(%2 : $Builtin.Int64, %1 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %5
|
|
%5 = tuple_extract %4 : $(Builtin.Int64, Builtin.Int1), 1 // user: %6
|
|
cond_fail %5 : $Builtin.Int1 // id: %6
|
|
|
|
%7 = integer_literal $Builtin.Int64, -1
|
|
%8 = builtin "smul_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %12
|
|
|
|
// This is -1 * X. We can remove this check because X could be MIN_INT, and the result will overflow.
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @signed_min_int_comparison
|
|
// CHECK: smul_with_overflow_Int8
|
|
// CHECK: cond_fail
|
|
// CHECK: smul_with_overflow_Int8
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
sil hidden @signed_min_int_comparison : $@convention(thin) (Int8) -> () {
|
|
bb0(%0 : $Int8):
|
|
%1 = integer_literal $Builtin.Int8, -128
|
|
%2 = struct_extract %0 : $Int8, #Int8._value
|
|
%3 = integer_literal $Builtin.Int1, -1
|
|
|
|
%4 = builtin "smul_with_overflow_Int8"(%2 : $Builtin.Int8, %1 : $Builtin.Int8, %3 : $Builtin.Int1) : $(Builtin.Int8, Builtin.Int1)
|
|
%5 = tuple_extract %4 : $(Builtin.Int8, Builtin.Int1), 1
|
|
cond_fail %5 : $Builtin.Int1
|
|
|
|
%7 = integer_literal $Builtin.Int8, 127
|
|
%8 = builtin "smul_with_overflow_Int8"(%2 : $Builtin.Int8, %7 : $Builtin.Int8, %3 : $Builtin.Int1) : $(Builtin.Int8, Builtin.Int1) // user: %11
|
|
%9 = tuple_extract %8 : $(Builtin.Int8, Builtin.Int1), 1 // user: %12
|
|
|
|
cond_fail %9 : $Builtin.Int1
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @crash_unary_comparator
|
|
// CHECK: return
|
|
sil hidden @crash_unary_comparator : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = builtin "trunc_Int32_Int1"(%0 : $Builtin.Int32) : $Builtin.Int1
|
|
cond_br %1, bb1, bb2 // id: %4
|
|
|
|
bb1: // Preds: bb0
|
|
br bb3 // id: %10
|
|
|
|
bb2: // Preds: bb0
|
|
br bb3 // id: %15
|
|
|
|
bb3: // Preds: bb1 bb2
|
|
%3 = tuple () // user: %17
|
|
return %3 : $() // id: %17
|
|
}
|
|
|
|
// Check that we are not crashing on arithmetic of different kinds
|
|
// that makes formulas of different types.
|
|
sil hidden @mixed_types : $@convention(thin) (Int8) -> () {
|
|
bb0(%0 : $Int8):
|
|
%1 = integer_literal $Builtin.Int8, -128
|
|
%2 = struct_extract %0 : $Int8, #Int8._value
|
|
%3 = integer_literal $Builtin.Int1, -1
|
|
%4 = builtin "smul_with_overflow_Int8"(%2 : $Builtin.Int8, %1 : $Builtin.Int8, %3 : $Builtin.Int1) : $(Builtin.Int8, Builtin.Int1)
|
|
%5 = tuple_extract %4 : $(Builtin.Int8, Builtin.Int1), 1
|
|
cond_fail %5 : $Builtin.Int1
|
|
|
|
%v0 = integer_literal $Builtin.Int32, 128
|
|
%v1 = integer_literal $Builtin.Int32, 128
|
|
%v4 = builtin "smul_with_overflow_Int32"(%v1 : $Builtin.Int32, %v0 : $Builtin.Int32, %3 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
|
|
%v5 = tuple_extract %v4 : $(Builtin.Int32, Builtin.Int1), 1
|
|
cond_fail %v5 : $Builtin.Int1
|
|
|
|
|
|
%g0 = integer_literal $Builtin.Int64, 2
|
|
%g1 = integer_literal $Builtin.Int64, 1
|
|
%g3 = builtin "cmp_slt_Int64"(%g0 : $Builtin.Int64, %g1 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %g3 : $Builtin.Int1
|
|
|
|
%t0 = integer_literal $Builtin.Int32, 2
|
|
%t1 = integer_literal $Builtin.Int32, 1
|
|
%t3 = builtin "cmp_slt_Int32"(%t0 : $Builtin.Int32, %t1 : $Builtin.Int32) : $Builtin.Int1
|
|
cond_fail %t3 : $Builtin.Int1
|
|
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
}
|
|
|
|
// Check that the optimization can handle even patterns like this:
|
|
// %cmp_result = builtin "cmp_ult_Int64"(%x : $Builtin.Int64, %y : $Builtin.Int64) : $Builtin.Int1
|
|
// This cond_fail formula should be registered!
|
|
// cond_fail %cmp_result : $Builtin.Int1
|
|
// At this point we know that x >= y
|
|
// %usub_result = builtin "usub_with_overflow_Int64"(%x : $Builtin.Int64, %y : $Builtin.Int64, %check_overflow : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
// %usub_val = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 0
|
|
// We can figure out that x - y will not underflow because of x >= y
|
|
// %usub_underverflow = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 1
|
|
// cond_fail %usub_underflow : $Builtin.Int1
|
|
|
|
// CHECK-LABEL: sil @cond_fail_of_cmp
|
|
// CHECK: cond_fail
|
|
// Second cond_fail should be removed, because it never fails.
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: // end sil function 'cond_fail_of_cmp'
|
|
sil @cond_fail_of_cmp : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> () {
|
|
bb0(%x : $Builtin.Int64, %y: $Builtin.Int64):
|
|
%cmp_result = builtin "cmp_ult_Int64"(%x : $Builtin.Int64, %y : $Builtin.Int64) : $Builtin.Int1
|
|
// This cond_fail formula should be registered!
|
|
cond_fail %cmp_result : $Builtin.Int1
|
|
%check_overflow = integer_literal $Builtin.Int1, -1
|
|
// At this point we know that x >= y
|
|
%usub_result = builtin "usub_with_overflow_Int64"(%x : $Builtin.Int64, %y : $Builtin.Int64, %check_overflow : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%usub_val = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 0
|
|
// We can figure out that x - y will not underflow because of x >= y
|
|
%usub_underflow = tuple_extract %usub_result : $(Builtin.Int64, Builtin.Int1), 1
|
|
cond_fail %usub_underflow : $Builtin.Int1
|
|
|
|
%ret = tuple ()
|
|
return %ret : $()
|
|
} // end sil function 'cond_fail_of_cmp'
|