1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=loop-unroll -S < %s | FileCheck %s 3 4declare void @bar() 5 6define void @test1() { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: call void @bar() 12; CHECK-NEXT: br label [[LATCH:%.*]] 13; CHECK: latch: 14; CHECK-NEXT: call void @bar() 15; CHECK-NEXT: call void @bar() 16; CHECK-NEXT: br label [[LATCH_1:%.*]] 17; CHECK: latch.1: 18; CHECK-NEXT: call void @bar() 19; CHECK-NEXT: call void @bar() 20; CHECK-NEXT: br label [[LATCH_2:%.*]] 21; CHECK: latch.2: 22; CHECK-NEXT: call void @bar() 23; CHECK-NEXT: call void @bar() 24; CHECK-NEXT: br label [[LATCH_3:%.*]] 25; CHECK: latch.3: 26; CHECK-NEXT: call void @bar() 27; CHECK-NEXT: call void @bar() 28; CHECK-NEXT: br label [[LATCH_4:%.*]] 29; CHECK: latch.4: 30; CHECK-NEXT: call void @bar() 31; CHECK-NEXT: call void @bar() 32; CHECK-NEXT: br label [[LATCH_5:%.*]] 33; CHECK: latch.5: 34; CHECK-NEXT: call void @bar() 35; CHECK-NEXT: call void @bar() 36; CHECK-NEXT: br label [[LATCH_6:%.*]] 37; CHECK: latch.6: 38; CHECK-NEXT: call void @bar() 39; CHECK-NEXT: call void @bar() 40; CHECK-NEXT: br label [[LATCH_7:%.*]] 41; CHECK: latch.7: 42; CHECK-NEXT: call void @bar() 43; CHECK-NEXT: call void @bar() 44; CHECK-NEXT: br label [[LATCH_8:%.*]] 45; CHECK: latch.8: 46; CHECK-NEXT: call void @bar() 47; CHECK-NEXT: call void @bar() 48; CHECK-NEXT: br label [[LATCH_9:%.*]] 49; CHECK: latch.9: 50; CHECK-NEXT: call void @bar() 51; CHECK-NEXT: call void @bar() 52; CHECK-NEXT: br i1 false, label [[LATCH_10:%.*]], label [[EXIT:%.*]] 53; CHECK: latch.10: 54; CHECK-NEXT: call void @bar() 55; CHECK-NEXT: br label [[EXIT]] 56; CHECK: exit: 57; CHECK-NEXT: ret void 58; 59entry: 60 br label %loop 61loop: 62 %iv = phi i64 [0, %entry], [%iv.next, %latch] 63 %iv.next = add i64 %iv, 1 64 call void @bar() 65 %cmp1 = icmp ult i64 %iv, 10 66 br i1 %cmp1, label %latch, label %exit 67latch: 68 call void @bar() 69 %cmp2 = icmp ult i64 %iv, 20 70 br i1 %cmp2, label %loop, label %exit 71exit: 72 ret void 73} 74 75; Fully unroll this loop by 10, but leave the unrolled latch 76; tests since we don't know if %N < 10, and break the backedge. 77define void @test2(i64 %N) { 78; CHECK-LABEL: @test2( 79; CHECK-NEXT: entry: 80; CHECK-NEXT: br label [[LOOP:%.*]] 81; CHECK: loop: 82; CHECK-NEXT: call void @bar() 83; CHECK-NEXT: br label [[LATCH:%.*]] 84; CHECK: latch: 85; CHECK-NEXT: call void @bar() 86; CHECK-NEXT: br i1 true, label [[LOOP_1:%.*]], label [[EXIT:%.*]] 87; CHECK: loop.1: 88; CHECK-NEXT: call void @bar() 89; CHECK-NEXT: br label [[LATCH_1:%.*]] 90; CHECK: latch.1: 91; CHECK-NEXT: call void @bar() 92; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ule i64 1, [[N:%.*]] 93; CHECK-NEXT: br i1 [[CMP2_1]], label [[LOOP_2:%.*]], label [[EXIT]] 94; CHECK: loop.2: 95; CHECK-NEXT: call void @bar() 96; CHECK-NEXT: br label [[LATCH_2:%.*]] 97; CHECK: latch.2: 98; CHECK-NEXT: call void @bar() 99; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ule i64 2, [[N]] 100; CHECK-NEXT: br i1 [[CMP2_2]], label [[LOOP_3:%.*]], label [[EXIT]] 101; CHECK: loop.3: 102; CHECK-NEXT: call void @bar() 103; CHECK-NEXT: br label [[LATCH_3:%.*]] 104; CHECK: latch.3: 105; CHECK-NEXT: call void @bar() 106; CHECK-NEXT: [[CMP2_3:%.*]] = icmp ule i64 3, [[N]] 107; CHECK-NEXT: br i1 [[CMP2_3]], label [[LOOP_4:%.*]], label [[EXIT]] 108; CHECK: loop.4: 109; CHECK-NEXT: call void @bar() 110; CHECK-NEXT: br label [[LATCH_4:%.*]] 111; CHECK: latch.4: 112; CHECK-NEXT: call void @bar() 113; CHECK-NEXT: [[CMP2_4:%.*]] = icmp ule i64 4, [[N]] 114; CHECK-NEXT: br i1 [[CMP2_4]], label [[LOOP_5:%.*]], label [[EXIT]] 115; CHECK: loop.5: 116; CHECK-NEXT: call void @bar() 117; CHECK-NEXT: br label [[LATCH_5:%.*]] 118; CHECK: latch.5: 119; CHECK-NEXT: call void @bar() 120; CHECK-NEXT: [[CMP2_5:%.*]] = icmp ule i64 5, [[N]] 121; CHECK-NEXT: br i1 [[CMP2_5]], label [[LOOP_6:%.*]], label [[EXIT]] 122; CHECK: loop.6: 123; CHECK-NEXT: call void @bar() 124; CHECK-NEXT: br label [[LATCH_6:%.*]] 125; CHECK: latch.6: 126; CHECK-NEXT: call void @bar() 127; CHECK-NEXT: [[CMP2_6:%.*]] = icmp ule i64 6, [[N]] 128; CHECK-NEXT: br i1 [[CMP2_6]], label [[LOOP_7:%.*]], label [[EXIT]] 129; CHECK: loop.7: 130; CHECK-NEXT: call void @bar() 131; CHECK-NEXT: br label [[LATCH_7:%.*]] 132; CHECK: latch.7: 133; CHECK-NEXT: call void @bar() 134; CHECK-NEXT: [[CMP2_7:%.*]] = icmp ule i64 7, [[N]] 135; CHECK-NEXT: br i1 [[CMP2_7]], label [[LOOP_8:%.*]], label [[EXIT]] 136; CHECK: loop.8: 137; CHECK-NEXT: call void @bar() 138; CHECK-NEXT: br label [[LATCH_8:%.*]] 139; CHECK: latch.8: 140; CHECK-NEXT: call void @bar() 141; CHECK-NEXT: [[CMP2_8:%.*]] = icmp ule i64 8, [[N]] 142; CHECK-NEXT: br i1 [[CMP2_8]], label [[LOOP_9:%.*]], label [[EXIT]] 143; CHECK: loop.9: 144; CHECK-NEXT: call void @bar() 145; CHECK-NEXT: br label [[LATCH_9:%.*]] 146; CHECK: latch.9: 147; CHECK-NEXT: call void @bar() 148; CHECK-NEXT: [[CMP2_9:%.*]] = icmp ule i64 9, [[N]] 149; CHECK-NEXT: br i1 [[CMP2_9]], label [[LOOP_10:%.*]], label [[EXIT]] 150; CHECK: loop.10: 151; CHECK-NEXT: call void @bar() 152; CHECK-NEXT: br label [[LATCH_10:%.*]] 153; CHECK: latch.10: 154; CHECK-NEXT: call void @bar() 155; CHECK-NEXT: [[CMP2_10:%.*]] = icmp ule i64 10, [[N]] 156; CHECK-NEXT: br i1 [[CMP2_10]], label [[LOOP_11:%.*]], label [[EXIT]] 157; CHECK: loop.11: 158; CHECK-NEXT: call void @bar() 159; CHECK-NEXT: br i1 false, label [[LATCH_11:%.*]], label [[EXIT]] 160; CHECK: latch.11: 161; CHECK-NEXT: call void @bar() 162; CHECK-NEXT: br label [[EXIT]] 163; CHECK: exit: 164; CHECK-NEXT: ret void 165; 166entry: 167 br label %loop 168loop: 169 %iv = phi i64 [0, %entry], [%iv.next, %latch] 170 %iv.next = add i64 %iv, 1 171 call void @bar() 172 %cmp1 = icmp ule i64 %iv, 10 173 br i1 %cmp1, label %latch, label %exit 174latch: 175 call void @bar() 176 %cmp2 = icmp ule i64 %iv, %N 177 br i1 %cmp2, label %loop, label %exit 178exit: 179 ret void 180} 181 182 183; TODO: We could partially unroll this by 2. 184define void @test3(i64 %N, i64 %M) { 185; CHECK-LABEL: @test3( 186; CHECK-NEXT: entry: 187; CHECK-NEXT: [[N_MASKED:%.*]] = and i64 [[N:%.*]], 65520 188; CHECK-NEXT: [[M_MASKED:%.*]] = and i64 [[M:%.*]], 65520 189; CHECK-NEXT: br label [[LOOP:%.*]] 190; CHECK: loop: 191; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 192; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 193; CHECK-NEXT: call void @bar() 194; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i64 [[IV]], [[N_MASKED]] 195; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT:%.*]] 196; CHECK: latch: 197; CHECK-NEXT: call void @bar() 198; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i64 [[IV]], [[M_MASKED]] 199; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT]] 200; CHECK: exit: 201; CHECK-NEXT: ret void 202; 203entry: 204 %N.masked = and i64 %N, 65520 ; 0xfff0 205 %M.masked = and i64 %M, 65520 ; 0xfff0 206 br label %loop 207loop: 208 %iv = phi i64 [0, %entry], [%iv.next, %latch] 209 %iv.next = add i64 %iv, 1 210 call void @bar() 211 %cmp1 = icmp ule i64 %iv, %N.masked 212 br i1 %cmp1, label %latch, label %exit 213latch: 214 call void @bar() 215 %cmp2 = icmp ule i64 %iv, %M.masked 216 br i1 %cmp2, label %loop, label %exit 217exit: 218 ret void 219} 220