| // RUN: %target-sil-opt -enable-sil-verify-all %s -licm | FileCheck %s |
| |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| |
| // CHECK-LABEL: @memset |
| |
| // CHECK: bb0 |
| // CHECK: load %0 |
| // CHECK: br bb2 |
| |
| // CHECK: bb2({{.*}}): |
| // CHECK-NOT: load |
| // CHECK-NOT: fix_lifetime |
| // CHECK: cond_br |
| |
| sil @memset : $@convention(thin) (@inout Builtin.NativeObject, Int) -> () { |
| bb0(%0 : $*Builtin.NativeObject, %1 : $Int): |
| %5 = integer_literal $Builtin.Int1, -1 |
| %46 = integer_literal $Builtin.Word, 0 |
| br bb2(%46 : $Builtin.Word) |
| |
| bb1: |
| %52 = tuple () |
| return %52 : $() |
| |
| bb2(%54 : $Builtin.Word): |
| %55 = integer_literal $Builtin.Word, 1 |
| %57 = builtin "sadd_with_overflow_Word"(%54 : $Builtin.Word, %55 : $Builtin.Word, %5 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1) |
| %58 = tuple_extract %57 : $(Builtin.Word, Builtin.Int1), 0 |
| %59 = load %0 : $*Builtin.NativeObject |
| %60 = integer_literal $Builtin.Word, 100 |
| %96 = ref_to_raw_pointer %59 : $Builtin.NativeObject to $Builtin.RawPointer |
| %97 = index_raw_pointer %96 : $Builtin.RawPointer, %58 : $Builtin.Word |
| %98 = pointer_to_address %97 : $Builtin.RawPointer to $*Int |
| %99 = index_addr %98 : $*Int, %54 : $Builtin.Word |
| fix_lifetime %59: $Builtin.NativeObject |
| store %1 to %99 : $*Int |
| %101 = builtin "cmp_eq_Word"(%58 : $Builtin.Word, %60 : $Builtin.Word) : $Builtin.Int1 |
| cond_br %101, bb1, bb2(%58 : $Builtin.Word) |
| } |
| |
| // CHECK-LABEL: @must_move_condfail |
| |
| // CHECK: bb0 |
| // CHECK: load %0 |
| // CHECK: cond_fail |
| // CHECK: [[INVARIANTADDR:%.*]] = pointer_to_address |
| // CHECK: load [[INVARIANTADDR]] |
| // CHECK: br bb2 |
| |
| // CHECK: bb2({{.*}}): |
| // The address computation of the load was guarded by the cond_fail. If we hoist |
| // the load we must also hoist the cond_fail. |
| // CHECK-NOT: cond_fail |
| // CHECK-NOT: load |
| // CHECK: cond_br |
| |
| sil @must_move_condfail : $@convention(thin) (@inout Builtin.NativeObject, Int, Builtin.Word) -> () { |
| bb0(%0 : $*Builtin.NativeObject, %1 : $Int, %2: $Builtin.Word): |
| %5 = integer_literal $Builtin.Int1, -1 |
| %6 = load %0 : $*Builtin.NativeObject |
| %46 = integer_literal $Builtin.Word, 0 |
| br bb2(%46 : $Builtin.Word) |
| |
| bb1: |
| %102 = tuple () |
| return %102 : $() |
| |
| bb2(%48 : $Builtin.Word): |
| %51 = builtin "sadd_with_overflow_Word"(%2 : $Builtin.Word, %46 : $Builtin.Word, %5 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1) |
| %52 = tuple_extract %51 : $(Builtin.Word, Builtin.Int1), 0 |
| %53 = tuple_extract %51 : $(Builtin.Word, Builtin.Int1), 1 |
| cond_fail %53 : $Builtin.Int1 |
| %55 = integer_literal $Builtin.Word, 1 |
| %57 = builtin "sadd_with_overflow_Word"(%48 : $Builtin.Word, %55 : $Builtin.Word, %5 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1) |
| %58 = tuple_extract %57 : $(Builtin.Word, Builtin.Int1), 0 |
| %60 = integer_literal $Builtin.Word, 100 |
| %61 = ref_to_raw_pointer %6 : $Builtin.NativeObject to $Builtin.RawPointer |
| %62 = index_raw_pointer %61 : $Builtin.RawPointer, %52 : $Builtin.Word |
| %63 = pointer_to_address %62 : $Builtin.RawPointer to $*Builtin.NativeObject |
| %64 = load %63 : $*Builtin.NativeObject |
| %96 = ref_to_raw_pointer %64 : $Builtin.NativeObject to $Builtin.RawPointer |
| %97 = index_raw_pointer %96 : $Builtin.RawPointer, %58 : $Builtin.Word |
| %98 = pointer_to_address %97 : $Builtin.RawPointer to $*Int |
| %99 = index_addr %98 : $*Int, %48 : $Builtin.Word |
| store %1 to %99 : $*Int |
| %101 = builtin "cmp_eq_Word"(%58 : $Builtin.Word, %60 : $Builtin.Word) : $Builtin.Int1 |
| cond_br %101, bb1, bb2(%58 : $Builtin.Word) |
| } |
| |
| |
| // CHECK-LABEL: sil @hoist_outer_loop |
| // CHECK: bb0([[ADDR:%.*]] : $*Builtin.Int1 |
| // CHECK: load [[ADDR]] |
| // CHECK: integer_literal $Builtin.Word, 101 |
| // CHECK: br bb1 |
| // CHECK: return |
| |
| sil @hoist_outer_loop : $@convention(thin) (@inout Builtin.Int1, Int) -> () { |
| bb0(%0 : $*Builtin.Int1, %1 : $Int): |
| %2 = integer_literal $Builtin.Int1, -1 |
| %3 = integer_literal $Builtin.Word, 0 |
| br bb1 |
| |
| // Outer loop. |
| bb1: |
| %5 = load %0 : $*Builtin.Int1 |
| %6 = integer_literal $Builtin.Word, 101 |
| cond_br %5, bb2, bb3 |
| |
| bb2: |
| cond_br %5, bb4, bb1 |
| |
| // Inner loop. |
| bb3: |
| cond_br %5, bb2, bb3 |
| |
| bb4: |
| %10 = tuple () |
| return %10 : $() |
| } |
| |
| // CHECK-LABEL: sil @dont_hoist_outer_loop |
| // CHECK: bb0([[ADDR:%.*]] : $*Builtin.Int1 |
| // CHECK: integer_literal $Builtin.Word, 101 |
| // CHECK: br bb1 |
| // CHECK: bb1: |
| // CHECK: load [[ADDR]] |
| // CHECK: return |
| |
| sil @dont_hoist_outer_loop : $@convention(thin) (@inout Builtin.Int1, Int) -> () { |
| bb0(%0 : $*Builtin.Int1, %1 : $Int): |
| %2 = integer_literal $Builtin.Int1, -1 |
| %3 = integer_literal $Builtin.Word, 0 |
| br bb1 |
| |
| // Outer loop. |
| bb1: |
| %5 = load %0 : $*Builtin.Int1 |
| %6 = integer_literal $Builtin.Word, 101 |
| cond_br %5, bb2, bb3 |
| |
| bb2: |
| cond_br %5, bb4, bb1 |
| |
| // Inner loop. |
| bb3: |
| store %2 to %0 : $*Builtin.Int1 |
| cond_br %5, bb2, bb3 |
| |
| bb4: |
| %10 = tuple () |
| return %10 : $() |
| } |
| |
| sil [_semantics "array.get_count"] @getCount : $@convention(method) (@guaranteed Array<Int>) -> Int |
| sil @user : $@convention(thin) (Int) -> () |
| |
| // CHECK-LABEL: sil @dont_hoist_get_count_on_low_level_sil |
| // CHECK: {{^}}bb1: |
| // CHECK: apply |
| // CHECK: apply |
| // CHECK: {{^}}bb2: |
| // CHECK: return |
| sil @dont_hoist_get_count_on_low_level_sil : $@convention(thin) (@guaranteed Array<Int>) -> () { |
| bb0(%0 : $Array<Int>): |
| br bb1 |
| |
| bb1: |
| %f1 = function_ref @getCount : $@convention(method) (@guaranteed Array<Int>) -> Int |
| %f2 = function_ref @user : $@convention(thin) (Int) -> () |
| %c1 = apply %f1(%0) : $@convention(method) (@guaranteed Array<Int>) -> Int |
| %c2 = apply %f2(%c1) : $@convention(thin) (Int) -> () |
| cond_br undef, bb1, bb2 |
| |
| bb2: |
| %r1 = tuple () |
| return %r1 : $() |
| } |
| |
| // CHECK-LABEL: sil @dont_hoist_aliased_stack_location |
| // CHECK: {{^}}bb0 |
| // CHECK-NOT: load |
| // CHECK: {{^}}bb1: |
| // CHECK: store |
| // CHECK: load |
| // CHECK: {{^}}bb2: |
| // CHECK: return |
| sil @dont_hoist_aliased_stack_location : $@convention(thin) (Int32) -> () { |
| bb0(%0 : $Int32): |
| %313 = alloc_stack $Int32 |
| br bb1 |
| |
| bb1: |
| store %0 to %313#1 : $*Int32 |
| %l1 = load %313#1 : $*Int32 |
| cond_br undef, bb1, bb2 |
| |
| bb2: |
| dealloc_stack %313#0 : $*@local_storage Int32 |
| %52 = tuple () |
| return %52 : $() |
| } |