1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=loop-unroll -unroll-runtime %s -o - | FileCheck %s 3; RUN: opt -S -passes=loop-unroll -unroll-runtime -unroll-max-upperbound=6 %s -o - | FileCheck %s --check-prefix=UPPER 4 5target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 6 7@global = dso_local local_unnamed_addr global i32 0, align 4 8@global.1 = dso_local local_unnamed_addr global ptr null, align 4 9 10; Check that loop in hoge_3, with a runtime upperbound of 3, is not unrolled. 11define dso_local void @hoge_3(i8 %arg) { 12; CHECK-LABEL: @hoge_3( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[X:%.*]] = load i32, ptr @global, align 4 15; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr @global.1, align 4 16; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17 17; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 18; CHECK: loop.preheader: 19; CHECK-NEXT: br label [[LOOP:%.*]] 20; CHECK: loop: 21; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ] 22; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ] 23; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 8 24; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, ptr [[PTR]], i32 1 25; CHECK-NEXT: store i8 [[ARG:%.*]], ptr [[PTR_NEXT]], align 1 26; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17 27; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 28; CHECK: exit.loopexit: 29; CHECK-NEXT: br label [[EXIT]] 30; CHECK: exit: 31; CHECK-NEXT: ret void 32; 33; UPPER-LABEL: @hoge_3( 34; UPPER-NEXT: entry: 35; UPPER-NEXT: [[X:%.*]] = load i32, ptr @global, align 4 36; UPPER-NEXT: [[Y:%.*]] = load ptr, ptr @global.1, align 4 37; UPPER-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17 38; UPPER-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 39; UPPER: loop.preheader: 40; UPPER-NEXT: br label [[LOOP:%.*]] 41; UPPER: loop: 42; UPPER-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ] 43; UPPER-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ] 44; UPPER-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 8 45; UPPER-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, ptr [[PTR]], i32 1 46; UPPER-NEXT: store i8 [[ARG:%.*]], ptr [[PTR_NEXT]], align 1 47; UPPER-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17 48; UPPER-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 49; UPPER: exit.loopexit: 50; UPPER-NEXT: br label [[EXIT]] 51; UPPER: exit: 52; UPPER-NEXT: ret void 53; 54entry: 55 %x = load i32, ptr @global, align 4 56 %y = load ptr, ptr @global.1, align 4 57 %0 = icmp ult i32 %x, 17 58 br i1 %0, label %loop, label %exit 59 60loop: 61 %iv = phi i32 [ %x, %entry ], [ %iv.next, %loop ] 62 %ptr = phi ptr [ %y, %entry ], [ %ptr.next, %loop ] 63 %iv.next = add nuw i32 %iv, 8 64 %ptr.next = getelementptr inbounds i8, ptr %ptr, i32 1 65 store i8 %arg, ptr %ptr.next, align 1 66 %1 = icmp ult i32 %iv.next, 17 67 br i1 %1, label %loop, label %exit 68 69exit: 70 ret void 71} 72 73; Check that loop in hoge_5, with a runtime upperbound of 5, is unrolled when -unroll-max-upperbound=4 74define dso_local void @hoge_5(i8 %arg) { 75; CHECK-LABEL: @hoge_5( 76; CHECK-NEXT: entry: 77; CHECK-NEXT: [[X:%.*]] = load i32, ptr @global, align 4 78; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr @global.1, align 4 79; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17 80; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 81; CHECK: loop.preheader: 82; CHECK-NEXT: br label [[LOOP:%.*]] 83; CHECK: loop: 84; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ] 85; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[Y]], [[LOOP_PREHEADER]] ] 86; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 4 87; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i8, ptr [[PTR]], i32 1 88; CHECK-NEXT: store i8 [[ARG:%.*]], ptr [[PTR_NEXT]], align 1 89; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17 90; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 91; CHECK: exit.loopexit: 92; CHECK-NEXT: br label [[EXIT]] 93; CHECK: exit: 94; CHECK-NEXT: ret void 95; 96; UPPER-LABEL: @hoge_5( 97; UPPER-NEXT: entry: 98; UPPER-NEXT: [[X:%.*]] = load i32, ptr @global, align 4 99; UPPER-NEXT: [[Y:%.*]] = load ptr, ptr @global.1, align 4 100; UPPER-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 17 101; UPPER-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 102; UPPER: loop.preheader: 103; UPPER-NEXT: br label [[LOOP:%.*]] 104; UPPER: loop: 105; UPPER-NEXT: [[IV_NEXT:%.*]] = add nuw i32 [[X]], 4 106; UPPER-NEXT: [[PTR_NEXT:%.*]] = getelementptr inbounds i8, ptr [[Y]], i32 1 107; UPPER-NEXT: store i8 [[ARG:%.*]], ptr [[PTR_NEXT]], align 1 108; UPPER-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], 17 109; UPPER-NEXT: br i1 [[TMP1]], label [[LOOP_1:%.*]], label [[EXIT_LOOPEXIT:%.*]] 110; UPPER: loop.1: 111; UPPER-NEXT: [[IV_NEXT_1:%.*]] = add nuw i32 [[X]], 8 112; UPPER-NEXT: [[PTR_NEXT_1:%.*]] = getelementptr inbounds i8, ptr [[PTR_NEXT]], i32 1 113; UPPER-NEXT: store i8 [[ARG]], ptr [[PTR_NEXT_1]], align 1 114; UPPER-NEXT: [[TMP2:%.*]] = icmp ult i32 [[IV_NEXT_1]], 17 115; UPPER-NEXT: br i1 [[TMP2]], label [[LOOP_2:%.*]], label [[EXIT_LOOPEXIT]] 116; UPPER: loop.2: 117; UPPER-NEXT: [[IV_NEXT_2:%.*]] = add nuw i32 [[X]], 12 118; UPPER-NEXT: [[PTR_NEXT_2:%.*]] = getelementptr inbounds i8, ptr [[PTR_NEXT_1]], i32 1 119; UPPER-NEXT: store i8 [[ARG]], ptr [[PTR_NEXT_2]], align 1 120; UPPER-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IV_NEXT_2]], 17 121; UPPER-NEXT: br i1 [[TMP3]], label [[LOOP_3:%.*]], label [[EXIT_LOOPEXIT]] 122; UPPER: loop.3: 123; UPPER-NEXT: [[IV_NEXT_3:%.*]] = add nuw i32 [[X]], 16 124; UPPER-NEXT: [[PTR_NEXT_3:%.*]] = getelementptr inbounds i8, ptr [[PTR_NEXT_2]], i32 1 125; UPPER-NEXT: store i8 [[ARG]], ptr [[PTR_NEXT_3]], align 1 126; UPPER-NEXT: [[TMP4:%.*]] = icmp ult i32 [[IV_NEXT_3]], 17 127; UPPER-NEXT: br i1 [[TMP4]], label [[LOOP_4:%.*]], label [[EXIT_LOOPEXIT]] 128; UPPER: loop.4: 129; UPPER-NEXT: [[PTR_NEXT_4:%.*]] = getelementptr inbounds i8, ptr [[PTR_NEXT_3]], i32 1 130; UPPER-NEXT: store i8 [[ARG]], ptr [[PTR_NEXT_4]], align 1 131; UPPER-NEXT: br i1 false, label [[LOOP_5:%.*]], label [[EXIT_LOOPEXIT]] 132; UPPER: loop.5: 133; UPPER-NEXT: [[PTR_NEXT_5:%.*]] = getelementptr inbounds i8, ptr [[PTR_NEXT_4]], i32 1 134; UPPER-NEXT: store i8 [[ARG]], ptr [[PTR_NEXT_5]], align 1 135; UPPER-NEXT: br label [[EXIT_LOOPEXIT]] 136; UPPER: exit.loopexit: 137; UPPER-NEXT: br label [[EXIT]] 138; UPPER: exit: 139; UPPER-NEXT: ret void 140; 141entry: 142 %x = load i32, ptr @global, align 4 143 %y = load ptr, ptr @global.1, align 4 144 %0 = icmp ult i32 %x, 17 145 br i1 %0, label %loop, label %exit 146 147loop: 148 %iv = phi i32 [ %x, %entry ], [ %iv.next, %loop ] 149 %ptr = phi ptr [ %y, %entry ], [ %ptr.next, %loop ] 150 %iv.next = add nuw i32 %iv, 4 151 %ptr.next = getelementptr inbounds i8, ptr %ptr, i32 1 152 store i8 %arg, ptr %ptr.next, align 1 153 %1 = icmp ult i32 %iv.next, 17 154 br i1 %1, label %loop, label %exit 155 156exit: 157 ret void 158} 159