1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s 3; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7define i32 @signed_loop_0_to_n_nested_0_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 8; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_inner_index_check( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 11; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[OUTER_LOOP_PREHEADER:%.*]] 12; CHECK: outer.loop.preheader: 13; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 14; CHECK: outer.loop: 15; CHECK-NEXT: [[OUTER_LOOP_ACC:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT:%.*]], [[OUTER_LOOP_INC:%.*]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 16; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OUTER_LOOP_INC]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 17; CHECK-NEXT: [[TMP6:%.*]] = icmp sle i32 [[L:%.*]], 0 18; CHECK-NEXT: br i1 [[TMP6]], label [[OUTER_LOOP_INC]], label [[INNER_LOOP_PREHEADER:%.*]] 19; CHECK: inner.loop.preheader: 20; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[L]], [[LENGTH:%.*]] 21; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 22; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 23; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 24; CHECK: inner.loop: 25; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] 26; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ 0, [[INNER_LOOP_PREHEADER]] ] 27; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] 28; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 29; CHECK-NEXT: [[J_I64:%.*]] = zext i32 [[J]] to i64 30; CHECK-NEXT: [[ARRAY_J_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[J_I64]] 31; CHECK-NEXT: [[ARRAY_J:%.*]] = load i32, i32* [[ARRAY_J_PTR]], align 4 32; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT]] = add i32 [[INNER_LOOP_ACC]], [[ARRAY_J]] 33; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1 34; CHECK-NEXT: [[INNER_CONTINUE:%.*]] = icmp slt i32 [[J_NEXT]], [[L]] 35; CHECK-NEXT: br i1 [[INNER_CONTINUE]], label [[INNER_LOOP]], label [[OUTER_LOOP_INC_LOOPEXIT:%.*]] 36; CHECK: outer.loop.inc.loopexit: 37; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT]], [[INNER_LOOP]] ] 38; CHECK-NEXT: br label [[OUTER_LOOP_INC]] 39; CHECK: outer.loop.inc: 40; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT]] = phi i32 [ [[OUTER_LOOP_ACC]], [[OUTER_LOOP]] ], [ [[INNER_LOOP_ACC_NEXT_LCSSA]], [[OUTER_LOOP_INC_LOOPEXIT]] ] 41; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 42; CHECK-NEXT: [[OUTER_CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 43; CHECK-NEXT: br i1 [[OUTER_CONTINUE]], label [[OUTER_LOOP]], label [[EXIT_LOOPEXIT:%.*]] 44; CHECK: exit.loopexit: 45; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT]], [[OUTER_LOOP_INC]] ] 46; CHECK-NEXT: br label [[EXIT]] 47; CHECK: exit: 48; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 49; CHECK-NEXT: ret i32 [[RESULT]] 50; 51entry: 52 %tmp5 = icmp sle i32 %n, 0 53 br i1 %tmp5, label %exit, label %outer.loop.preheader 54 55outer.loop.preheader: 56 br label %outer.loop 57 58outer.loop: 59 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 60 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 61 %tmp6 = icmp sle i32 %l, 0 62 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 63 64inner.loop.preheader: 65 br label %inner.loop 66 67inner.loop: 68 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 69 %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ] 70 71 %within.bounds = icmp ult i32 %j, %length 72 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 73 74 %j.i64 = zext i32 %j to i64 75 %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64 76 %array.j = load i32, i32* %array.j.ptr, align 4 77 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j 78 79 %j.next = add nsw i32 %j, 1 80 %inner.continue = icmp slt i32 %j.next, %l 81 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 82 83outer.loop.inc: 84 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 85 %i.next = add nsw i32 %i, 1 86 %outer.continue = icmp slt i32 %i.next, %n 87 br i1 %outer.continue, label %outer.loop, label %exit 88 89exit: 90 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 91 ret i32 %result 92} 93 94define i32 @signed_loop_0_to_n_nested_0_to_l_outer_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 95; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_outer_index_check( 96; CHECK-NEXT: entry: 97; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 98; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[OUTER_LOOP_PREHEADER:%.*]] 99; CHECK: outer.loop.preheader: 100; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]] 101; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 102; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 103; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 104; CHECK: outer.loop: 105; CHECK-NEXT: [[OUTER_LOOP_ACC:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT:%.*]], [[OUTER_LOOP_INC:%.*]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 106; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OUTER_LOOP_INC]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 107; CHECK-NEXT: [[TMP6:%.*]] = icmp sle i32 [[L:%.*]], 0 108; CHECK-NEXT: br i1 [[TMP6]], label [[OUTER_LOOP_INC]], label [[INNER_LOOP_PREHEADER:%.*]] 109; CHECK: inner.loop.preheader: 110; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 111; CHECK: inner.loop: 112; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] 113; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ 0, [[INNER_LOOP_PREHEADER]] ] 114; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] 115; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 116; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 117; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 118; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 119; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT]] = add i32 [[INNER_LOOP_ACC]], [[ARRAY_I]] 120; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1 121; CHECK-NEXT: [[INNER_CONTINUE:%.*]] = icmp slt i32 [[J_NEXT]], [[L]] 122; CHECK-NEXT: br i1 [[INNER_CONTINUE]], label [[INNER_LOOP]], label [[OUTER_LOOP_INC_LOOPEXIT:%.*]] 123; CHECK: outer.loop.inc.loopexit: 124; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT]], [[INNER_LOOP]] ] 125; CHECK-NEXT: br label [[OUTER_LOOP_INC]] 126; CHECK: outer.loop.inc: 127; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT]] = phi i32 [ [[OUTER_LOOP_ACC]], [[OUTER_LOOP]] ], [ [[INNER_LOOP_ACC_NEXT_LCSSA]], [[OUTER_LOOP_INC_LOOPEXIT]] ] 128; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 129; CHECK-NEXT: [[OUTER_CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 130; CHECK-NEXT: br i1 [[OUTER_CONTINUE]], label [[OUTER_LOOP]], label [[EXIT_LOOPEXIT:%.*]] 131; CHECK: exit.loopexit: 132; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT]], [[OUTER_LOOP_INC]] ] 133; CHECK-NEXT: br label [[EXIT]] 134; CHECK: exit: 135; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 136; CHECK-NEXT: ret i32 [[RESULT]] 137; 138entry: 139 %tmp5 = icmp sle i32 %n, 0 140 br i1 %tmp5, label %exit, label %outer.loop.preheader 141 142outer.loop.preheader: 143 br label %outer.loop 144 145outer.loop: 146 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 147 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 148 %tmp6 = icmp sle i32 %l, 0 149 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 150 151inner.loop.preheader: 152 br label %inner.loop 153 154inner.loop: 155 156 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 157 %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ] 158 159 %within.bounds = icmp ult i32 %i, %length 160 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 161 162 %i.i64 = zext i32 %i 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 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.i 166 167 %j.next = add nsw i32 %j, 1 168 %inner.continue = icmp slt i32 %j.next, %l 169 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 170 171outer.loop.inc: 172 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 173 %i.next = add nsw i32 %i, 1 174 %outer.continue = icmp slt i32 %i.next, %n 175 br i1 %outer.continue, label %outer.loop, label %exit 176 177exit: 178 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 179 ret i32 %result 180} 181 182define i32 @signed_loop_0_to_n_nested_i_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 183; CHECK-LABEL: @signed_loop_0_to_n_nested_i_to_l_inner_index_check( 184; CHECK-NEXT: entry: 185; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 186; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[OUTER_LOOP_PREHEADER:%.*]] 187; CHECK: outer.loop.preheader: 188; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]] 189; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 190; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 191; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 192; CHECK: outer.loop: 193; CHECK-NEXT: [[OUTER_LOOP_ACC:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT:%.*]], [[OUTER_LOOP_INC:%.*]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 194; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OUTER_LOOP_INC]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 195; CHECK-NEXT: [[TMP6:%.*]] = icmp sle i32 [[L:%.*]], 0 196; CHECK-NEXT: br i1 [[TMP6]], label [[OUTER_LOOP_INC]], label [[INNER_LOOP_PREHEADER:%.*]] 197; CHECK: inner.loop.preheader: 198; CHECK-NEXT: [[TMP3:%.*]] = icmp sle i32 [[L]], [[LENGTH]] 199; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[I]], [[LENGTH]] 200; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]] 201; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 202; CHECK: inner.loop: 203; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] 204; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ [[I]], [[INNER_LOOP_PREHEADER]] ] 205; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] 206; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP2]] 207; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ] 208; CHECK-NEXT: [[J_I64:%.*]] = zext i32 [[J]] to i64 209; CHECK-NEXT: [[ARRAY_J_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[J_I64]] 210; CHECK-NEXT: [[ARRAY_J:%.*]] = load i32, i32* [[ARRAY_J_PTR]], align 4 211; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT]] = add i32 [[INNER_LOOP_ACC]], [[ARRAY_J]] 212; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1 213; CHECK-NEXT: [[INNER_CONTINUE:%.*]] = icmp slt i32 [[J_NEXT]], [[L]] 214; CHECK-NEXT: br i1 [[INNER_CONTINUE]], label [[INNER_LOOP]], label [[OUTER_LOOP_INC_LOOPEXIT:%.*]] 215; CHECK: outer.loop.inc.loopexit: 216; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT]], [[INNER_LOOP]] ] 217; CHECK-NEXT: br label [[OUTER_LOOP_INC]] 218; CHECK: outer.loop.inc: 219; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT]] = phi i32 [ [[OUTER_LOOP_ACC]], [[OUTER_LOOP]] ], [ [[INNER_LOOP_ACC_NEXT_LCSSA]], [[OUTER_LOOP_INC_LOOPEXIT]] ] 220; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 221; CHECK-NEXT: [[OUTER_CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 222; CHECK-NEXT: br i1 [[OUTER_CONTINUE]], label [[OUTER_LOOP]], label [[EXIT_LOOPEXIT:%.*]] 223; CHECK: exit.loopexit: 224; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT]], [[OUTER_LOOP_INC]] ] 225; CHECK-NEXT: br label [[EXIT]] 226; CHECK: exit: 227; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 228; CHECK-NEXT: ret i32 [[RESULT]] 229; 230entry: 231 %tmp5 = icmp sle i32 %n, 0 232 br i1 %tmp5, label %exit, label %outer.loop.preheader 233 234outer.loop.preheader: 235 br label %outer.loop 236 237outer.loop: 238 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 239 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 240 %tmp6 = icmp sle i32 %l, 0 241 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 242 243inner.loop.preheader: 244 br label %inner.loop 245 246inner.loop: 247 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 248 %j = phi i32 [ %j.next, %inner.loop ], [ %i, %inner.loop.preheader ] 249 250 %within.bounds = icmp ult i32 %j, %length 251 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 252 253 %j.i64 = zext i32 %j to i64 254 %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64 255 %array.j = load i32, i32* %array.j.ptr, align 4 256 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j 257 258 %j.next = add nsw i32 %j, 1 259 %inner.continue = icmp slt i32 %j.next, %l 260 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 261 262outer.loop.inc: 263 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 264 %i.next = add nsw i32 %i, 1 265 %outer.continue = icmp slt i32 %i.next, %n 266 br i1 %outer.continue, label %outer.loop, label %exit 267 268exit: 269 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 270 ret i32 %result 271} 272 273define i32 @cant_expand_guard_check_start(i32* %array, i32 %length, i32 %n, i32 %l, i32 %maybezero) { 274; CHECK-LABEL: @cant_expand_guard_check_start( 275; CHECK-NEXT: entry: 276; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 277; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[OUTER_LOOP_PREHEADER:%.*]] 278; CHECK: outer.loop.preheader: 279; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 280; CHECK: outer.loop: 281; CHECK-NEXT: [[OUTER_LOOP_ACC:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT:%.*]], [[OUTER_LOOP_INC:%.*]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 282; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OUTER_LOOP_INC]] ], [ 0, [[OUTER_LOOP_PREHEADER]] ] 283; CHECK-NEXT: [[TMP6:%.*]] = icmp sle i32 [[L:%.*]], 0 284; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[I]], [[MAYBEZERO:%.*]] 285; CHECK-NEXT: br i1 [[TMP6]], label [[OUTER_LOOP_INC]], label [[INNER_LOOP_PREHEADER:%.*]] 286; CHECK: inner.loop.preheader: 287; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 288; CHECK: inner.loop: 289; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] 290; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ [[DIV]], [[INNER_LOOP_PREHEADER]] ] 291; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]] 292; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 293; CHECK-NEXT: [[J_I64:%.*]] = zext i32 [[J]] to i64 294; CHECK-NEXT: [[ARRAY_J_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[J_I64]] 295; CHECK-NEXT: [[ARRAY_J:%.*]] = load i32, i32* [[ARRAY_J_PTR]], align 4 296; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT]] = add i32 [[INNER_LOOP_ACC]], [[ARRAY_J]] 297; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1 298; CHECK-NEXT: [[INNER_CONTINUE:%.*]] = icmp slt i32 [[J_NEXT]], [[L]] 299; CHECK-NEXT: br i1 [[INNER_CONTINUE]], label [[INNER_LOOP]], label [[OUTER_LOOP_INC_LOOPEXIT:%.*]] 300; CHECK: outer.loop.inc.loopexit: 301; CHECK-NEXT: [[INNER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT]], [[INNER_LOOP]] ] 302; CHECK-NEXT: br label [[OUTER_LOOP_INC]] 303; CHECK: outer.loop.inc: 304; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT]] = phi i32 [ [[OUTER_LOOP_ACC]], [[OUTER_LOOP]] ], [ [[INNER_LOOP_ACC_NEXT_LCSSA]], [[OUTER_LOOP_INC_LOOPEXIT]] ] 305; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 306; CHECK-NEXT: [[OUTER_CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 307; CHECK-NEXT: br i1 [[OUTER_CONTINUE]], label [[OUTER_LOOP]], label [[EXIT_LOOPEXIT:%.*]] 308; CHECK: exit.loopexit: 309; CHECK-NEXT: [[OUTER_LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[OUTER_LOOP_ACC_NEXT]], [[OUTER_LOOP_INC]] ] 310; CHECK-NEXT: br label [[EXIT]] 311; CHECK: exit: 312; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 313; CHECK-NEXT: ret i32 [[RESULT]] 314; 315entry: 316 %tmp5 = icmp sle i32 %n, 0 317 br i1 %tmp5, label %exit, label %outer.loop.preheader 318 319outer.loop.preheader: 320 br label %outer.loop 321 322outer.loop: 323 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 324 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 325 %tmp6 = icmp sle i32 %l, 0 326 %div = udiv i32 %i, %maybezero 327 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 328 329inner.loop.preheader: 330 br label %inner.loop 331 332inner.loop: 333 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 334 %j = phi i32 [ %j.next, %inner.loop ], [ %div, %inner.loop.preheader ] 335 336 %within.bounds = icmp ult i32 %j, %length 337 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 338 339 %j.i64 = zext i32 %j to i64 340 %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64 341 %array.j = load i32, i32* %array.j.ptr, align 4 342 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j 343 344 %j.next = add nsw i32 %j, 1 345 %inner.continue = icmp slt i32 %j.next, %l 346 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 347 348outer.loop.inc: 349 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 350 %i.next = add nsw i32 %i, 1 351 %outer.continue = icmp slt i32 %i.next, %n 352 br i1 %outer.continue, label %outer.loop, label %exit 353 354exit: 355 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 356 ret i32 %result 357} 358