1; RUN: opt -loop-unroll -S %s -verify-loop-info -verify-dom-info -verify-loop-lcssa | FileCheck %s 2 3%struct.spam = type { double, double, double, double, double, double, double } 4 5define void @test2(i32* %arg) { 6; CHECK-LABEL: void @test2 7; CHECK-NEXT: entry: 8; CHECK-NEXT: br label %for.header 9 10; CHECK-LABEL: for.header: ; preds = %entry 11; CHECK-NEXT: store i32 0, i32* %arg, align 4 12; CHECK-NEXT: br label %for.latch 13 14; CHECK-LABEL: for.latch: ; preds = %for.header 15; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 1 16; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 17; CHECK-NEXT: br label %for.latch.1 18 19; CHECK-LABEL: if.end.loopexit: ; preds = %for.latch.2 20; CHECK-NEXT: ret void 21 22; CHECK-LABEL: for.latch.1: ; preds = %for.latch 23; CHECK-NEXT: %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 2 24; CHECK-NEXT: store i32 0, i32* %ptr.2, align 4 25; CHECK-NEXT: br label %for.latch.2 26 27; CHECK-LABEL: for.latch.2: ; preds = %for.latch.1 28; CHECK-NEXT: %ptr.3 = getelementptr inbounds i32, i32* %arg, i64 3 29; CHECK-NEXT: store i32 0, i32* %ptr.3, align 4 30; CHECK-NEXT: br i1 true, label %if.end.loopexit, label %for.latch.3 31 32; CHECK-LABEL: for.latch.3: ; preds = %for.latch.2 33; CHECK-NEXT: unreachable 34 35entry: 36 br label %for.header 37 38for.header: ; preds = %for.latch, %entry 39 %indvars.iv800 = phi i64 [ 0, %entry ], [ %indvars.iv.next801, %for.latch ] 40 %ptr = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv800 41 store i32 0, i32* %ptr, align 4 42 %indvars.iv.next801 = add nuw nsw i64 %indvars.iv800, 1 43 %exitcond802 = icmp eq i64 %indvars.iv.next801, 4 44 br i1 %exitcond802, label %if.end.loopexit, label %for.latch 45 46for.latch: ; preds = %for.header 47 br label %for.header 48 49if.end.loopexit: ; preds = %for.header 50 ret void 51} 52 53define double @test_with_lcssa(double %arg1, double* %arg2) { 54; CHECK-LABEL: define double @test_with_lcssa( 55; CHECK-LABEL: entry: 56; CHECK-NEXT: br label %loop.header 57 58; CHECK-LABEL: loop.header: ; preds = %entry 59; CHECK-NEXT: %res = fsub double %arg1, 3.000000e+00 60; CHECK-NEXT: br label %loop.latch 61 62; CHECK-LABEL: loop.latch: ; preds = %loop.header 63; CHECK-NEXT: %ptr = getelementptr inbounds double, double* %arg2, i64 1 64; CHECK-NEXT: %lv = load double, double* %ptr, align 8 65; CHECK-NEXT: %res.1 = fsub double %lv, %res 66; CHECK-NEXT: br i1 true, label %loop.exit, label %loop.latch.1 67 68; CHECK-LABEL: loop.exit: ; preds = %loop.latch 69; CHECK-NEXT: %res.lcssa = phi double [ %res.1, %loop.latch ] 70; CHECK-NEXT: ret double %res.lcssa 71 72; CHECK-LABEL: loop.latch.1: ; preds = %loop.latch 73; CHECK-NEXT: %ptr.1 = getelementptr inbounds double, double* %arg2, i64 2 74; CHECK-NEXT: unreachable 75 76entry: 77 br label %loop.header 78 79loop.header: ; preds = %entry, %loop.latch 80 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 81 %d1 = phi double [ %arg1, %entry ], [ %lv, %loop.latch ] 82 %d2 = phi double [ 3.0, %entry ], [ %res, %loop.latch ] 83 %res = fsub double %d1, %d2 84 %iv.next = add nuw nsw i64 %iv, 1 85 %cond = icmp eq i64 %iv.next, 2 86 br i1 %cond, label %loop.exit, label %loop.latch 87 88loop.latch: ; preds = %bb366 89 %ptr = getelementptr inbounds double, double* %arg2, i64 %iv.next 90 %lv = load double, double* %ptr, align 8 91 br label %loop.header 92 93loop.exit: ; preds = %bb366 94 %res.lcssa = phi double [ %res, %loop.header ] 95 ret double %res.lcssa 96} 97 98; We unroll the outer loop and need to preserve LI for the inner loop. 99define void @test_with_nested_loop(i32* %arg) { 100; CHECK-LABEL: void @test_with_nested_loop 101; CHECK-LABEL: entry: 102; CHECK-NEXT: br label %outer.header 103 104; CHECK-DAG: outer.header: ; preds = %entry 105; CHECK-NEXT: br label %inner.body.preheader 106 107; CHECK-DAG: inner.body.preheader: ; preds = %outer.header 108; CHECK-NEXT: br label %inner.body 109 110; CHECK-LABEL: inner.body: ; preds = %inner.body.preheader, %inner.body 111; CHECK-NEXT: %j.iv = phi i64 [ %j.iv.next, %inner.body ], [ 0, %inner.body.preheader ] 112; CHECK-NEXT: %ptr = getelementptr inbounds i32, i32* %arg, i64 %j.iv 113; CHECK-NEXT: store i32 0, i32* %ptr, align 4 114; CHECK-NEXT: %j.iv.next = add nuw nsw i64 %j.iv, 1 115; CHECK-NEXT: %inner.cond = icmp eq i64 %j.iv.next, 40000 116; CHECK-NEXT: br i1 %inner.cond, label %outer.latch, label %inner.body 117 118; CHECK-LABEL: outer.latch: ; preds = %inner.body 119; CHECK-NEXT: br label %inner.body.preheader.1 120 121; CHECK-LABEL: exit: ; preds = %outer.latch.1 122; CHECK-NEXT: ret void 123 124; CHECK-LABEL: inner.body.preheader.1: ; preds = %outer.latch 125; CHECK-NEXT: br label %inner.body.1 126 127; CHECK-LABEL: inner.body.1: ; preds = %inner.body.1, %inner.body.preheader.1 128; CHECK-NEXT: %j.iv.1 = phi i64 [ %j.iv.next.1, %inner.body.1 ], [ 0, %inner.body.preheader.1 ] 129; CHECK-NEXT: %idx.1 = add i64 1, %j.iv.1 130; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1 131; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 132; CHECK-NEXT: %j.iv.next.1 = add nuw nsw i64 %j.iv.1, 1 133; CHECK-NEXT: %inner.cond.1 = icmp eq i64 %j.iv.next.1, 40000 134; CHECK-NEXT: br i1 %inner.cond.1, label %outer.latch.1, label %inner.body.1 135 136; CHECK-LABEL: outer.latch.1: ; preds = %inner.body.1 137; CHECK-NEXT: br i1 true, label %exit, label %inner.body.preheader.2 138 139; CHECK-LABEL: inner.body.preheader.2: ; preds = %outer.latch.1 140; CHECK-NEXT: br label %inner.body.2 141 142; CHECK-LABEL: inner.body.2: ; preds = %inner.body.2, %inner.body.preheader.2 143; CHECK-NEXT: %j.iv.2 = phi i64 [ %j.iv.next.2, %inner.body.2 ], [ 0, %inner.body.preheader.2 ] 144; CHECK-NEXT: %idx.2 = add i64 2, %j.iv.2 145; CHECK-NEXT: %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 %idx.2 146; CHECK-NEXT: store i32 0, i32* %ptr.2, align 4 147; CHECK-NEXT: %j.iv.next.2 = add nuw nsw i64 %j.iv.2, 1 148; CHECK-NEXT: %inner.cond.2 = icmp eq i64 %j.iv.next.2, 40000 149; CHECK-NEXT: br i1 %inner.cond.2, label %outer.latch.2, label %inner.body.2 150 151; CHECK-LABEL: outer.latch.2: ; preds = %inner.body.2 152; CHECK-NEXT: unreachable 153; 154entry: 155 br label %outer.header 156 157outer.header: ; preds = %outer.latch, %entry 158 %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ] 159 %outer.iv.next = add nuw nsw i64 %outer.iv, 1 160 %outer.cond = icmp eq i64 %outer.iv, 2 161 br i1 %outer.cond, label %exit, label %inner.body 162 163inner.body: 164 %j.iv = phi i64 [ 0, %outer.header ], [ %j.iv.next, %inner.body ] 165 %idx = add i64 %outer.iv, %j.iv 166 %ptr = getelementptr inbounds i32, i32* %arg, i64 %idx 167 store i32 0, i32* %ptr, align 4 168 %j.iv.next = add nuw nsw i64 %j.iv, 1 169 %inner.cond = icmp eq i64 %j.iv.next, 40000 170 br i1 %inner.cond, label %outer.latch, label %inner.body 171 172outer.latch: ; preds = %inner.body 173 br label %outer.header 174 175exit: ; preds = %outer.header 176 ret void 177} 178 179; We unroll the inner loop and need to preserve LI for the outer loop. 180define void @test_with_nested_loop_unroll_inner(i32* %arg) { 181; CHECK-LABEL: define void @test_with_nested_loop_unroll_inner( 182; CHECK-LABEL: entry: 183; CHECK-NEXT: br label %outer.header 184 185; CHECK-LABEL: outer.header: ; preds = %inner.body, %entry 186; CHECK-NEXT: %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %inner.body ] 187; CHECK-NEXT: %outer.iv.next = add nuw nsw i64 %outer.iv, 1 188; CHECK-NEXT: %outer.cond = icmp eq i64 %outer.iv, 40000 189; CHECK-NEXT: br i1 %outer.cond, label %exit, label %inner.body.preheader 190 191; CHECK-LABEL: inner.body.preheader: ; preds = %outer.header 192; CHECK-NEXT: br label %inner.body 193 194; CHECK-LABEL: inner.body: ; preds = %inner.body.preheader 195; CHECK-NEXT: %ptr = getelementptr inbounds i32, i32* %arg, i64 %outer.iv 196; CHECK-NEXT: store i32 0, i32* %ptr, align 4 197; CHECK-NEXT: %idx.1 = add i64 %outer.iv, 1 198; CHECK-NEXT: %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1 199; CHECK-NEXT: store i32 0, i32* %ptr.1, align 4 200; CHECK-NEXT: br label %outer.header 201 202; CHECK-LABEL: exit: ; preds = %outer.header 203; CHECK-NEXT: ret void 204; 205entry: 206 br label %outer.header 207 208outer.header: ; preds = %outer.latch, %entry 209 %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ] 210 %outer.iv.next = add nuw nsw i64 %outer.iv, 1 211 %outer.cond = icmp eq i64 %outer.iv, 40000 212 br i1 %outer.cond, label %exit, label %inner.body 213 214inner.body: 215 %j.iv = phi i64 [ 0, %outer.header ], [ %j.iv.next, %inner.body ] 216 %idx = add i64 %outer.iv, %j.iv 217 %ptr = getelementptr inbounds i32, i32* %arg, i64 %idx 218 store i32 0, i32* %ptr, align 4 219 %j.iv.next = add nuw nsw i64 %j.iv, 1 220 %inner.cond = icmp eq i64 %j.iv.next, 2 221 br i1 %inner.cond, label %outer.latch, label %inner.body 222 223outer.latch: ; preds = %inner.body 224 br label %outer.header 225 226exit: ; preds = %outer.header 227 ret void 228} 229 230 231 232; Check that we do not crash for headers with non-branch instructions, e.g. 233; switch. We do not unroll in those cases. 234define void @test_switchinst_in_header() { 235; CHECK-LABEL: define void @test_switchinst_in_header() { 236; CHECK-LABEL: entry: 237; CHECK-NEXT: br label %while.header 238 239; CHECK-LABEL: while.header: ; preds = %while.latch, %entry 240; CHECK-NEXT: switch i32 undef, label %exit [ 241; CHECK-NEXT: i32 11, label %while.body1 242; CHECK-NEXT: i32 5, label %while.body2 243; CHECK-NEXT: ] 244 245; CHECK-LABEL: while.body1: ; preds = %while.header 246; CHECK-NEXT: unreachable 247 248; CHECK-LABEL: while.body2: ; preds = %while.header 249; CHECK-NEXT: br label %while.latch 250 251; CHECK-LABEL: while.latch: ; preds = %while.body2 252; CHECK-NEXT: br label %while.header 253 254; CHECK-LABEL: exit: ; preds = %while.header 255; CHECK-NEXT: ret void 256; 257entry: 258 br label %while.header 259 260while.header: ; preds = %while.latch, %entry 261 switch i32 undef, label %exit [ 262 i32 11, label %while.body1 263 i32 5, label %while.body2 264 ] 265 266while.body1: ; preds = %while.header 267 unreachable 268 269while.body2: ; preds = %while.header 270 br label %while.latch 271 272while.latch: ; preds = %while.body2 273 br label %while.header 274 275exit: ; preds = %while.header 276 ret void 277} 278