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