1; RUN: opt < %s -S -debug-only=loop-unroll -loop-unroll -unroll-allow-peeling 2>&1 | FileCheck %s 2; REQUIRES: asserts 3 4; Make sure we use the profile information correctly to peel-off 3 iterations 5; from the loop, and update the branch weights for the peeled loop properly. 6 7; CHECK: Loop Unroll: F[basic] 8; CHECK: PEELING loop %for.body with iteration count 3! 9; CHECK: Loop Unroll: F[optsize] 10; CHECK-NOT: PEELING 11 12; CHECK-LABEL: @basic 13; CHECK: br i1 %{{.*}}, label %[[NEXT0:.*]], label %for.cond.for.end_crit_edge, !prof !1 14; CHECK: [[NEXT0]]: 15; CHECK: br i1 %{{.*}}, label %[[NEXT1:.*]], label %for.cond.for.end_crit_edge, !prof !2 16; CHECK: [[NEXT1]]: 17; CHECK: br i1 %{{.*}}, label %[[NEXT2:.*]], label %for.cond.for.end_crit_edge, !prof !3 18; CHECK: [[NEXT2]]: 19; CHECK: br i1 %{{.*}}, label %for.body, label %{{.*}}, !prof !4 20 21define void @basic(i32* %p, i32 %k) #0 !prof !0 { 22entry: 23 %cmp3 = icmp slt i32 0, %k 24 br i1 %cmp3, label %for.body.lr.ph, label %for.end 25 26for.body.lr.ph: ; preds = %entry 27 br label %for.body 28 29for.body: ; preds = %for.body.lr.ph, %for.body 30 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] 31 %p.addr.04 = phi i32* [ %p, %for.body.lr.ph ], [ %incdec.ptr, %for.body ] 32 %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.04, i32 1 33 store i32 %i.05, i32* %p.addr.04, align 4 34 %inc = add nsw i32 %i.05, 1 35 %cmp = icmp slt i32 %inc, %k 36 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge, !prof !1 37 38for.cond.for.end_crit_edge: ; preds = %for.body 39 br label %for.end 40 41for.end: ; preds = %for.cond.for.end_crit_edge, %entry 42 ret void 43} 44 45; We don't want to peel loops when optimizing for size. 46; CHECK-LABEL: @optsize 47; CHECK: for.body.lr.ph: 48; CHECK-NEXT: br label %for.body 49; CHECK: for.body: 50; CHECK-NOT: br 51; CHECK: br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge 52define void @optsize(i32* %p, i32 %k) #1 !prof !0 { 53entry: 54 %cmp3 = icmp slt i32 0, %k 55 br i1 %cmp3, label %for.body.lr.ph, label %for.end 56 57for.body.lr.ph: ; preds = %entry 58 br label %for.body 59 60for.body: ; preds = %for.body.lr.ph, %for.body 61 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] 62 %p.addr.04 = phi i32* [ %p, %for.body.lr.ph ], [ %incdec.ptr, %for.body ] 63 %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.04, i32 1 64 store i32 %i.05, i32* %p.addr.04, align 4 65 %inc = add nsw i32 %i.05, 1 66 %cmp = icmp slt i32 %inc, %k 67 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge, !prof !1 68 69for.cond.for.end_crit_edge: ; preds = %for.body 70 br label %for.end 71 72for.end: ; preds = %for.cond.for.end_crit_edge, %entry 73 ret void 74} 75 76attributes #0 = { nounwind } 77attributes #1 = { nounwind optsize } 78 79!0 = !{!"function_entry_count", i64 1} 80!1 = !{!"branch_weights", i32 3001, i32 1001} 81 82;CHECK: !1 = !{!"branch_weights", i32 900, i32 101} 83;CHECK: !2 = !{!"branch_weights", i32 540, i32 360} 84;CHECK: !3 = !{!"branch_weights", i32 162, i32 378} 85;CHECK: !4 = !{!"branch_weights", i32 1399, i32 162} 86 87