1;; RUN: opt -S < %s -indvars | FileCheck %s 2; RUN: opt -lcssa -loop-simplify -S < %s | opt -S -passes='require<targetir>,require<scalar-evolution>,require<domtree>,loop(indvars)' 3 4;; Check if llvm can narrow !range metadata based on loop entry 5;; predicates. 6 7declare void @abort() 8 9define i1 @bounded_below_slt(i32* nocapture readonly %buffer) { 10; CHECK-LABEL: bounded_below_slt 11entry: 12 %length = load i32, i32* %buffer, !range !0 13 %entry.pred = icmp eq i32 %length, 0 14 br i1 %entry.pred, label %abort, label %loop.preheader 15 16loop.preheader: 17 br label %loop 18 19loop: 20; CHECK: loop 21 %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] 22 %oob.pred = icmp slt i32 %idx, %length 23 br i1 %oob.pred, label %loop.next, label %oob 24; CHECK: br i1 true, label %loop.next, label %oob 25 26loop.next: 27; CHECK: loop.next 28 %idx.inc = add i32 %idx, 1 29 %exit.pred = icmp slt i32 %idx.inc, %length 30 br i1 %exit.pred, label %loop, label %abort.loopexit 31 32abort.loopexit: 33 br label %abort 34 35abort: 36 ret i1 false 37 38oob: 39 tail call void @abort() 40 ret i1 false 41} 42 43define i1 @bounded_below_sle(i32* nocapture readonly %buffer) { 44; CHECK-LABEL: bounded_below_sle 45entry: 46 %length = load i32, i32* %buffer, !range !0 47 %entry.pred = icmp eq i32 %length, 0 48 br i1 %entry.pred, label %abort, label %loop.preheader 49 50loop.preheader: 51 br label %loop 52 53loop: 54; CHECK: loop 55 %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] 56 %oob.pred = icmp sle i32 %idx, %length 57 br i1 %oob.pred, label %loop.next, label %oob 58; CHECK: br i1 true, label %loop.next, label %oob 59 60loop.next: 61; CHECK: loop.next 62 %idx.inc = add i32 %idx, 1 63 %exit.pred = icmp sle i32 %idx.inc, %length 64 br i1 %exit.pred, label %loop, label %abort.loopexit 65 66abort.loopexit: 67 br label %abort 68 69abort: 70 ret i1 false 71 72oob: 73 tail call void @abort() 74 ret i1 false 75} 76 77;; Assert that we're not making an incorrect transform. 78 79declare i32 @check(i8*) 80 81define void @NoChange() { 82; CHECK-LABEL: NoChange 83entry: 84 br label %loop.begin 85 86loop.begin: 87; CHECK: loop.begin: 88 %i.01 = phi i64 [ 2, %entry ], [ %add, %loop.end ] 89 %cmp = icmp ugt i64 %i.01, 1 90; CHECK: %cmp = icmp ugt i64 %i.01, 1 91 br i1 %cmp, label %loop, label %loop.end 92 93loop: 94; CHECK: loop 95 %.sum = add i64 %i.01, -2 96 %v = getelementptr inbounds i8, i8* null, i64 %.sum 97 %r = tail call i32 @check(i8* %v) 98 %c = icmp eq i32 %r, 0 99 br i1 %c, label %loop.end, label %abort.now 100 101abort.now: 102 tail call void @abort() 103 unreachable 104 105loop.end: 106 %add = add i64 %i.01, -1 107 %eq = icmp eq i64 %add, 0 108 br i1 %eq, label %exit, label %loop.begin 109 110exit: 111 ret void 112} 113 114!0 = !{i32 0, i32 100} 115