1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s 3; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7define i32 @signed_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 8; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 11; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 12; CHECK: loop.preheader: 13; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 14; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 15; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[LOWERLIMIT:%.*]], 1 16; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 17; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 18; CHECK-NEXT: br label [[LOOP:%.*]] 19; CHECK: loop: 20; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 21; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 22; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 23; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 24; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 25; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 26; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 27; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 28; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 29; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 30; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I]], [[LOWERLIMIT]] 31; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 32; CHECK: exit.loopexit: 33; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 34; CHECK-NEXT: br label [[EXIT]] 35; CHECK: exit: 36; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 37; CHECK-NEXT: ret i32 [[RESULT]] 38; 39entry: 40 %tmp5 = icmp eq i32 %n, 0 41 br i1 %tmp5, label %exit, label %loop.preheader 42 43loop.preheader: 44 br label %loop 45 46loop: 47 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 48 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 49 %i.next = add nsw i32 %i, -1 50 %within.bounds = icmp ult i32 %i.next, %length 51 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 52 %i.i64 = zext i32 %i.next to i64 53 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 54 %array.i = load i32, ptr %array.i.ptr, align 4 55 %loop.acc.next = add i32 %loop.acc, %array.i 56 %continue = icmp sgt i32 %i, %lowerlimit 57 br i1 %continue, label %loop, label %exit 58 59exit: 60 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 61 ret i32 %result 62} 63 64define i32 @unsigned_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 65; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit( 66; CHECK-NEXT: entry: 67; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 68; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 69; CHECK: loop.preheader: 70; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 71; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 72; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[LOWERLIMIT:%.*]], 1 73; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 74; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 75; CHECK-NEXT: br label [[LOOP:%.*]] 76; CHECK: loop: 77; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 78; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 79; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 80; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 81; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 82; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 83; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 84; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 85; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 86; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 87; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], [[LOWERLIMIT]] 88; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 89; CHECK: exit.loopexit: 90; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 91; CHECK-NEXT: br label [[EXIT]] 92; CHECK: exit: 93; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 94; CHECK-NEXT: ret i32 [[RESULT]] 95; 96entry: 97 %tmp5 = icmp eq i32 %n, 0 98 br i1 %tmp5, label %exit, label %loop.preheader 99 100loop.preheader: 101 br label %loop 102 103loop: 104 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 105 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 106 %i.next = add nsw i32 %i, -1 107 %within.bounds = icmp ult i32 %i.next, %length 108 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 109 %i.i64 = zext i32 %i.next to i64 110 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 111 %array.i = load i32, ptr %array.i.ptr, align 4 112 %loop.acc.next = add i32 %loop.acc, %array.i 113 %continue = icmp ugt i32 %i, %lowerlimit 114 br i1 %continue, label %loop, label %exit 115 116exit: 117 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 118 ret i32 %result 119} 120 121 122; if we predicated the loop, the guard will definitely fail and we will 123; deoptimize early on. 124define i32 @unsigned_reverse_loop_n_to_0(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 125; CHECK-LABEL: @unsigned_reverse_loop_n_to_0( 126; CHECK-NEXT: entry: 127; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 128; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 129; CHECK: loop.preheader: 130; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 131; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 132; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false 133; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]] 134; CHECK-NEXT: br label [[LOOP:%.*]] 135; CHECK: loop: 136; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 137; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 138; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 139; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 140; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 141; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 142; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 143; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 144; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 145; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 146; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0 147; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 148; CHECK: exit.loopexit: 149; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 150; CHECK-NEXT: br label [[EXIT]] 151; CHECK: exit: 152; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 153; CHECK-NEXT: ret i32 [[RESULT]] 154; 155entry: 156 %tmp5 = icmp eq i32 %n, 0 157 br i1 %tmp5, label %exit, label %loop.preheader 158 159loop.preheader: 160 br label %loop 161 162loop: 163 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 164 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 165 %i.next = add nsw i32 %i, -1 166 %within.bounds = icmp ult i32 %i.next, %length 167 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 168 %i.i64 = zext i32 %i.next to i64 169 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 170 %array.i = load i32, ptr %array.i.ptr, align 4 171 %loop.acc.next = add i32 %loop.acc, %array.i 172 %continue = icmp ugt i32 %i, 0 173 br i1 %continue, label %loop, label %exit 174 175exit: 176 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 177 ret i32 %result 178} 179 180; do not loop predicate when the range has step -1 and latch has step 1. 181define i32 @reverse_loop_range_step_increment(i32 %n, ptr %array, i32 %length) { 182; CHECK-LABEL: @reverse_loop_range_step_increment( 183; CHECK-NEXT: entry: 184; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 185; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 186; CHECK: loop.preheader: 187; CHECK-NEXT: br label [[LOOP:%.*]] 188; CHECK: loop: 189; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 190; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 191; CHECK-NEXT: [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ] 192; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[IRC]], 1 193; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]] 194; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 195; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[IRC]] to i64 196; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 197; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 198; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 199; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 200; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534 201; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 202; CHECK: exit.loopexit: 203; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 204; CHECK-NEXT: br label [[EXIT]] 205; CHECK: exit: 206; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 207; CHECK-NEXT: ret i32 [[RESULT]] 208; 209entry: 210 %tmp5 = icmp eq i32 %n, 0 211 br i1 %tmp5, label %exit, label %loop.preheader 212 213loop.preheader: 214 br label %loop 215 216loop: 217 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 218 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 219 %irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ] 220 %i.inc = add nuw nsw i32 %irc, 1 221 %within.bounds = icmp ult i32 %irc, %length 222 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 223 %i.i64 = zext i32 %irc to i64 224 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 225 %array.i = load i32, ptr %array.i.ptr, align 4 226 %i.next = add nsw i32 %i, -1 227 %loop.acc.next = add i32 %loop.acc, %array.i 228 %continue = icmp ugt i32 %i, 65534 229 br i1 %continue, label %loop, label %exit 230 231exit: 232 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 233 ret i32 %result 234} 235 236define i32 @signed_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 237; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal( 238; CHECK-NEXT: entry: 239; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 240; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 241; CHECK: loop.preheader: 242; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 243; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 244; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1 245; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 246; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 247; CHECK-NEXT: br label [[LOOP:%.*]] 248; CHECK: loop: 249; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 250; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 251; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 252; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 253; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 254; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 255; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 256; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 257; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 258; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 259; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]] 260; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 261; CHECK: exit.loopexit: 262; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 263; CHECK-NEXT: br label [[EXIT]] 264; CHECK: exit: 265; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 266; CHECK-NEXT: ret i32 [[RESULT]] 267; 268entry: 269 %tmp5 = icmp eq i32 %n, 0 270 br i1 %tmp5, label %exit, label %loop.preheader 271 272loop.preheader: 273 br label %loop 274 275loop: 276 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 277 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 278 %i.next = add nsw i32 %i, -1 279 %within.bounds = icmp ult i32 %i.next, %length 280 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 281 %i.i64 = zext i32 %i.next to i64 282 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 283 %array.i = load i32, ptr %array.i.ptr, align 4 284 %loop.acc.next = add i32 %loop.acc, %array.i 285 %continue = icmp sge i32 %i, %lowerlimit 286 br i1 %continue, label %loop, label %exit 287 288exit: 289 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 290 ret i32 %result 291} 292 293define i32 @unsigned_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 294; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal( 295; CHECK-NEXT: entry: 296; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 297; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 298; CHECK: loop.preheader: 299; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 300; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 301; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1 302; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 303; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 304; CHECK-NEXT: br label [[LOOP:%.*]] 305; CHECK: loop: 306; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 307; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 308; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 309; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 310; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 311; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 312; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 313; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 314; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 315; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 316; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]] 317; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 318; CHECK: exit.loopexit: 319; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 320; CHECK-NEXT: br label [[EXIT]] 321; CHECK: exit: 322; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 323; CHECK-NEXT: ret i32 [[RESULT]] 324; 325entry: 326 %tmp5 = icmp eq i32 %n, 0 327 br i1 %tmp5, label %exit, label %loop.preheader 328 329loop.preheader: 330 br label %loop 331 332loop: 333 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 334 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 335 %i.next = add nsw i32 %i, -1 336 %within.bounds = icmp ult i32 %i.next, %length 337 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 338 %i.i64 = zext i32 %i.next to i64 339 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 340 %array.i = load i32, ptr %array.i.ptr, align 4 341 %loop.acc.next = add i32 %loop.acc, %array.i 342 %continue = icmp uge i32 %i, %lowerlimit 343 br i1 %continue, label %loop, label %exit 344 345exit: 346 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 347 ret i32 %result 348} 349 350 351; if we predicated the loop, the guard will definitely fail and we will 352; deoptimize early on. 353define i32 @unsigned_reverse_loop_n_to_1(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 354; CHECK-LABEL: @unsigned_reverse_loop_n_to_1( 355; CHECK-NEXT: entry: 356; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 357; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 358; CHECK: loop.preheader: 359; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 360; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 361; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false 362; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]] 363; CHECK-NEXT: br label [[LOOP:%.*]] 364; CHECK: loop: 365; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 366; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 367; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 368; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 369; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 370; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 371; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 372; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 373; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 374; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 375; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1 376; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 377; CHECK: exit.loopexit: 378; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 379; CHECK-NEXT: br label [[EXIT]] 380; CHECK: exit: 381; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 382; CHECK-NEXT: ret i32 [[RESULT]] 383; 384entry: 385 %tmp5 = icmp eq i32 %n, 0 386 br i1 %tmp5, label %exit, label %loop.preheader 387 388loop.preheader: 389 br label %loop 390 391loop: 392 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 393 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 394 %i.next = add nsw i32 %i, -1 395 %within.bounds = icmp ult i32 %i.next, %length 396 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 397 %i.i64 = zext i32 %i.next to i64 398 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 399 %array.i = load i32, ptr %array.i.ptr, align 4 400 %loop.acc.next = add i32 %loop.acc, %array.i 401 %continue = icmp uge i32 %i, 1 402 br i1 %continue, label %loop, label %exit 403 404exit: 405 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 406 ret i32 %result 407} 408 409