; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -S -passes=loop-unroll -mattr=+no-default-unroll | FileCheck %s ; Regression test: when a loop has a small MaxTripCount and falls through to ; runtime unrolling, the unroll count should be based on DefaultUnrollRuntimeCount ; (not MaxTripCount). Previously, a quirk would set UP.Count = MaxTripCount (5) ; before the power-of-two reduction, yielding count 2 (5 >> 1). Now the count ; starts at DefaultUnrollRuntimeCount (8) and reduces to 4 (8 >> 1). ; ; This test uses RISC-V because we need a target that sets UP.Force = true ; (via RISCVTTIImpl::getUnrollingPreferences) to trigger the bug. target triple = "riscv64-unknown-linux-gnu" define void @test(i32 %start, ptr %p) { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[END:%.*]] = add i32 [[START:%.*]], 5 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT_3:%.*]], [[LOOP_3:%.*]] ] ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[IV]] ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[GEP]], align 4 ; CHECK-NEXT: store volatile i32 [[V]], ptr [[GEP]], align 4 ; CHECK-NEXT: [[IV_NEXT:%.*]] = add nuw i32 [[IV]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[END]] ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_1:%.*]], label [[EXIT:%.*]] ; CHECK: loop.1: ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[IV_NEXT]] ; CHECK-NEXT: [[V_1:%.*]] = load volatile i32, ptr [[GEP_1]], align 4 ; CHECK-NEXT: store volatile i32 [[V_1]], ptr [[GEP_1]], align 4 ; CHECK-NEXT: [[IV_NEXT_1:%.*]] = add nuw i32 [[IV]], 2 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV_NEXT_1]], [[END]] ; CHECK-NEXT: br i1 [[CMP_1]], label [[LOOP_2:%.*]], label [[EXIT]] ; CHECK: loop.2: ; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[IV_NEXT_1]] ; CHECK-NEXT: [[V_2:%.*]] = load volatile i32, ptr [[GEP_2]], align 4 ; CHECK-NEXT: store volatile i32 [[V_2]], ptr [[GEP_2]], align 4 ; CHECK-NEXT: [[IV_NEXT_2:%.*]] = add nuw i32 [[IV]], 3 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i32 [[IV_NEXT_2]], [[END]] ; CHECK-NEXT: br i1 [[CMP_2]], label [[LOOP_3]], label [[EXIT]] ; CHECK: loop.3: ; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[IV_NEXT_2]] ; CHECK-NEXT: [[V_3:%.*]] = load volatile i32, ptr [[GEP_3]], align 4 ; CHECK-NEXT: store volatile i32 [[V_3]], ptr [[GEP_3]], align 4 ; CHECK-NEXT: [[IV_NEXT_3]] = add nuw i32 [[IV]], 4 ; CHECK-NEXT: [[CMP_3:%.*]] = icmp ult i32 [[IV_NEXT_3]], [[END]] ; CHECK-NEXT: br i1 [[CMP_3]], label [[LOOP]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void ; entry: %end = add i32 %start, 5 br label %loop loop: %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i32, ptr %p, i32 %iv %v = load volatile i32, ptr %gep %b0 = call i32 @llvm.bswap.i32(i32 %v) %b1 = call i32 @llvm.bswap.i32(i32 %b0) %b2 = call i32 @llvm.bswap.i32(i32 %b1) %b3 = call i32 @llvm.bswap.i32(i32 %b2) %b4 = call i32 @llvm.bswap.i32(i32 %b3) %b5 = call i32 @llvm.bswap.i32(i32 %b4) %b6 = call i32 @llvm.bswap.i32(i32 %b5) %b7 = call i32 @llvm.bswap.i32(i32 %b6) %b8 = call i32 @llvm.bswap.i32(i32 %b7) %b9 = call i32 @llvm.bswap.i32(i32 %b8) %b10 = call i32 @llvm.bswap.i32(i32 %b9) %b11 = call i32 @llvm.bswap.i32(i32 %b10) %b12 = call i32 @llvm.bswap.i32(i32 %b11) %b13 = call i32 @llvm.bswap.i32(i32 %b12) %b14 = call i32 @llvm.bswap.i32(i32 %b13) %b15 = call i32 @llvm.bswap.i32(i32 %b14) %b16 = call i32 @llvm.bswap.i32(i32 %b15) %b17 = call i32 @llvm.bswap.i32(i32 %b16) %b18 = call i32 @llvm.bswap.i32(i32 %b17) %b19 = call i32 @llvm.bswap.i32(i32 %b18) %b20 = call i32 @llvm.bswap.i32(i32 %b19) %b21 = call i32 @llvm.bswap.i32(i32 %b20) %b22 = call i32 @llvm.bswap.i32(i32 %b21) %b23 = call i32 @llvm.bswap.i32(i32 %b22) %b24 = call i32 @llvm.bswap.i32(i32 %b23) %b25 = call i32 @llvm.bswap.i32(i32 %b24) store volatile i32 %b25, ptr %gep %iv.next = add nuw i32 %iv, 1 %cmp = icmp ult i32 %iv.next, %end br i1 %cmp, label %loop, label %exit exit: ret void }