1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=indvars -indvars-predicate-loops=1 -S | FileCheck %s 3 4declare void @prevent_merging() 5 6; Base case 7define i32 @test1(ptr %array, i32 %length, i32 %n) { 8; CHECK-LABEL: @test1( 9; CHECK-NEXT: loop.preheader: 10; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 11; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1 12; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 13; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]]) 14; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 18; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 19; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] 20; CHECK: deopt: 21; CHECK-NEXT: call void @prevent_merging() 22; CHECK-NEXT: ret i32 -1 23; CHECK: guarded: 24; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 25; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 26; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 27; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 28; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 29; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 30; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 31; CHECK: exit: 32; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 33; CHECK-NEXT: ret i32 [[RESULT]] 34; 35loop.preheader: ; preds = %entry 36 br label %loop 37 38loop: ; preds = %guarded, %loop.preheader 39 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 40 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 41 %within.bounds = icmp ult i32 %i, %length 42 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 43 44deopt: ; preds = %loop 45 call void @prevent_merging() 46 ret i32 -1 47 48guarded: ; preds = %loop 49 %i.i64 = zext i32 %i to i64 50 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 51 %array.i = load i32, ptr %array.i.ptr, align 4 52 %loop.acc.next = add i32 %loop.acc, %array.i 53 %i.next = add nuw i32 %i, 1 54 %continue = icmp ult i32 %i.next, %n 55 br i1 %continue, label %loop, label %exit 56 57exit: ; preds = %guarded, %entry 58 %result = phi i32 [ %loop.acc.next, %guarded ] 59 ret i32 %result 60} 61 62; Has side effect which must be reflected 63define i32 @neg_store(ptr %array, i32 %length, i32 %n) { 64; CHECK-LABEL: @neg_store( 65; CHECK-NEXT: loop.preheader: 66; CHECK-NEXT: br label [[LOOP:%.*]] 67; CHECK: loop: 68; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 69; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 70; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 71; CHECK-NEXT: br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 72; CHECK: deopt: 73; CHECK-NEXT: call void @prevent_merging() 74; CHECK-NEXT: ret i32 -1 75; CHECK: guarded: 76; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 77; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 78; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 79; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 80; CHECK-NEXT: store i32 0, ptr [[ARRAY_I_PTR]], align 4 81; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 82; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]] 83; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 84; CHECK: exit: 85; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 86; CHECK-NEXT: ret i32 [[RESULT]] 87; 88loop.preheader: ; preds = %entry 89 br label %loop 90 91loop: ; preds = %guarded, %loop.preheader 92 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 93 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 94 %within.bounds = icmp ult i32 %i, %length 95 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 96 97deopt: ; preds = %loop 98 call void @prevent_merging() 99 ret i32 -1 100 101guarded: ; preds = %loop 102 %i.i64 = zext i32 %i to i64 103 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 104 %array.i = load i32, ptr %array.i.ptr, align 4 105 %loop.acc.next = add i32 %loop.acc, %array.i 106 store i32 0, ptr %array.i.ptr 107 %i.next = add nuw i32 %i, 1 108 %continue = icmp ult i32 %i.next, %n 109 br i1 %continue, label %loop, label %exit 110 111exit: ; preds = %guarded, %entry 112 %result = phi i32 [ %loop.acc.next, %guarded ] 113 ret i32 %result 114} 115 116declare void @maythrow() 117 118; May exit through implicit exception edge 119define i32 @neg_implicit_exit(ptr %array, i32 %length, i32 %n) { 120; CHECK-LABEL: @neg_implicit_exit( 121; CHECK-NEXT: loop.preheader: 122; CHECK-NEXT: br label [[LOOP:%.*]] 123; CHECK: loop: 124; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 125; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 126; CHECK-NEXT: call void @maythrow() 127; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 128; CHECK-NEXT: br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 129; CHECK: deopt: 130; CHECK-NEXT: call void @prevent_merging() 131; CHECK-NEXT: ret i32 -1 132; CHECK: guarded: 133; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 134; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 135; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 136; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 137; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 138; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]] 139; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 140; CHECK: exit: 141; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 142; CHECK-NEXT: ret i32 [[RESULT]] 143; 144loop.preheader: ; preds = %entry 145 br label %loop 146 147loop: ; preds = %guarded, %loop.preheader 148 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 149 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 150 call void @maythrow() 151 %within.bounds = icmp ult i32 %i, %length 152 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 153 154deopt: ; preds = %loop 155 call void @prevent_merging() 156 ret i32 -1 157 158guarded: ; preds = %loop 159 %i.i64 = zext i32 %i to i64 160 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 161 %array.i = load i32, ptr %array.i.ptr, align 4 162 %loop.acc.next = add i32 %loop.acc, %array.i 163 %i.next = add nuw i32 %i, 1 164 %continue = icmp ult i32 %i.next, %n 165 br i1 %continue, label %loop, label %exit 166 167exit: ; preds = %guarded, %entry 168 %result = phi i32 [ %loop.acc.next, %guarded ] 169 ret i32 %result 170} 171 172 173 174; Base case, but in LFTR form (just for basic correctness checking) 175define i32 @test2(ptr %array, i32 %length, i32 %n) { 176; CHECK-LABEL: @test2( 177; CHECK-NEXT: loop.preheader: 178; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1 179; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 180; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]]) 181; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 182; CHECK-NEXT: br label [[LOOP:%.*]] 183; CHECK: loop: 184; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 185; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 186; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 187; CHECK: deopt: 188; CHECK-NEXT: call void @prevent_merging() 189; CHECK-NEXT: ret i32 -1 190; CHECK: guarded: 191; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 192; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 193; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 194; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 195; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 196; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] 197; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 198; CHECK: exit: 199; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 200; CHECK-NEXT: ret i32 [[RESULT]] 201; 202loop.preheader: ; preds = %entry 203 br label %loop 204 205loop: ; preds = %guarded, %loop.preheader 206 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 207 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 208 %within.bounds = icmp ne i32 %i, %length 209 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 210 211deopt: ; preds = %loop 212 call void @prevent_merging() 213 ret i32 -1 214 215guarded: ; preds = %loop 216 %i.i64 = zext i32 %i to i64 217 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 218 %array.i = load i32, ptr %array.i.ptr, align 4 219 %loop.acc.next = add i32 %loop.acc, %array.i 220 %i.next = add nuw i32 %i, 1 221 %continue = icmp ne i32 %i.next, %n 222 br i1 %continue, label %loop, label %exit 223 224exit: ; preds = %guarded, %entry 225 %result = phi i32 [ %loop.acc.next, %guarded ] 226 ret i32 %result 227} 228 229; br (and rcheck1, rcheck2) 230define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, i32 %n) { 231; CHECK-LABEL: @two_range_checks( 232; CHECK-NEXT: loop.preheader: 233; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]]) 234; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 235; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1 236; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 237; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN]]) 238; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[UMIN]], [[UMIN1]] 239; CHECK-NEXT: br label [[LOOP:%.*]] 240; CHECK: loop: 241; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 242; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 243; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 244; CHECK: deopt: 245; CHECK-NEXT: call void @prevent_merging() 246; CHECK-NEXT: ret i32 -1 247; CHECK: guarded: 248; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 249; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]] 250; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4 251; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 252; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]] 253; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4 254; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 255; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 256; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 257; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 258; CHECK: exit: 259; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 260; CHECK-NEXT: ret i32 [[RESULT]] 261; 262loop.preheader: ; preds = %entry 263 br label %loop 264 265loop: ; preds = %guarded, %loop.preheader 266 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 267 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 268 %within.bounds.1 = icmp ult i32 %i, %length.1 269 %within.bounds.2 = icmp ult i32 %i, %length.2 270 %within.bounds = and i1 %within.bounds.1, %within.bounds.2 271 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 272 273deopt: ; preds = %loop 274 call void @prevent_merging() 275 ret i32 -1 276 277guarded: ; preds = %loop 278 %i.i64 = zext i32 %i to i64 279 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64 280 %array.1.i = load i32, ptr %array.1.i.ptr, align 4 281 %loop.acc.1 = add i32 %loop.acc, %array.1.i 282 %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64 283 %array.2.i = load i32, ptr %array.2.i.ptr, align 4 284 %loop.acc.next = add i32 %loop.acc.1, %array.2.i 285 %i.next = add nuw i32 %i, 1 286 %continue = icmp ult i32 %i.next, %n 287 br i1 %continue, label %loop, label %exit 288 289exit: ; preds = %guarded, %entry 290 %result = phi i32 [ %loop.acc.next, %guarded ] 291 ret i32 %result 292} 293 294define i32 @three_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, ptr %array.3, i32 %length.3, i32 %n) { 295; CHECK-LABEL: @three_range_checks( 296; CHECK-NEXT: loop.preheader: 297; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_3:%.*]], i32 [[LENGTH_2:%.*]]) 298; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]]) 299; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 300; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1 301; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 302; CHECK-NEXT: [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN1]]) 303; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN2]] 304; CHECK-NEXT: br label [[LOOP:%.*]] 305; CHECK: loop: 306; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 307; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 308; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 309; CHECK: deopt: 310; CHECK-NEXT: call void @prevent_merging() 311; CHECK-NEXT: ret i32 -1 312; CHECK: guarded: 313; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 314; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]] 315; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4 316; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 317; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]] 318; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4 319; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 320; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]] 321; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4 322; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] 323; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 324; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 325; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 326; CHECK: exit: 327; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 328; CHECK-NEXT: ret i32 [[RESULT]] 329; 330loop.preheader: ; preds = %entry 331 br label %loop 332 333loop: ; preds = %guarded, %loop.preheader 334 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 335 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 336 %within.bounds.1 = icmp ult i32 %i, %length.1 337 %within.bounds.2 = icmp ult i32 %i, %length.2 338 %within.bounds.3 = icmp ult i32 %i, %length.3 339 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2 340 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3 341 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 342 343deopt: ; preds = %loop 344 call void @prevent_merging() 345 ret i32 -1 346 347guarded: ; preds = %loop 348 %i.i64 = zext i32 %i to i64 349 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64 350 %array.1.i = load i32, ptr %array.1.i.ptr, align 4 351 %loop.acc.1 = add i32 %loop.acc, %array.1.i 352 %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64 353 %array.2.i = load i32, ptr %array.2.i.ptr, align 4 354 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 355 %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64 356 %array.3.i = load i32, ptr %array.3.i.ptr, align 4 357 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 358 %i.next = add nuw i32 %i, 1 359 %continue = icmp ult i32 %i.next, %n 360 br i1 %continue, label %loop, label %exit 361 362exit: ; preds = %guarded, %entry 363 %result = phi i32 [ %loop.acc.next, %guarded ] 364 ret i32 %result 365} 366 367; Analogous to the above, but with two distinct branches (on different conditions) 368define i32 @distinct_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, ptr %array.3, i32 %length.3, i32 %n) { 369; CHECK-LABEL: @distinct_checks( 370; CHECK-NEXT: loop.preheader: 371; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 372; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1 373; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 374; CHECK-NEXT: [[TMP2:%.*]] = freeze i32 [[LENGTH_2:%.*]] 375; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[TMP2]]) 376; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]]) 377; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[LENGTH_1]], [[UMIN1]] 378; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[LENGTH_2]], [[UMIN1]] 379; CHECK-NEXT: br label [[LOOP:%.*]] 380; CHECK: loop: 381; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 382; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 383; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 384; CHECK: deopt: 385; CHECK-NEXT: call void @prevent_merging() 386; CHECK-NEXT: ret i32 -1 387; CHECK: guarded: 388; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 389; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]] 390; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4 391; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 392; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]] 393; CHECK: deopt2: 394; CHECK-NEXT: call void @prevent_merging() 395; CHECK-NEXT: ret i32 -1 396; CHECK: guarded1: 397; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]] 398; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4 399; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 400; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 401; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 402; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 403; CHECK: exit: 404; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 405; CHECK-NEXT: ret i32 [[RESULT]] 406; 407loop.preheader: ; preds = %entry 408 br label %loop 409 410loop: ; preds = %guarded4, %loop.preheader 411 %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ] 412 %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ] 413 %within.bounds.1 = icmp ult i32 %i, %length.1 414 br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0 415 416deopt: ; preds = %loop 417 call void @prevent_merging() 418 ret i32 -1 419 420guarded: ; preds = %loop 421 %i.i64 = zext i32 %i to i64 422 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64 423 %array.1.i = load i32, ptr %array.1.i.ptr, align 4 424 %loop.acc.1 = add i32 %loop.acc, %array.1.i 425 %within.bounds.2 = icmp ult i32 %i, %length.2 426 br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0 427 428deopt2: ; preds = %guarded 429 call void @prevent_merging() 430 ret i32 -1 431 432guarded1: ; preds = %guarded1 433 %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64 434 %array.3.i = load i32, ptr %array.3.i.ptr, align 4 435 %loop.acc.next = add i32 %loop.acc.1, %array.3.i 436 %i.next = add nuw i32 %i, 1 437 %continue = icmp ult i32 %i.next, %n 438 br i1 %continue, label %loop, label %exit 439 440exit: 441 %result = phi i32 [ %loop.acc.next, %guarded1 ] 442 ret i32 %result 443} 444 445define i32 @duplicate_checks(ptr %array.1, ptr %array.2, ptr %array.3, i32 %length, i32 %n) { 446; CHECK-LABEL: @duplicate_checks( 447; CHECK-NEXT: loop.preheader: 448; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 449; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1 450; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]] 451; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]]) 452; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 453; CHECK-NEXT: br label [[LOOP:%.*]] 454; CHECK: loop: 455; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 456; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 457; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 458; CHECK: deopt: 459; CHECK-NEXT: call void @prevent_merging() 460; CHECK-NEXT: ret i32 -1 461; CHECK: guarded: 462; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 463; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]] 464; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4 465; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 466; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]] 467; CHECK: deopt2: 468; CHECK-NEXT: call void @prevent_merging() 469; CHECK-NEXT: ret i32 -1 470; CHECK: guarded1: 471; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]] 472; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4 473; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 474; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 475; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 476; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 477; CHECK: exit: 478; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 479; CHECK-NEXT: ret i32 [[RESULT]] 480; 481loop.preheader: ; preds = %entry 482 br label %loop 483 484loop: ; preds = %guarded4, %loop.preheader 485 %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ] 486 %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ] 487 %within.bounds.1 = icmp ult i32 %i, %length 488 br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0 489 490deopt: ; preds = %loop 491 call void @prevent_merging() 492 ret i32 -1 493 494guarded: ; preds = %loop 495 %i.i64 = zext i32 %i to i64 496 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64 497 %array.1.i = load i32, ptr %array.1.i.ptr, align 4 498 %loop.acc.1 = add i32 %loop.acc, %array.1.i 499 %within.bounds.2 = icmp ult i32 %i, %length 500 br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0 501 502deopt2: ; preds = %guarded 503 call void @prevent_merging() 504 ret i32 -1 505 506guarded1: ; preds = %guarded1 507 %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64 508 %array.3.i = load i32, ptr %array.3.i.ptr, align 4 509 %loop.acc.next = add i32 %loop.acc.1, %array.3.i 510 %i.next = add nuw i32 %i, 1 511 %continue = icmp ult i32 %i.next, %n 512 br i1 %continue, label %loop, label %exit 513 514exit: 515 %result = phi i32 [ %loop.acc.next, %guarded1 ] 516 ret i32 %result 517} 518 519 520define i32 @provably_taken(ptr %array, ptr %length.ptr) { 521; CHECK-LABEL: @provably_taken( 522; CHECK-NEXT: loop.preheader: 523; CHECK-NEXT: br label [[LOOP:%.*]] 524; CHECK: loop: 525; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 526; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 527; CHECK-NEXT: br i1 false, label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 528; CHECK: deopt: 529; CHECK-NEXT: call void @prevent_merging() 530; CHECK-NEXT: ret i32 -1 531; CHECK: guarded: 532; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 533; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 534; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 535; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 536; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 537; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT:%.*]] 538; CHECK: exit: 539; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 540; CHECK-NEXT: ret i32 [[RESULT]] 541; 542loop.preheader: 543 %length = load i32, ptr %length.ptr, !range !2 544 br label %loop 545 546loop: ; preds = %guarded, %loop.preheader 547 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 548 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 549 %within.bounds = icmp ult i32 %i, %length 550 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 551 552deopt: ; preds = %loop 553 call void @prevent_merging() 554 ret i32 -1 555 556guarded: ; preds = %loop 557 %i.i64 = zext i32 %i to i64 558 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 559 %array.i = load i32, ptr %array.i.ptr, align 4 560 %loop.acc.next = add i32 %loop.acc, %array.i 561 %i.next = add nuw i32 %i, 1 562 %continue = icmp slt i32 %i.next, 200 563 br i1 %continue, label %loop, label %exit 564 565exit: ; preds = %guarded 566 %result = phi i32 [ %loop.acc.next, %guarded ] 567 ret i32 %result 568} 569 570; Non-latch exits can still be predicated 571define i32 @unconditional_latch(ptr %a, i32 %length) { 572; CHECK-LABEL: @unconditional_latch( 573; CHECK-NEXT: loop.preheader: 574; CHECK-NEXT: br label [[LOOP:%.*]] 575; CHECK: loop: 576; CHECK-NEXT: br i1 false, label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 577; CHECK: deopt: 578; CHECK-NEXT: call void @prevent_merging() 579; CHECK-NEXT: ret i32 -1 580; CHECK: guarded: 581; CHECK-NEXT: br label [[LOOP]] 582; 583loop.preheader: 584 br label %loop 585 586loop: ; preds = %guarded, %loop.preheader 587 %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ] 588 %within.bounds = icmp ult i32 %i, %length 589 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 590 591deopt: ; preds = %loop 592 call void @prevent_merging() 593 ret i32 -1 594 595guarded: ; preds = %loop 596 %i.next = add i32 %i, 1 597 br label %loop 598} 599 600; Side effect in loop must run proper number of times 601define i32 @unconditional_latch_with_side_effect(ptr %a, i32 %length) { 602; CHECK-LABEL: @unconditional_latch_with_side_effect( 603; CHECK-NEXT: loop.preheader: 604; CHECK-NEXT: br label [[LOOP:%.*]] 605; CHECK: loop: 606; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED:%.*]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] 607; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 608; CHECK-NEXT: br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 609; CHECK: deopt: 610; CHECK-NEXT: call void @prevent_merging() 611; CHECK-NEXT: ret i32 -1 612; CHECK: guarded: 613; CHECK-NEXT: store volatile i32 0, ptr [[A:%.*]], align 4 614; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 615; CHECK-NEXT: br label [[LOOP]] 616; 617loop.preheader: 618 br label %loop 619 620loop: ; preds = %guarded, %loop.preheader 621 %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ] 622 %within.bounds = icmp ult i32 %i, %length 623 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 624 625deopt: ; preds = %loop 626 call void @prevent_merging() 627 ret i32 -1 628 629guarded: ; preds = %loop 630 store volatile i32 0, ptr %a 631 %i.next = add i32 %i, 1 632 br label %loop 633} 634 635; Demonstrate that this approach works with IVs of different steps, and types 636; This version uses a manually lftred exit condition to work around an issue described 637; in detail on next test. 638define i32 @different_ivs(ptr %array, i32 %length, i32 %n) { 639; CHECK-LABEL: @different_ivs( 640; CHECK-NEXT: loop.preheader: 641; CHECK-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64 642; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N64]], i64 1) 643; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[UMAX]], -1 644; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]] 645; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64 646; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]]) 647; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[LENGTH]] to i64 648; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], [[UMIN]] 649; CHECK-NEXT: br label [[LOOP:%.*]] 650; CHECK: loop: 651; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 652; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 653; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 654; CHECK: deopt: 655; CHECK-NEXT: call void @prevent_merging() 656; CHECK-NEXT: ret i32 -1 657; CHECK: guarded: 658; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I]] 659; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 660; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 661; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1 662; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]] 663; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 664; CHECK: exit: 665; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 666; CHECK-NEXT: ret i32 [[RESULT]] 667; 668loop.preheader: 669 %j.start = sub nuw nsw i32 %length, 1 670 %n64 = zext i32 %n to i64 671 br label %loop 672 673loop: 674 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 675 %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ] 676 %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ] 677 %within.bounds = icmp ne i32 %j, -1 678 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 679 680deopt: 681 call void @prevent_merging() 682 ret i32 -1 683 684guarded: 685 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i 686 %array.i = load i32, ptr %array.i.ptr, align 4 687 %loop.acc.next = add i32 %loop.acc, %array.i 688 %i.next = add nuw i64 %i, 1 689 %j.next = sub nuw i32 %j, 1 690 %continue = icmp ult i64 %i.next, %n64 691 br i1 %continue, label %loop, label %exit 692 693exit: 694 %result = phi i32 [ %loop.acc.next, %guarded ] 695 ret i32 %result 696} 697 698; TODO: We're failing to compute an exit count for the bounds check. 699; From some quick analysis, it looks like we don't handle -1 step 700; in howManyLessThans. Should be a simple fix. 701define i32 @different_ivs2(ptr %array, i32 %length, i32 %n) { 702; CHECK-LABEL: @different_ivs2( 703; CHECK-NEXT: entry: 704; CHECK-NEXT: [[POS_LENGTH:%.*]] = icmp sgt i32 [[LENGTH:%.*]], 0 705; CHECK-NEXT: br i1 [[POS_LENGTH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 706; CHECK: loop.preheader: 707; CHECK-NEXT: [[J_START:%.*]] = sub nuw nsw i32 [[LENGTH]], 1 708; CHECK-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64 709; CHECK-NEXT: br label [[LOOP:%.*]] 710; CHECK: loop: 711; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 712; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 713; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ [[J_START]], [[LOOP_PREHEADER]] ] 714; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] 715; CHECK-NEXT: br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] 716; CHECK: deopt: 717; CHECK-NEXT: call void @prevent_merging() 718; CHECK-NEXT: ret i32 -1 719; CHECK: guarded: 720; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I]] 721; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 722; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 723; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1 724; CHECK-NEXT: [[J_NEXT]] = sub nuw i32 [[J]], 1 725; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]] 726; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 727; CHECK: exit.loopexit: 728; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 729; CHECK-NEXT: br label [[EXIT]] 730; CHECK: exit: 731; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 732; CHECK-NEXT: ret i32 [[RESULT]] 733; 734entry: 735 %pos_length = icmp sgt i32 %length, 0 736 br i1 %pos_length, label %loop.preheader, label %exit 737 738loop.preheader: 739 %j.start = sub nuw nsw i32 %length, 1 740 %n64 = zext i32 %n to i64 741 br label %loop 742 743loop: 744 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 745 %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ] 746 %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ] 747 %within.bounds = icmp ult i32 %j, %length 748 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 749 750deopt: 751 call void @prevent_merging() 752 ret i32 -1 753 754guarded: 755 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i 756 %array.i = load i32, ptr %array.i.ptr, align 4 757 %loop.acc.next = add i32 %loop.acc, %array.i 758 %i.next = add nuw i64 %i, 1 759 %j.next = sub nuw i32 %j, 1 760 %continue = icmp ult i64 %i.next, %n64 761 br i1 %continue, label %loop, label %exit 762 763exit: 764 %result = phi i32 [ %loop.acc.next, %guarded ], [0, %entry] 765 ret i32 %result 766} 767 768; If we have a dominating exit (exit1) which can't be itself rewritten, we 769; can't rewrite a later exit (exit2). Doing so would cause the loop to exit 770; from the exit2 when it should have exited from exit1. 771define i32 @neg_dominating_exit(ptr %array, i32 %length, i32 %length2, i32 %n) { 772; CHECK-LABEL: @neg_dominating_exit( 773; CHECK-NEXT: loop.preheader: 774; CHECK-NEXT: br label [[LOOP:%.*]] 775; CHECK: loop: 776; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED2:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 777; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED2]] ], [ 0, [[LOOP_PREHEADER]] ] 778; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 779; CHECK-NEXT: br i1 [[WITHIN_BOUNDS]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 780; CHECK: deopt: 781; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC]], [[LOOP]] ] 782; CHECK-NEXT: call void @prevent_merging() 783; CHECK-NEXT: ret i32 [[RESULT]] 784; CHECK: guarded: 785; CHECK-NEXT: [[WITHIN_BOUNDS2:%.*]] = icmp ult i32 [[I]], [[LENGTH2:%.*]] 786; CHECK-NEXT: br i1 [[WITHIN_BOUNDS2]], label [[GUARDED2]], label [[DEOPT2:%.*]], !prof [[PROF0]] 787; CHECK: deopt2: 788; CHECK-NEXT: call void @prevent_merging() 789; CHECK-NEXT: ret i32 -1 790; CHECK: guarded2: 791; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 792; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 793; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 794; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 795; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 796; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]] 797; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 798; CHECK: exit: 799; CHECK-NEXT: [[RESULT2:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED2]] ] 800; CHECK-NEXT: ret i32 [[RESULT2]] 801; 802loop.preheader: ; preds = %entry 803 br label %loop 804 805loop: ; preds = %guarded, %loop.preheader 806 %loop.acc = phi i32 [ %loop.acc.next, %guarded2 ], [ 0, %loop.preheader ] 807 %i = phi i32 [ %i.next, %guarded2 ], [ 0, %loop.preheader ] 808 %within.bounds = icmp ult i32 %i, %length 809 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 810 811deopt: ; preds = %loop 812 %result = phi i32 [ %loop.acc, %loop ] 813 call void @prevent_merging() 814 ret i32 %result 815 816guarded: ; preds = %loop 817 %within.bounds2 = icmp ult i32 %i, %length2 818 br i1 %within.bounds2, label %guarded2, label %deopt2, !prof !0 819 820deopt2: ; preds = %loop 821 call void @prevent_merging() 822 ret i32 -1 823 824guarded2: ; preds = %loop 825 %i.i64 = zext i32 %i to i64 826 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 827 %array.i = load i32, ptr %array.i.ptr, align 4 828 %loop.acc.next = add i32 %loop.acc, %array.i 829 %i.next = add nuw i32 %i, 1 830 %continue = icmp ult i32 %i.next, %n 831 br i1 %continue, label %loop, label %exit 832 833exit: ; preds = %guarded, %entry 834 %result2 = phi i32 [ %loop.acc.next, %guarded2 ] 835 ret i32 %result2 836} 837 838 839declare i32 @llvm.experimental.deoptimize.i32(...) 840 841!0 = !{!"branch_weights", i32 1048576, i32 1} 842!1 = !{i32 1, i32 -2147483648} 843!2 = !{i32 0, i32 50} 844