1 ; RUN: opt -S -indvars < %s | FileCheck %s 2 3 ; Check that SCEV is able to recognize and use guards to prove 4 ; conditions gaurding loop entries and backedges. This isn't intended 5 ; to be a comprehensive test of SCEV's simplification capabilities, 6 ; tests directly testing e.g. if SCEV can elide a sext should go 7 ; elsewhere. 8 9 target datalayout = "n8:16:32:64" 10 11 declare void @llvm.experimental.guard(i1, ...) 12 13 declare void @use(i64 %x) 14 15 define void @test_1(i1* %cond_buf, i32* %len_buf) { 16 ; CHECK-LABEL: @test_1( 17 entry: 18 %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648} 19 br label %loop 20 21 loop: 22 ; CHECK: loop: 23 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] 24 ; CHECK: %iv.inc.cmp = icmp ult i32 %iv.inc, %len 25 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 26 ; CHECK: leave: 27 28 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 29 %iv.inc = add i32 %iv, 1 30 31 %iv.cmp = icmp slt i32 %iv, %len 32 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 33 34 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 35 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 36 37 %becond = load volatile i1, i1* %cond_buf 38 br i1 %becond, label %loop, label %leave 39 40 leave: 41 ret void 42 } 43 44 define void @test_2(i32 %n, i32* %len_buf) { 45 ; CHECK-LABEL: @test_2( 46 ; CHECK: [[LEN_ZEXT:%[^ ]+]] = zext i32 %len to i64 47 ; CHECK: br label %loop 48 49 entry: 50 %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648} 51 br label %loop 52 53 loop: 54 ; CHECK: loop: 55 ; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ] 56 ; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 57 ; CHECK: %iv.inc.cmp = icmp ult i64 %indvars.iv.next, [[LEN_ZEXT]] 58 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 59 ; CHECK: leave: 60 61 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 62 %iv.inc = add i32 %iv, 1 63 64 %iv.sext = sext i32 %iv to i64 65 call void @use(i64 %iv.sext) 66 67 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 68 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 69 70 %becond = icmp ne i32 %iv, %n 71 br i1 %becond, label %loop, label %leave 72 73 leave: 74 ret void 75 } 76 77 define void @test_3(i1* %cond_buf, i32* %len_buf) { 78 ; CHECK-LABEL: @test_3( 79 80 entry: 81 %len = load i32, i32* %len_buf 82 %entry.cond = icmp sgt i32 %len, 0 83 call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] 84 br label %loop 85 86 loop: 87 ; CHECK: loop: 88 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] 89 ; CHECK: %iv.inc.cmp = icmp slt i32 %iv.inc, %len 90 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 91 ; CHECK: leave: 92 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 93 %iv.inc = add i32 %iv, 1 94 95 %iv.cmp = icmp slt i32 %iv, %len 96 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 97 98 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 99 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 100 101 %becond = load volatile i1, i1* %cond_buf 102 br i1 %becond, label %loop, label %leave 103 104 leave: 105 ret void 106 } 107 108 define void @test_4(i1* %cond_buf, i32* %len_buf) { 109 ; CHECK-LABEL: @test_4( 110 111 entry: 112 %len = load i32, i32* %len_buf 113 %entry.cond = icmp sgt i32 %len, 0 114 call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] 115 br label %loop 116 117 loop: 118 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ] 119 %iv.inc = add i32 %iv, 1 120 121 %cond = load volatile i1, i1* %cond_buf 122 br i1 %cond, label %left, label %be 123 124 left: 125 ; Does not dominate the backedge, so cannot be used in the inductive proof 126 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 127 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 128 br label %be 129 130 be: 131 ; CHECK: be: 132 ; CHECK-NEXT: %iv.cmp = icmp slt i32 %iv, %len 133 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 134 ; CHECK: leave: 135 136 %iv.cmp = icmp slt i32 %iv, %len 137 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 138 139 %becond = load volatile i1, i1* %cond_buf 140 br i1 %becond, label %loop, label %leave 141 142 leave: 143 ret void 144 } 145