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 13declare void @use(i64 %x) 14 15define void @test_1(i1* %cond_buf, i32* %len_buf) { 16; CHECK-LABEL: @test_1( 17entry: 18 %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648} 19 br label %loop 20 21loop: 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 40leave: 41 ret void 42} 43 44define 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 49entry: 50 %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648} 51 br label %loop 52 53loop: 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 73leave: 74 ret void 75} 76 77define void @test_3(i1* %cond_buf, i32* %len_buf) { 78; CHECK-LABEL: @test_3( 79 80entry: 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 86loop: 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 104leave: 105 ret void 106} 107 108define void @test_4(i1* %cond_buf, i32* %len_buf) { 109; CHECK-LABEL: @test_4( 110 111entry: 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 117loop: 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 124left: 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 130be: 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 142leave: 143 ret void 144} 145