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