1; RUN: opt -S -loop-unswitch < %s | FileCheck %s 2 3declare void @llvm.experimental.guard(i1, ...) 4 5define 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"() ] 11entry: 12 br label %loop 13 14loop: 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 22leave: 23 ret void 24} 25 26define 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) ] 39entry: 40 br label %loop 41 42loop: 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 51leave: 52 ret void 53} 54 55; Basic negative test 56 57define void @f_3(i32 %n, i32* %ptr, i1* %c_ptr) { 58; CHECK-LABEL: @f_3( 59; CHECK-NOT: loop.us: 60entry: 61 br label %loop 62 63loop: 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 72leave: 73 ret void 74} 75 76define 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). 82entry: 83 br label %loop 84 85loop: 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 95leave: 96 ret void 97} 98