1*0ec421d0SRoman Lebedev; RUN: opt -verify-loop-info -passes=irce -S < %s | FileCheck %s 267904db2SAlina Sbirlea; RUN: opt -verify-loop-info -passes='require<branch-prob>,irce' -S < %s | FileCheck %s 3cee313d2SEric Christopher 4631432a3SMatt Arsenaultdefine void @decrementing_loop(ptr %arr, ptr %a_len_ptr, i32 %n) { 5cee313d2SEric Christopher entry: 6631432a3SMatt Arsenault %len = load i32, ptr %a_len_ptr, !range !0 7cee313d2SEric Christopher %first.itr.check = icmp sgt i32 %n, 0 8cee313d2SEric Christopher %start = sub i32 %n, 1 9cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 10cee313d2SEric Christopher 11cee313d2SEric Christopher loop: 12cee313d2SEric Christopher %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ] 13cee313d2SEric Christopher %idx.dec = sub i32 %idx, 1 14cee313d2SEric Christopher %abc.high = icmp slt i32 %idx, %len 15cee313d2SEric Christopher %abc.low = icmp sge i32 %idx, 0 16cee313d2SEric Christopher %abc = and i1 %abc.low, %abc.high 17cee313d2SEric Christopher br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 18cee313d2SEric Christopher 19cee313d2SEric Christopher in.bounds: 20631432a3SMatt Arsenault %addr = getelementptr i32, ptr %arr, i32 %idx 21631432a3SMatt Arsenault store i32 0, ptr %addr 22cee313d2SEric Christopher %next = icmp sgt i32 %idx.dec, -1 23cee313d2SEric Christopher br i1 %next, label %loop, label %exit 24cee313d2SEric Christopher 25cee313d2SEric Christopher out.of.bounds: 26cee313d2SEric Christopher ret void 27cee313d2SEric Christopher 28cee313d2SEric Christopher exit: 29cee313d2SEric Christopher ret void 30cee313d2SEric Christopher 31cee313d2SEric Christopher; CHECK: loop.preheader: 32b46c085dSRoman Lebedev; CHECK: [[len_hiclamp:[^ ]+]] = call i32 @llvm.smin.i32(i32 %len, i32 %n) 33b46c085dSRoman Lebedev; CHECK: [[not_exit_preloop_at:[^ ]+]] = call i32 @llvm.smax.i32(i32 [[len_hiclamp]], i32 0) 340cf9639aSSam Parker; CHECK: %exit.preloop.at = add nsw i32 [[not_exit_preloop_at]], -1 35cee313d2SEric Christopher} 36cee313d2SEric Christopher 37cee313d2SEric Christopher; Make sure that we can eliminate the range check when the loop looks like: 38cee313d2SEric Christopher; for (i = len.a - 1; i >= 0; --i) 39cee313d2SEric Christopher; b[i] = a[i]; 40631432a3SMatt Arsenaultdefine void @test_01(ptr %a, ptr %b, ptr %a_len_ptr, ptr %b_len_ptr) { 41cee313d2SEric Christopher 42cee313d2SEric Christopher; CHECK-LABEL: test_01 43cee313d2SEric Christopher; CHECK: mainloop: 44cee313d2SEric Christopher; CHECK-NEXT: br label %loop 45cee313d2SEric Christopher; CHECK: loop: 46cee313d2SEric Christopher; CHECK: %rc = and i1 true, true 47cee313d2SEric Christopher; CHECK: loop.preloop: 48cee313d2SEric Christopher 49cee313d2SEric Christopher entry: 50631432a3SMatt Arsenault %len.a = load i32, ptr %a_len_ptr, !range !0 51631432a3SMatt Arsenault %len.b = load i32, ptr %b_len_ptr, !range !0 52cee313d2SEric Christopher %first.itr.check = icmp ne i32 %len.a, 0 53cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 54cee313d2SEric Christopher 55cee313d2SEric Christopher loop: 56cee313d2SEric Christopher %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ] 57cee313d2SEric Christopher %idx.next = sub i32 %idx, 1 58cee313d2SEric Christopher %rca = icmp ult i32 %idx.next, %len.a 59cee313d2SEric Christopher %rcb = icmp ult i32 %idx.next, %len.b 60cee313d2SEric Christopher %rc = and i1 %rca, %rcb 61cee313d2SEric Christopher br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 62cee313d2SEric Christopher 63cee313d2SEric Christopher in.bounds: 64631432a3SMatt Arsenault %el.a = getelementptr i32, ptr %a, i32 %idx.next 65631432a3SMatt Arsenault %el.b = getelementptr i32, ptr %b, i32 %idx.next 66631432a3SMatt Arsenault %v = load i32, ptr %el.a 67631432a3SMatt Arsenault store i32 %v, ptr %el.b 68cee313d2SEric Christopher %loop.cond = icmp slt i32 %idx, 2 69cee313d2SEric Christopher br i1 %loop.cond, label %exit, label %loop 70cee313d2SEric Christopher 71cee313d2SEric Christopher out.of.bounds: 72cee313d2SEric Christopher ret void 73cee313d2SEric Christopher 74cee313d2SEric Christopher exit: 75cee313d2SEric Christopher ret void 76cee313d2SEric Christopher} 77cee313d2SEric Christopher 78cee313d2SEric Christopher; Same as test_01, but the latch condition is unsigned 79631432a3SMatt Arsenaultdefine void @test_02(ptr %a, ptr %b, ptr %a_len_ptr, ptr %b_len_ptr) { 80cee313d2SEric Christopher 81cee313d2SEric Christopher; CHECK-LABEL: test_02 82cee313d2SEric Christopher; CHECK: mainloop: 83cee313d2SEric Christopher; CHECK-NEXT: br label %loop 84cee313d2SEric Christopher; CHECK: loop: 85cee313d2SEric Christopher; CHECK: %rc = and i1 true, true 86cee313d2SEric Christopher; CHECK: loop.preloop: 87cee313d2SEric Christopher 88cee313d2SEric Christopher entry: 89631432a3SMatt Arsenault %len.a = load i32, ptr %a_len_ptr, !range !0 90631432a3SMatt Arsenault %len.b = load i32, ptr %b_len_ptr, !range !0 91cee313d2SEric Christopher %first.itr.check = icmp ne i32 %len.a, 0 92cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 93cee313d2SEric Christopher 94cee313d2SEric Christopher loop: 95cee313d2SEric Christopher %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ] 96cee313d2SEric Christopher %idx.next = sub i32 %idx, 1 97cee313d2SEric Christopher %rca = icmp ult i32 %idx.next, %len.a 98cee313d2SEric Christopher %rcb = icmp ult i32 %idx.next, %len.b 99cee313d2SEric Christopher %rc = and i1 %rca, %rcb 100cee313d2SEric Christopher br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 101cee313d2SEric Christopher 102cee313d2SEric Christopher in.bounds: 103631432a3SMatt Arsenault %el.a = getelementptr i32, ptr %a, i32 %idx.next 104631432a3SMatt Arsenault %el.b = getelementptr i32, ptr %b, i32 %idx.next 105631432a3SMatt Arsenault %v = load i32, ptr %el.a 106631432a3SMatt Arsenault store i32 %v, ptr %el.b 107cee313d2SEric Christopher %loop.cond = icmp ult i32 %idx, 2 108cee313d2SEric Christopher br i1 %loop.cond, label %exit, label %loop 109cee313d2SEric Christopher 110cee313d2SEric Christopher out.of.bounds: 111cee313d2SEric Christopher ret void 112cee313d2SEric Christopher 113cee313d2SEric Christopher exit: 114cee313d2SEric Christopher ret void 115cee313d2SEric Christopher} 116cee313d2SEric Christopher 117cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through 118cee313d2SEric Christopher; Phi node. 119631432a3SMatt Arsenaultdefine void @test_03(ptr %a, ptr %a_len_ptr, i1 %cond) { 120cee313d2SEric Christopher 121cee313d2SEric Christopher; CHECK-LABEL: test_03 122cee313d2SEric Christopher; CHECK: mainloop: 123cee313d2SEric Christopher; CHECK-NEXT: br label %loop 124cee313d2SEric Christopher; CHECK: loop: 125cee313d2SEric Christopher; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 126cee313d2SEric Christopher; CHECK: loop.preloop: 127cee313d2SEric Christopher 128cee313d2SEric Christopher entry: 129631432a3SMatt Arsenault %len.a = load i32, ptr %a_len_ptr, !range !0 130cee313d2SEric Christopher %len.minus.one = sub nsw i32 %len.a, 1 131cee313d2SEric Christopher %len.minus.two = sub nsw i32 %len.a, 2 132cee313d2SEric Christopher br i1 %cond, label %if.true, label %if.false 133cee313d2SEric Christopher 134cee313d2SEric Christopherif.true: 135cee313d2SEric Christopher br label %merge 136cee313d2SEric Christopher 137cee313d2SEric Christopherif.false: 138cee313d2SEric Christopher br label %merge 139cee313d2SEric Christopher 140cee313d2SEric Christophermerge: 141cee313d2SEric Christopher %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ] 142cee313d2SEric Christopher %first.itr.check = icmp sgt i32 %len.a, 3 143cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 144cee313d2SEric Christopher 145cee313d2SEric Christopherloop: 146cee313d2SEric Christopher %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ] 147cee313d2SEric Christopher %idx.next = sub i32 %idx, 1 148cee313d2SEric Christopher %rc = icmp ult i32 %idx.next, %len.a 149cee313d2SEric Christopher br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 150cee313d2SEric Christopher 151cee313d2SEric Christopherin.bounds: 152631432a3SMatt Arsenault %el.a = getelementptr i32, ptr %a, i32 %idx.next 153631432a3SMatt Arsenault %v = load i32, ptr %el.a 154cee313d2SEric Christopher %loop.cond = icmp slt i32 %idx, 2 155cee313d2SEric Christopher br i1 %loop.cond, label %exit, label %loop 156cee313d2SEric Christopher 157cee313d2SEric Christopherout.of.bounds: 158cee313d2SEric Christopher ret void 159cee313d2SEric Christopher 160cee313d2SEric Christopherexit: 161cee313d2SEric Christopher ret void 162cee313d2SEric Christopher} 163cee313d2SEric Christopher 164cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through 165cee313d2SEric Christopher; two Phi nodes. 166631432a3SMatt Arsenaultdefine void @test_04(ptr %a, ptr %a_len_ptr, i1 %cond) { 167cee313d2SEric Christopher 168cee313d2SEric Christopher; CHECK-LABEL: test_04 169cee313d2SEric Christopher; CHECK: mainloop: 170cee313d2SEric Christopher; CHECK-NEXT: br label %loop 171cee313d2SEric Christopher; CHECK: loop: 172cee313d2SEric Christopher; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 173cee313d2SEric Christopher; CHECK: loop.preloop: 174cee313d2SEric Christopher 175cee313d2SEric Christopher entry: 176631432a3SMatt Arsenault %len.a = load i32, ptr %a_len_ptr, !range !0 177cee313d2SEric Christopher %len.minus.one = sub nsw i32 %len.a, 1 178cee313d2SEric Christopher %len.plus.one = add nsw i32 %len.a, 1 179cee313d2SEric Christopher %len.minus.two = sub nsw i32 %len.a, 2 180cee313d2SEric Christopher br i1 %cond, label %if.true, label %if.false 181cee313d2SEric Christopher 182cee313d2SEric Christopherif.true: 183cee313d2SEric Christopher br label %merge 184cee313d2SEric Christopher 185cee313d2SEric Christopherif.false: 186cee313d2SEric Christopher br label %merge 187cee313d2SEric Christopher 188cee313d2SEric Christophermerge: 189cee313d2SEric Christopher %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ] 190cee313d2SEric Christopher %len.phi = phi i32 [ %len.a, %if.true ], [ %len.plus.one, %if.false ] 191cee313d2SEric Christopher %first.itr.check = icmp sgt i32 %len.a, 3 192cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 193cee313d2SEric Christopher 194cee313d2SEric Christopherloop: 195cee313d2SEric Christopher %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ] 196cee313d2SEric Christopher %idx.next = sub i32 %idx, 1 197cee313d2SEric Christopher %rc = icmp ult i32 %idx.next, %len.phi 198cee313d2SEric Christopher br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 199cee313d2SEric Christopher 200cee313d2SEric Christopherin.bounds: 201631432a3SMatt Arsenault %el.a = getelementptr i32, ptr %a, i32 %idx.next 202631432a3SMatt Arsenault %v = load i32, ptr %el.a 203cee313d2SEric Christopher %loop.cond = icmp slt i32 %idx, 2 204cee313d2SEric Christopher br i1 %loop.cond, label %exit, label %loop 205cee313d2SEric Christopher 206cee313d2SEric Christopherout.of.bounds: 207cee313d2SEric Christopher ret void 208cee313d2SEric Christopher 209cee313d2SEric Christopherexit: 210cee313d2SEric Christopher ret void 211cee313d2SEric Christopher} 212cee313d2SEric Christopher 213cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through 214cee313d2SEric Christopher; two Phi nodes, one being AddRec. 215631432a3SMatt Arsenaultdefine void @test_05(ptr %a, ptr %a_len_ptr, i1 %cond) { 216cee313d2SEric Christopher 217cee313d2SEric Christopher; CHECK-LABEL: test_05 218e4d1d0ccSNikita Popov; CHECK: mainloop: 219e4d1d0ccSNikita Popov; CHECK-NEXT: br label %loop 220e4d1d0ccSNikita Popov; CHECK: loop: 221e4d1d0ccSNikita Popov; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 222e4d1d0ccSNikita Popov; CHECK: loop.preloop: 223cee313d2SEric Christopher 224cee313d2SEric Christopher entry: 225631432a3SMatt Arsenault %len.a = load i32, ptr %a_len_ptr, !range !0 226cee313d2SEric Christopher %len.minus.one = sub nsw i32 %len.a, 1 227cee313d2SEric Christopher %len.plus.one = add nsw i32 %len.a, 1 228cee313d2SEric Christopher %len.minus.two = sub nsw i32 %len.a, 2 229cee313d2SEric Christopher br label %merge 230cee313d2SEric Christopher 231cee313d2SEric Christophermerge: 232cee313d2SEric Christopher %starting.value = phi i32 [ %len.minus.two, %entry ], [ %len.minus.one, %merge ] 233cee313d2SEric Christopher %len.phi = phi i32 [ %len.a, %entry ], [ %len.phi.next, %merge ] 234cee313d2SEric Christopher %len.phi.next = add nsw i32 %len.phi, 1 235cee313d2SEric Christopher br i1 true, label %first.iter.check, label %merge 236cee313d2SEric Christopher 237cee313d2SEric Christopherfirst.iter.check: 238cee313d2SEric Christopher %first.itr.check = icmp sgt i32 %len.a, 3 239cee313d2SEric Christopher br i1 %first.itr.check, label %loop, label %exit 240cee313d2SEric Christopher 241cee313d2SEric Christopherloop: 242cee313d2SEric Christopher %idx = phi i32 [ %starting.value, %first.iter.check ] , [ %idx.next, %in.bounds ] 243cee313d2SEric Christopher %idx.next = sub i32 %idx, 1 244cee313d2SEric Christopher %rc = icmp ult i32 %idx.next, %len.phi 245cee313d2SEric Christopher br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 246cee313d2SEric Christopher 247cee313d2SEric Christopherin.bounds: 248631432a3SMatt Arsenault %el.a = getelementptr i32, ptr %a, i32 %idx.next 249631432a3SMatt Arsenault %v = load i32, ptr %el.a 250cee313d2SEric Christopher %loop.cond = icmp slt i32 %idx, 2 251cee313d2SEric Christopher br i1 %loop.cond, label %exit, label %loop 252cee313d2SEric Christopher 253cee313d2SEric Christopherout.of.bounds: 254cee313d2SEric Christopher ret void 255cee313d2SEric Christopher 256cee313d2SEric Christopherexit: 257cee313d2SEric Christopher ret void 258cee313d2SEric Christopher} 259cee313d2SEric Christopher 260cee313d2SEric Christopher!0 = !{i32 0, i32 2147483647} 261cee313d2SEric Christopher!1 = !{!"branch_weights", i32 64, i32 4} 262