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: 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: [[TMP2:%.*]] = and i1 [[TMP1]], false 127; CHECK-NEXT: br label [[LOOP:%.*]] 128; CHECK: loop: 129; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 130; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 131; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 132; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 133; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 134; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 135; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 136; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 137; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0 138; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 139; CHECK: exit.loopexit: 140; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 141; CHECK-NEXT: br label [[EXIT]] 142; CHECK: exit: 143; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 144; CHECK-NEXT: ret i32 [[RESULT]] 145; 146entry: 147 %tmp5 = icmp eq i32 %n, 0 148 br i1 %tmp5, label %exit, label %loop.preheader 149 150loop.preheader: 151 br label %loop 152 153loop: 154 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 155 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 156 %i.next = add nsw i32 %i, -1 157 %within.bounds = icmp ult i32 %i.next, %length 158 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 159 %i.i64 = zext i32 %i.next to i64 160 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 161 %array.i = load i32, i32* %array.i.ptr, align 4 162 %loop.acc.next = add i32 %loop.acc, %array.i 163 %continue = icmp ugt i32 %i, 0 164 br i1 %continue, label %loop, label %exit 165 166exit: 167 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 168 ret i32 %result 169} 170 171; do not loop predicate when the range has step -1 and latch has step 1. 172define i32 @reverse_loop_range_step_increment(i32 %n, i32* %array, i32 %length) { 173; CHECK-LABEL: @reverse_loop_range_step_increment( 174; CHECK-NEXT: entry: 175; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 176; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 177; CHECK: loop.preheader: 178; CHECK-NEXT: br label [[LOOP:%.*]] 179; CHECK: loop: 180; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 181; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 182; CHECK-NEXT: [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ] 183; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[IRC]], 1 184; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]] 185; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 186; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[IRC]] to i64 187; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 188; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 189; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 190; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 191; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534 192; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 193; CHECK: exit.loopexit: 194; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 195; CHECK-NEXT: br label [[EXIT]] 196; CHECK: exit: 197; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 198; CHECK-NEXT: ret i32 [[RESULT]] 199; 200entry: 201 %tmp5 = icmp eq i32 %n, 0 202 br i1 %tmp5, label %exit, label %loop.preheader 203 204loop.preheader: 205 br label %loop 206 207loop: 208 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 209 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 210 %irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ] 211 %i.inc = add nuw nsw i32 %irc, 1 212 %within.bounds = icmp ult i32 %irc, %length 213 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 214 %i.i64 = zext i32 %irc to i64 215 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 216 %array.i = load i32, i32* %array.i.ptr, align 4 217 %i.next = add nsw i32 %i, -1 218 %loop.acc.next = add i32 %loop.acc, %array.i 219 %continue = icmp ugt i32 %i, 65534 220 br i1 %continue, label %loop, label %exit 221 222exit: 223 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 224 ret i32 %result 225} 226 227define i32 @signed_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) { 228; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal( 229; CHECK-NEXT: entry: 230; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 231; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 232; CHECK: loop.preheader: 233; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 234; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 235; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1 236; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 237; CHECK-NEXT: br label [[LOOP:%.*]] 238; CHECK: loop: 239; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 240; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 241; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 242; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 243; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 244; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 245; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 246; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 247; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]] 248; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 249; CHECK: exit.loopexit: 250; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 251; CHECK-NEXT: br label [[EXIT]] 252; CHECK: exit: 253; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 254; CHECK-NEXT: ret i32 [[RESULT]] 255; 256entry: 257 %tmp5 = icmp eq i32 %n, 0 258 br i1 %tmp5, label %exit, label %loop.preheader 259 260loop.preheader: 261 br label %loop 262 263loop: 264 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 265 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 266 %i.next = add nsw i32 %i, -1 267 %within.bounds = icmp ult i32 %i.next, %length 268 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 269 %i.i64 = zext i32 %i.next to i64 270 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 271 %array.i = load i32, i32* %array.i.ptr, align 4 272 %loop.acc.next = add i32 %loop.acc, %array.i 273 %continue = icmp sge i32 %i, %lowerlimit 274 br i1 %continue, label %loop, label %exit 275 276exit: 277 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 278 ret i32 %result 279} 280 281define i32 @unsigned_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) { 282; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal( 283; CHECK-NEXT: entry: 284; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 285; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 286; CHECK: loop.preheader: 287; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 288; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 289; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1 290; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 291; CHECK-NEXT: br label [[LOOP:%.*]] 292; CHECK: loop: 293; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 294; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 295; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 296; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 297; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 298; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 299; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 300; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 301; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]] 302; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 303; CHECK: exit.loopexit: 304; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 305; CHECK-NEXT: br label [[EXIT]] 306; CHECK: exit: 307; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 308; CHECK-NEXT: ret i32 [[RESULT]] 309; 310entry: 311 %tmp5 = icmp eq i32 %n, 0 312 br i1 %tmp5, label %exit, label %loop.preheader 313 314loop.preheader: 315 br label %loop 316 317loop: 318 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 319 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 320 %i.next = add nsw i32 %i, -1 321 %within.bounds = icmp ult i32 %i.next, %length 322 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 323 %i.i64 = zext i32 %i.next to i64 324 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 325 %array.i = load i32, i32* %array.i.ptr, align 4 326 %loop.acc.next = add i32 %loop.acc, %array.i 327 %continue = icmp uge i32 %i, %lowerlimit 328 br i1 %continue, label %loop, label %exit 329 330exit: 331 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 332 ret i32 %result 333} 334 335 336; if we predicated the loop, the guard will definitely fail and we will 337; deoptimize early on. 338define i32 @unsigned_reverse_loop_n_to_1(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) { 339; CHECK-LABEL: @unsigned_reverse_loop_n_to_1( 340; CHECK-NEXT: entry: 341; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 342; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 343; CHECK: loop.preheader: 344; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 345; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 346; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false 347; CHECK-NEXT: br label [[LOOP:%.*]] 348; CHECK: loop: 349; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 350; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 351; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 352; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 353; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 354; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 355; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 356; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 357; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1 358; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 359; CHECK: exit.loopexit: 360; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 361; CHECK-NEXT: br label [[EXIT]] 362; CHECK: exit: 363; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 364; CHECK-NEXT: ret i32 [[RESULT]] 365; 366entry: 367 %tmp5 = icmp eq i32 %n, 0 368 br i1 %tmp5, label %exit, label %loop.preheader 369 370loop.preheader: 371 br label %loop 372 373loop: 374 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 375 %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 376 %i.next = add nsw i32 %i, -1 377 %within.bounds = icmp ult i32 %i.next, %length 378 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 379 %i.i64 = zext i32 %i.next to i64 380 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 381 %array.i = load i32, i32* %array.i.ptr, align 4 382 %loop.acc.next = add i32 %loop.acc, %array.i 383 %continue = icmp uge i32 %i, 1 384 br i1 %continue, label %loop, label %exit 385 386exit: 387 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 388 ret i32 %result 389} 390 391