1 ; RUN: opt -S -loop-unswitch < %s | FileCheck %s 2 3 declare void @llvm.experimental.guard(i1, ...) 4 5 define void @f_0(i32 %n, i32* %ptr, i1 %c) { 6 ; CHECK-LABEL: @f_0( 7 ; CHECK: loop.us: 8 ; CHECK-NOT: guard 9 ; CHECK: loop: 10 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 11 entry: 12 br label %loop 13 14 loop: 15 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 16 %iv.inc = add i32 %iv, 1 17 call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ] 18 store volatile i32 0, i32* %ptr 19 %becond = icmp ult i32 %iv.inc, %n 20 br i1 %becond, label %leave, label %loop 21 22 leave: 23 ret void 24 } 25 26 define void @f_1(i32 %n, i32* %ptr, i1 %c_0, i1 %c_1) { 27 ; CHECK-LABEL: @f_1( 28 ; CHECK: loop.us.us: 29 ; CHECK-NOT: guard 30 ; CHECK: loop.us: 31 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 2) ] 32 ; CHECK-NOT: guard 33 ; CHECK: loop.us1: 34 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 1) ] 35 ; CHECK-NOT: guard 36 ; CHECK: loop: 37 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 1) ] 38 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 2) ] 39 entry: 40 br label %loop 41 42 loop: 43 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 44 %iv.inc = add i32 %iv, 1 45 call void(i1, ...) @llvm.experimental.guard(i1 %c_0) [ "deopt"(i32 1) ] 46 store volatile i32 0, i32* %ptr 47 call void(i1, ...) @llvm.experimental.guard(i1 %c_1) [ "deopt"(i32 2) ] 48 %becond = icmp ult i32 %iv.inc, %n 49 br i1 %becond, label %leave, label %loop 50 51 leave: 52 ret void 53 } 54 55 ; Basic negative test 56 57 define void @f_3(i32 %n, i32* %ptr, i1* %c_ptr) { 58 ; CHECK-LABEL: @f_3( 59 ; CHECK-NOT: loop.us: 60 entry: 61 br label %loop 62 63 loop: 64 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 65 %iv.inc = add i32 %iv, 1 66 %c = load volatile i1, i1* %c_ptr 67 call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ] 68 store volatile i32 0, i32* %ptr 69 %becond = icmp ult i32 %iv.inc, %n 70 br i1 %becond, label %leave, label %loop 71 72 leave: 73 ret void 74 } 75 76 define void @f_4(i32 %n, i32* %ptr, i1 %c) { 77 ; CHECK-LABEL: @f_4( 78 ; 79 ; Demonstrate that unswitching on one guard can cause another guard to 80 ; be erased (this has implications on what guards we can keep raw 81 ; pointers to). 82 entry: 83 br label %loop 84 85 loop: 86 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 87 %iv.inc = add i32 %iv, 1 88 call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"(i32 1) ] 89 store volatile i32 0, i32* %ptr 90 %neg = xor i1 %c, 1 91 call void(i1, ...) @llvm.experimental.guard(i1 %neg) [ "deopt"(i32 2) ] 92 %becond = icmp ult i32 %iv.inc, %n 93 br i1 %becond, label %leave, label %loop 94 95 leave: 96 ret void 97 } 98