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 define void @test_1(i1* %cond_buf, i32* %len_buf) { 14 ; CHECK-LABEL: @test_1( 15 entry: 16 %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648} 17 br label %loop 18 19 loop: 20 ; CHECK: loop: 21 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] 22 ; CHECK: %iv.inc.cmp = icmp slt i32 %iv.inc, %len 23 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 24 ; CHECK: leave: 25 26 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 27 %iv.inc = add i32 %iv, 1 28 29 %iv.cmp = icmp slt i32 %iv, %len 30 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 31 32 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 33 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 34 35 %becond = load volatile i1, i1* %cond_buf 36 br i1 %becond, label %loop, label %leave 37 38 leave: 39 ret void 40 } 41 42 define void @test_2(i32 %n, i32* %len_buf) { 43 ; CHECK-LABEL: @test_2( 44 ; CHECK: [[LEN_SEXT:%[^ ]+]] = sext i32 %len to i64 45 ; CHECK: br label %loop 46 47 entry: 48 %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648} 49 br label %loop 50 51 loop: 52 ; CHECK: loop: 53 ; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ] 54 ; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 55 ; CHECK: %iv.inc.cmp = icmp slt i64 %indvars.iv.next, [[LEN_SEXT]] 56 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 57 ; CHECK: leave: 58 59 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 60 %iv.inc = add i32 %iv, 1 61 62 %iv.sext = sext i32 %iv to i64 63 64 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 65 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 66 67 %becond = icmp ne i32 %iv, %n 68 br i1 %becond, label %loop, label %leave 69 70 leave: 71 ret void 72 } 73 74 define void @test_3(i1* %cond_buf, i32* %len_buf) { 75 ; CHECK-LABEL: @test_3( 76 77 entry: 78 %len = load i32, i32* %len_buf 79 %entry.cond = icmp sgt i32 %len, 0 80 call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] 81 br label %loop 82 83 loop: 84 ; CHECK: loop: 85 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] 86 ; CHECK: %iv.inc.cmp = icmp slt i32 %iv.inc, %len 87 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 88 ; CHECK: leave: 89 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] 90 %iv.inc = add i32 %iv, 1 91 92 %iv.cmp = icmp slt i32 %iv, %len 93 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 94 95 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 96 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 97 98 %becond = load volatile i1, i1* %cond_buf 99 br i1 %becond, label %loop, label %leave 100 101 leave: 102 ret void 103 } 104 105 define void @test_4(i1* %cond_buf, i32* %len_buf) { 106 ; CHECK-LABEL: @test_4( 107 108 entry: 109 %len = load i32, i32* %len_buf 110 %entry.cond = icmp sgt i32 %len, 0 111 call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] 112 br label %loop 113 114 loop: 115 %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ] 116 %iv.inc = add i32 %iv, 1 117 118 %cond = load volatile i1, i1* %cond_buf 119 br i1 %cond, label %left, label %be 120 121 left: 122 ; Does not dominate the backedge, so cannot be used in the inductive proof 123 %iv.inc.cmp = icmp slt i32 %iv.inc, %len 124 call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] 125 br label %be 126 127 be: 128 ; CHECK: be: 129 ; CHECK-NEXT: %iv.cmp = icmp slt i32 %iv, %len 130 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 131 ; CHECK: leave: 132 133 %iv.cmp = icmp slt i32 %iv, %len 134 call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] 135 136 %becond = load volatile i1, i1* %cond_buf 137 br i1 %becond, label %loop, label %leave 138 139 leave: 140 ret void 141 } 142