1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/test/Transforms/LoopUnroll/runtime-small-upperbound.ll
Nikita Popov 9b44b72937 [LoopUnroll] Clamp unroll count to MaxTripCount
Unrolling with more iterations than MaxTripCount is pointless, as
those iterations can never be executed. As such, we clamp ULO.Count
to MaxTripCount if it is known. This means we no longer need to
consider iterations after MaxTripCount for exit folding, and the
CompletelyUnroll flag becomes independent of ULO.TripCount.

Differential Revision: https://reviews.llvm.org/D103748
2021-06-07 21:08:42 +02:00

161 lines
7.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-unroll -unroll-runtime %s -o - | FileCheck %s
; RUN: opt -S -loop-unroll -unroll-runtime -unroll-max-upperbound=6 %s -o - | FileCheck %s --check-prefix=UPPER
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
@global = dso_local local_unnamed_addr global i32 0, align 4
@global.1 = dso_local local_unnamed_addr global i8* null, align 4
; Check that loop in hoge_3, with a runtime upperbound of 3, is not unrolled.
define dso_local void @hoge_3(i8 %arg) {
; CHECK-LABEL: @hoge_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X:%.*]] = load i32, i32* @global, align 4
; CHECK-NEXT: [[Y:%.*]] = load i8*, i8** @global.1, align 4
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[PTR:%.*]] = phi i8* [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 8
; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, i8* [[PTR]], i32 1
; CHECK-NEXT: store i8 [[ARG:%.*]], i8* [[PTR_NEXT]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17
; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
; UPPER-LABEL: @hoge_3(
; UPPER-NEXT: entry:
; UPPER-NEXT: [[X:%.*]] = load i32, i32* @global, align 4
; UPPER-NEXT: [[Y:%.*]] = load i8*, i8** @global.1, align 4
; UPPER-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17
; UPPER-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; UPPER: loop.preheader:
; UPPER-NEXT: br label [[LOOP:%.*]]
; UPPER: loop:
; UPPER-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ]
; UPPER-NEXT: [[PTR:%.*]] = phi i8* [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ]
; UPPER-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 8
; UPPER-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, i8* [[PTR]], i32 1
; UPPER-NEXT: store i8 [[ARG:%.*]], i8* [[PTR_NEXT]], align 1
; UPPER-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17
; UPPER-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; UPPER: exit.loopexit:
; UPPER-NEXT: br label [[EXIT]]
; UPPER: exit:
; UPPER-NEXT: ret void
;
entry:
%x = load i32, i32* @global, align 4
%y = load i8*, i8** @global.1, align 4
%0 = icmp ult i32 %x, 17
br i1 %0, label %loop, label %exit
loop:
%iv = phi i32 [ %x, %entry ], [ %iv.next, %loop ]
%ptr = phi i8* [ %y, %entry ], [ %ptr.next, %loop ]
%iv.next = add nuw i32 %iv, 8
%ptr.next = getelementptr inbounds i8, i8* %ptr, i32 1
store i8 %arg, i8* %ptr.next, align 1
%1 = icmp ult i32 %iv.next, 17
br i1 %1, label %loop, label %exit
exit:
ret void
}
; Check that loop in hoge_5, with a runtime upperbound of 5, is unrolled when -unroll-max-upperbound=4
define dso_local void @hoge_5(i8 %arg) {
; CHECK-LABEL: @hoge_5(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X:%.*]] = load i32, i32* @global, align 4
; CHECK-NEXT: [[Y:%.*]] = load i8*, i8** @global.1, align 4
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[PTR:%.*]] = phi i8* [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 4
; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, i8* [[PTR]], i32 1
; CHECK-NEXT: store i8 [[ARG:%.*]], i8* [[PTR_NEXT]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17
; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
; UPPER-LABEL: @hoge_5(
; UPPER-NEXT: entry:
; UPPER-NEXT: [[X:%.*]] = load i32, i32* @global, align 4
; UPPER-NEXT: [[Y:%.*]] = load i8*, i8** @global.1, align 4
; UPPER-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17
; UPPER-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; UPPER: loop.preheader:
; UPPER-NEXT: br label [[LOOP:%.*]]
; UPPER: loop:
; UPPER-NEXT: [[IV_NEXT:%.*]] = add nuw i32 [[X]], 4
; UPPER-NEXT: [[PTR_NEXT:%.*]] = getelementptr inbounds i8, i8* [[Y]], i32 1
; UPPER-NEXT: store i8 [[ARG:%.*]], i8* [[PTR_NEXT]], align 1
; UPPER-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17
; UPPER-NEXT: br i1 [[TMP1]], label [[LOOP_1:%.*]], label [[EXIT_LOOPEXIT:%.*]]
; UPPER: exit.loopexit:
; UPPER-NEXT: br label [[EXIT]]
; UPPER: exit:
; UPPER-NEXT: ret void
; UPPER: loop.1:
; UPPER-NEXT: [[IV_NEXT_1:%.*]] = add nuw i32 [[IV_NEXT]], 4
; UPPER-NEXT: [[PTR_NEXT_1:%.*]] = getelementptr inbounds i8, i8* [[PTR_NEXT]], i32 1
; UPPER-NEXT: store i8 [[ARG]], i8* [[PTR_NEXT_1]], align 1
; UPPER-NEXT: [[TMP2:%.*]] = icmp ult i32 [[IV_NEXT_1]], 17
; UPPER-NEXT: br i1 [[TMP2]], label [[LOOP_2:%.*]], label [[EXIT_LOOPEXIT]]
; UPPER: loop.2:
; UPPER-NEXT: [[IV_NEXT_2:%.*]] = add nuw i32 [[IV_NEXT_1]], 4
; UPPER-NEXT: [[PTR_NEXT_2:%.*]] = getelementptr inbounds i8, i8* [[PTR_NEXT_1]], i32 1
; UPPER-NEXT: store i8 [[ARG]], i8* [[PTR_NEXT_2]], align 1
; UPPER-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IV_NEXT_2]], 17
; UPPER-NEXT: br i1 [[TMP3]], label [[LOOP_3:%.*]], label [[EXIT_LOOPEXIT]]
; UPPER: loop.3:
; UPPER-NEXT: [[IV_NEXT_3:%.*]] = add nuw i32 [[IV_NEXT_2]], 4
; UPPER-NEXT: [[PTR_NEXT_3:%.*]] = getelementptr inbounds i8, i8* [[PTR_NEXT_2]], i32 1
; UPPER-NEXT: store i8 [[ARG]], i8* [[PTR_NEXT_3]], align 1
; UPPER-NEXT: [[TMP4:%.*]] = icmp ult i32 [[IV_NEXT_3]], 17
; UPPER-NEXT: br i1 [[TMP4]], label [[LOOP_4:%.*]], label [[EXIT_LOOPEXIT]]
; UPPER: loop.4:
; UPPER-NEXT: [[IV_NEXT_4:%.*]] = add nuw i32 [[IV_NEXT_3]], 4
; UPPER-NEXT: [[PTR_NEXT_4:%.*]] = getelementptr inbounds i8, i8* [[PTR_NEXT_3]], i32 1
; UPPER-NEXT: store i8 [[ARG]], i8* [[PTR_NEXT_4]], align 1
; UPPER-NEXT: [[TMP5:%.*]] = icmp ult i32 [[IV_NEXT_4]], 17
; UPPER-NEXT: br i1 [[TMP5]], label [[LOOP_5:%.*]], label [[EXIT_LOOPEXIT]]
; UPPER: loop.5:
; UPPER-NEXT: [[PTR_NEXT_5:%.*]] = getelementptr inbounds i8, i8* [[PTR_NEXT_4]], i32 1
; UPPER-NEXT: store i8 [[ARG]], i8* [[PTR_NEXT_5]], align 1
; UPPER-NEXT: br label [[EXIT_LOOPEXIT]]
;
entry:
%x = load i32, i32* @global, align 4
%y = load i8*, i8** @global.1, align 4
%0 = icmp ult i32 %x, 17
br i1 %0, label %loop, label %exit
loop:
%iv = phi i32 [ %x, %entry ], [ %iv.next, %loop ]
%ptr = phi i8* [ %y, %entry ], [ %ptr.next, %loop ]
%iv.next = add nuw i32 %iv, 4
%ptr.next = getelementptr inbounds i8, i8* %ptr, i32 1
store i8 %arg, i8* %ptr.next, align 1
%1 = icmp ult i32 %iv.next, 17
br i1 %1, label %loop, label %exit
exit:
ret void
}