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