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 9target datalayout = "n8:16:32:64" 10 11declare void @llvm.experimental.guard(i1, ...) 12 13define void @test_1(i1* %cond_buf, i32* %len_buf) { 14; CHECK-LABEL: @test_1( 15entry: 16 %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648} 17 br label %loop 18 19loop: 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 38leave: 39 ret void 40} 41 42define 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 47entry: 48 %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648} 49 br label %loop 50 51loop: 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 70leave: 71 ret void 72} 73 74define void @test_3(i1* %cond_buf, i32* %len_buf) { 75; CHECK-LABEL: @test_3( 76 77entry: 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 83loop: 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 101leave: 102 ret void 103} 104 105define void @test_4(i1* %cond_buf, i32* %len_buf) { 106; CHECK-LABEL: @test_4( 107 108entry: 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 114loop: 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 121left: 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 127be: 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 139leave: 140 ret void 141} 142