1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=thumbv8m.main -indvars -S < %s | FileCheck %s --check-prefix=CHECK-V8M 3; RUN: opt -mtriple=thumbv8a -indvars -S < %s | FileCheck %s --check-prefix=CHECK-V8A 4 5define i32 @remove_loop(i32 %size) #0 { 6; CHECK-V8M-LABEL: @remove_loop( 7; CHECK-V8M-NEXT: entry: 8; CHECK-V8M-NEXT: [[TMP0:%.*]] = add i32 [[SIZE:%.*]], 31 9; CHECK-V8M-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SIZE]], 31 10; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP1]], i32 [[SIZE]], i32 31 11; CHECK-V8M-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[UMIN]] 12; CHECK-V8M-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP2]], 5 13; CHECK-V8M-NEXT: [[TMP4:%.*]] = shl nuw i32 [[TMP3]], 5 14; CHECK-V8M-NEXT: br label [[WHILE_COND:%.*]] 15; CHECK-V8M: while.cond: 16; CHECK-V8M-NEXT: br i1 false, label [[WHILE_COND]], label [[WHILE_END:%.*]] 17; CHECK-V8M: while.end: 18; CHECK-V8M-NEXT: [[TMP5:%.*]] = sub i32 [[SIZE]], [[TMP4]] 19; CHECK-V8M-NEXT: ret i32 [[TMP5]] 20; 21; CHECK-V8A-LABEL: @remove_loop( 22; CHECK-V8A-NEXT: entry: 23; CHECK-V8A-NEXT: [[TMP0:%.*]] = add i32 [[SIZE:%.*]], 31 24; CHECK-V8A-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SIZE]], 31 25; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP1]], i32 [[SIZE]], i32 31 26; CHECK-V8A-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[UMIN]] 27; CHECK-V8A-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP2]], 5 28; CHECK-V8A-NEXT: [[TMP4:%.*]] = shl nuw i32 [[TMP3]], 5 29; CHECK-V8A-NEXT: br label [[WHILE_COND:%.*]] 30; CHECK-V8A: while.cond: 31; CHECK-V8A-NEXT: br i1 false, label [[WHILE_COND]], label [[WHILE_END:%.*]] 32; CHECK-V8A: while.end: 33; CHECK-V8A-NEXT: [[TMP5:%.*]] = sub i32 [[SIZE]], [[TMP4]] 34; CHECK-V8A-NEXT: ret i32 [[TMP5]] 35; 36entry: 37 br label %while.cond 38 39while.cond: ; preds = %while.cond, %entry 40 %size.addr.0 = phi i32 [ %size, %entry ], [ %sub, %while.cond ] 41 %cmp = icmp ugt i32 %size.addr.0, 31 42 %sub = add i32 %size.addr.0, -32 43 br i1 %cmp, label %while.cond, label %while.end 44 45while.end: ; preds = %while.cond 46 %size.lcssa = phi i32 [ %size.addr.0, %while.cond ] 47 ret i32 %size.lcssa 48} 49 50define void @expandOuterRecurrence(i32 %arg) nounwind #0 { 51; CHECK-V8M-LABEL: @expandOuterRecurrence( 52; CHECK-V8M-NEXT: entry: 53; CHECK-V8M-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 54; CHECK-V8M-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 55; CHECK-V8M-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] 56; CHECK-V8M: outer.preheader: 57; CHECK-V8M-NEXT: br label [[OUTER:%.*]] 58; CHECK-V8M: outer: 59; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 60; CHECK-V8M-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 61; CHECK-V8M-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 62; CHECK-V8M-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 63; CHECK-V8M-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 64; CHECK-V8M: inner.ph: 65; CHECK-V8M-NEXT: br label [[INNER:%.*]] 66; CHECK-V8M: inner: 67; CHECK-V8M-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 68; CHECK-V8M: outer.inc.loopexit: 69; CHECK-V8M-NEXT: br label [[OUTER_INC]] 70; CHECK-V8M: outer.inc: 71; CHECK-V8M-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 72; CHECK-V8M-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] 73; CHECK-V8M: exit.loopexit: 74; CHECK-V8M-NEXT: br label [[EXIT]] 75; CHECK-V8M: exit: 76; CHECK-V8M-NEXT: ret void 77; 78; CHECK-V8A-LABEL: @expandOuterRecurrence( 79; CHECK-V8A-NEXT: entry: 80; CHECK-V8A-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 81; CHECK-V8A-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 82; CHECK-V8A-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] 83; CHECK-V8A: outer.preheader: 84; CHECK-V8A-NEXT: br label [[OUTER:%.*]] 85; CHECK-V8A: outer: 86; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 87; CHECK-V8A-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 88; CHECK-V8A-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 89; CHECK-V8A-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 90; CHECK-V8A-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 91; CHECK-V8A: inner.ph: 92; CHECK-V8A-NEXT: br label [[INNER:%.*]] 93; CHECK-V8A: inner: 94; CHECK-V8A-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 95; CHECK-V8A: outer.inc.loopexit: 96; CHECK-V8A-NEXT: br label [[OUTER_INC]] 97; CHECK-V8A: outer.inc: 98; CHECK-V8A-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 99; CHECK-V8A-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] 100; CHECK-V8A: exit.loopexit: 101; CHECK-V8A-NEXT: br label [[EXIT]] 102; CHECK-V8A: exit: 103; CHECK-V8A-NEXT: ret void 104; 105entry: 106 %sub1 = sub nsw i32 %arg, 1 107 %cmp1 = icmp slt i32 0, %sub1 108 br i1 %cmp1, label %outer, label %exit 109 110outer: 111 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 112 %sub2 = sub nsw i32 %arg, %i 113 %sub3 = sub nsw i32 %sub2, 1 114 %cmp2 = icmp slt i32 0, %sub3 115 br i1 %cmp2, label %inner.ph, label %outer.inc 116 117inner.ph: 118 br label %inner 119 120inner: 121 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 122 %j.inc = add nsw i32 %j, 1 123 %cmp3 = icmp slt i32 %j.inc, %sub3 124 br i1 %cmp3, label %inner, label %outer.inc 125 126outer.inc: 127 %i.inc = add nsw i32 %i, 1 128 %cmp4 = icmp slt i32 %i.inc, %sub1 129 br i1 %cmp4, label %outer, label %exit 130 131exit: 132 ret void 133} 134 135define i32 @test1(i32* %array, i32 %length, i32 %n) #0 { 136; CHECK-V8M-LABEL: @test1( 137; CHECK-V8M-NEXT: loop.preheader: 138; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1 139; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1 140; CHECK-V8M-NEXT: [[TMP1:%.*]] = add i32 [[UMAX]], -1 141; CHECK-V8M-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]] 142; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]] 143; CHECK-V8M-NEXT: [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 144; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 145; CHECK-V8M: loop: 146; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 147; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 148; CHECK-V8M-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 149; CHECK-V8M: deopt: 150; CHECK-V8M-NEXT: call void @prevent_merging() 151; CHECK-V8M-NEXT: ret i32 -1 152; CHECK-V8M: guarded: 153; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 154; CHECK-V8M-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 155; CHECK-V8M-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 156; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 157; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 158; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 159; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 160; CHECK-V8M: exit: 161; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 162; CHECK-V8M-NEXT: ret i32 [[RESULT]] 163; 164; CHECK-V8A-LABEL: @test1( 165; CHECK-V8A-NEXT: loop.preheader: 166; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1 167; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1 168; CHECK-V8A-NEXT: [[TMP1:%.*]] = add i32 [[UMAX]], -1 169; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]] 170; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]] 171; CHECK-V8A-NEXT: [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 172; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 173; CHECK-V8A: loop: 174; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 175; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 176; CHECK-V8A-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 177; CHECK-V8A: deopt: 178; CHECK-V8A-NEXT: call void @prevent_merging() 179; CHECK-V8A-NEXT: ret i32 -1 180; CHECK-V8A: guarded: 181; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 182; CHECK-V8A-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 183; CHECK-V8A-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 184; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 185; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 186; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 187; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 188; CHECK-V8A: exit: 189; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 190; CHECK-V8A-NEXT: ret i32 [[RESULT]] 191; 192loop.preheader: ; preds = %entry 193 br label %loop 194 195loop: ; preds = %guarded, %loop.preheader 196 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 197 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 198 %within.bounds = icmp ult i32 %i, %length 199 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 200 201deopt: ; preds = %loop 202 call void @prevent_merging() 203 ret i32 -1 204 205guarded: ; preds = %loop 206 %i.i64 = zext i32 %i to i64 207 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 208 %array.i = load i32, i32* %array.i.ptr, align 4 209 %loop.acc.next = add i32 %loop.acc, %array.i 210 %i.next = add nuw i32 %i, 1 211 %continue = icmp ult i32 %i.next, %n 212 br i1 %continue, label %loop, label %exit 213 214exit: ; preds = %guarded, %entry 215 %result = phi i32 [ %loop.acc.next, %guarded ] 216 ret i32 %result 217} 218 219declare void @maythrow() 220 221define i32 @test2(i32* %array, i32 %length, i32 %n) #0 { 222; CHECK-V8M-LABEL: @test2( 223; CHECK-V8M-NEXT: loop.preheader: 224; CHECK-V8M-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1 225; CHECK-V8M-NEXT: [[TMP1:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP0]] 226; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP1]], i32 [[LENGTH]], i32 [[TMP0]] 227; CHECK-V8M-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 228; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 229; CHECK-V8M: loop: 230; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 231; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 232; CHECK-V8M-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 233; CHECK-V8M: deopt: 234; CHECK-V8M-NEXT: call void @prevent_merging() 235; CHECK-V8M-NEXT: ret i32 -1 236; CHECK-V8M: guarded: 237; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 238; CHECK-V8M-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 239; CHECK-V8M-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 240; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 241; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 242; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] 243; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 244; CHECK-V8M: exit: 245; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 246; CHECK-V8M-NEXT: ret i32 [[RESULT]] 247; 248; CHECK-V8A-LABEL: @test2( 249; CHECK-V8A-NEXT: loop.preheader: 250; CHECK-V8A-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1 251; CHECK-V8A-NEXT: [[TMP1:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP0]] 252; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP1]], i32 [[LENGTH]], i32 [[TMP0]] 253; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 254; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 255; CHECK-V8A: loop: 256; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 257; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 258; CHECK-V8A-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 259; CHECK-V8A: deopt: 260; CHECK-V8A-NEXT: call void @prevent_merging() 261; CHECK-V8A-NEXT: ret i32 -1 262; CHECK-V8A: guarded: 263; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 264; CHECK-V8A-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 265; CHECK-V8A-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 266; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 267; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 268; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] 269; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 270; CHECK-V8A: exit: 271; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 272; CHECK-V8A-NEXT: ret i32 [[RESULT]] 273; 274loop.preheader: ; preds = %entry 275 br label %loop 276 277loop: ; preds = %guarded, %loop.preheader 278 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 279 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 280 %within.bounds = icmp ne i32 %i, %length 281 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 282 283deopt: ; preds = %loop 284 call void @prevent_merging() 285 ret i32 -1 286 287guarded: ; preds = %loop 288 %i.i64 = zext i32 %i to i64 289 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 290 %array.i = load i32, i32* %array.i.ptr, align 4 291 %loop.acc.next = add i32 %loop.acc, %array.i 292 %i.next = add nuw i32 %i, 1 293 %continue = icmp ne i32 %i.next, %n 294 br i1 %continue, label %loop, label %exit 295 296exit: ; preds = %guarded, %entry 297 %result = phi i32 [ %loop.acc.next, %guarded ] 298 ret i32 %result 299} 300 301define i32 @two_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32 %n) #0 { 302; CHECK-V8M-LABEL: @two_range_checks( 303; CHECK-V8M-NEXT: loop.preheader: 304; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]] 305; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 306; CHECK-V8M-NEXT: [[TMP1:%.*]] = icmp ult i32 [[LENGTH_2]], [[LENGTH_1]] 307; CHECK-V8M-NEXT: [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 308; CHECK-V8M-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[N:%.*]], 1 309; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP2]], i32 [[N]], i32 1 310; CHECK-V8M-NEXT: [[TMP3:%.*]] = add i32 [[UMAX]], -1 311; CHECK-V8M-NEXT: [[TMP4:%.*]] = icmp ult i32 [[UMIN1]], [[TMP3]] 312; CHECK-V8M-NEXT: [[UMIN2:%.*]] = select i1 [[TMP4]], i32 [[UMIN1]], i32 [[TMP3]] 313; CHECK-V8M-NEXT: [[TMP5:%.*]] = icmp ne i32 [[UMIN]], [[UMIN2]] 314; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 315; CHECK-V8M: loop: 316; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 317; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 318; CHECK-V8M-NEXT: br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 319; CHECK-V8M: deopt: 320; CHECK-V8M-NEXT: call void @prevent_merging() 321; CHECK-V8M-NEXT: ret i32 -1 322; CHECK-V8M: guarded: 323; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 324; CHECK-V8M-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 325; CHECK-V8M-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 326; CHECK-V8M-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 327; CHECK-V8M-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 328; CHECK-V8M-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 329; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 330; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 331; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 332; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 333; CHECK-V8M: exit: 334; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 335; CHECK-V8M-NEXT: ret i32 [[RESULT]] 336; 337; CHECK-V8A-LABEL: @two_range_checks( 338; CHECK-V8A-NEXT: loop.preheader: 339; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]] 340; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 341; CHECK-V8A-NEXT: [[TMP1:%.*]] = icmp ult i32 [[LENGTH_2]], [[LENGTH_1]] 342; CHECK-V8A-NEXT: [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 343; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[N:%.*]], 1 344; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP2]], i32 [[N]], i32 1 345; CHECK-V8A-NEXT: [[TMP3:%.*]] = add i32 [[UMAX]], -1 346; CHECK-V8A-NEXT: [[TMP4:%.*]] = icmp ult i32 [[UMIN1]], [[TMP3]] 347; CHECK-V8A-NEXT: [[UMIN2:%.*]] = select i1 [[TMP4]], i32 [[UMIN1]], i32 [[TMP3]] 348; CHECK-V8A-NEXT: [[TMP5:%.*]] = icmp ne i32 [[UMIN]], [[UMIN2]] 349; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 350; CHECK-V8A: loop: 351; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 352; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 353; CHECK-V8A-NEXT: br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 354; CHECK-V8A: deopt: 355; CHECK-V8A-NEXT: call void @prevent_merging() 356; CHECK-V8A-NEXT: ret i32 -1 357; CHECK-V8A: guarded: 358; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 359; CHECK-V8A-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 360; CHECK-V8A-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 361; CHECK-V8A-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 362; CHECK-V8A-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 363; CHECK-V8A-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 364; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 365; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 366; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 367; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 368; CHECK-V8A: exit: 369; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 370; CHECK-V8A-NEXT: ret i32 [[RESULT]] 371; 372loop.preheader: ; preds = %entry 373 br label %loop 374 375loop: ; preds = %guarded, %loop.preheader 376 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 377 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 378 %within.bounds.1 = icmp ult i32 %i, %length.1 379 %within.bounds.2 = icmp ult i32 %i, %length.2 380 %within.bounds = and i1 %within.bounds.1, %within.bounds.2 381 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 382 383deopt: ; preds = %loop 384 call void @prevent_merging() 385 ret i32 -1 386 387guarded: ; preds = %loop 388 %i.i64 = zext i32 %i to i64 389 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 390 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 391 %loop.acc.1 = add i32 %loop.acc, %array.1.i 392 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 393 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 394 %loop.acc.next = add i32 %loop.acc.1, %array.2.i 395 %i.next = add nuw i32 %i, 1 396 %continue = icmp ult i32 %i.next, %n 397 br i1 %continue, label %loop, label %exit 398 399exit: ; preds = %guarded, %entry 400 %result = phi i32 [ %loop.acc.next, %guarded ] 401 ret i32 %result 402} 403 404define i32 @three_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) #0 { 405; CHECK-V8M-LABEL: @three_range_checks( 406; CHECK-V8M-NEXT: loop.preheader: 407; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_3:%.*]], [[LENGTH_2:%.*]] 408; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_3]], i32 [[LENGTH_2]] 409; CHECK-V8M-NEXT: [[TMP1:%.*]] = icmp ult i32 [[UMIN]], [[LENGTH_1:%.*]] 410; CHECK-V8M-NEXT: [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[UMIN]], i32 [[LENGTH_1]] 411; CHECK-V8M-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH_3]], [[LENGTH_2]] 412; CHECK-V8M-NEXT: [[UMIN2:%.*]] = select i1 [[TMP2]], i32 [[LENGTH_3]], i32 [[LENGTH_2]] 413; CHECK-V8M-NEXT: [[TMP3:%.*]] = icmp ult i32 [[UMIN2]], [[LENGTH_1]] 414; CHECK-V8M-NEXT: [[UMIN3:%.*]] = select i1 [[TMP3]], i32 [[UMIN2]], i32 [[LENGTH_1]] 415; CHECK-V8M-NEXT: [[TMP4:%.*]] = icmp ugt i32 [[N:%.*]], 1 416; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP4]], i32 [[N]], i32 1 417; CHECK-V8M-NEXT: [[TMP5:%.*]] = add i32 [[UMAX]], -1 418; CHECK-V8M-NEXT: [[TMP6:%.*]] = icmp ult i32 [[UMIN3]], [[TMP5]] 419; CHECK-V8M-NEXT: [[UMIN4:%.*]] = select i1 [[TMP6]], i32 [[UMIN3]], i32 [[TMP5]] 420; CHECK-V8M-NEXT: [[TMP7:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN4]] 421; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 422; CHECK-V8M: loop: 423; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 424; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 425; CHECK-V8M-NEXT: br i1 [[TMP7]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 426; CHECK-V8M: deopt: 427; CHECK-V8M-NEXT: call void @prevent_merging() 428; CHECK-V8M-NEXT: ret i32 -1 429; CHECK-V8M: guarded: 430; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 431; CHECK-V8M-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 432; CHECK-V8M-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 433; CHECK-V8M-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 434; CHECK-V8M-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 435; CHECK-V8M-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 436; CHECK-V8M-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 437; CHECK-V8M-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 438; CHECK-V8M-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 439; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] 440; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 441; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 442; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 443; CHECK-V8M: exit: 444; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 445; CHECK-V8M-NEXT: ret i32 [[RESULT]] 446; 447; CHECK-V8A-LABEL: @three_range_checks( 448; CHECK-V8A-NEXT: loop.preheader: 449; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_3:%.*]], [[LENGTH_2:%.*]] 450; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_3]], i32 [[LENGTH_2]] 451; CHECK-V8A-NEXT: [[TMP1:%.*]] = icmp ult i32 [[UMIN]], [[LENGTH_1:%.*]] 452; CHECK-V8A-NEXT: [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[UMIN]], i32 [[LENGTH_1]] 453; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH_3]], [[LENGTH_2]] 454; CHECK-V8A-NEXT: [[UMIN2:%.*]] = select i1 [[TMP2]], i32 [[LENGTH_3]], i32 [[LENGTH_2]] 455; CHECK-V8A-NEXT: [[TMP3:%.*]] = icmp ult i32 [[UMIN2]], [[LENGTH_1]] 456; CHECK-V8A-NEXT: [[UMIN3:%.*]] = select i1 [[TMP3]], i32 [[UMIN2]], i32 [[LENGTH_1]] 457; CHECK-V8A-NEXT: [[TMP4:%.*]] = icmp ugt i32 [[N:%.*]], 1 458; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP4]], i32 [[N]], i32 1 459; CHECK-V8A-NEXT: [[TMP5:%.*]] = add i32 [[UMAX]], -1 460; CHECK-V8A-NEXT: [[TMP6:%.*]] = icmp ult i32 [[UMIN3]], [[TMP5]] 461; CHECK-V8A-NEXT: [[UMIN4:%.*]] = select i1 [[TMP6]], i32 [[UMIN3]], i32 [[TMP5]] 462; CHECK-V8A-NEXT: [[TMP7:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN4]] 463; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 464; CHECK-V8A: loop: 465; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 466; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 467; CHECK-V8A-NEXT: br i1 [[TMP7]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 468; CHECK-V8A: deopt: 469; CHECK-V8A-NEXT: call void @prevent_merging() 470; CHECK-V8A-NEXT: ret i32 -1 471; CHECK-V8A: guarded: 472; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 473; CHECK-V8A-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 474; CHECK-V8A-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 475; CHECK-V8A-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 476; CHECK-V8A-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 477; CHECK-V8A-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 478; CHECK-V8A-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 479; CHECK-V8A-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 480; CHECK-V8A-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 481; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] 482; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 483; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 484; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 485; CHECK-V8A: exit: 486; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 487; CHECK-V8A-NEXT: ret i32 [[RESULT]] 488; 489loop.preheader: ; preds = %entry 490 br label %loop 491 492loop: ; preds = %guarded, %loop.preheader 493 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 494 %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ] 495 %within.bounds.1 = icmp ult i32 %i, %length.1 496 %within.bounds.2 = icmp ult i32 %i, %length.2 497 %within.bounds.3 = icmp ult i32 %i, %length.3 498 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2 499 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3 500 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 501 502deopt: ; preds = %loop 503 call void @prevent_merging() 504 ret i32 -1 505 506guarded: ; preds = %loop 507 %i.i64 = zext i32 %i to i64 508 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 509 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 510 %loop.acc.1 = add i32 %loop.acc, %array.1.i 511 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 512 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 513 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 514 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 515 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 516 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 517 %i.next = add nuw i32 %i, 1 518 %continue = icmp ult i32 %i.next, %n 519 br i1 %continue, label %loop, label %exit 520 521exit: ; preds = %guarded, %entry 522 %result = phi i32 [ %loop.acc.next, %guarded ] 523 ret i32 %result 524} 525 526; Analogous to the above, but with two distinct branches (on different conditions) 527define i32 @distinct_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) #0 { 528; CHECK-V8M-LABEL: @distinct_checks( 529; CHECK-V8M-NEXT: loop.preheader: 530; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]] 531; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 532; CHECK-V8M-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[N:%.*]], 1 533; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP1]], i32 [[N]], i32 1 534; CHECK-V8M-NEXT: [[TMP2:%.*]] = add i32 [[UMAX]], -1 535; CHECK-V8M-NEXT: [[TMP3:%.*]] = icmp ult i32 [[UMIN]], [[TMP2]] 536; CHECK-V8M-NEXT: [[UMIN1:%.*]] = select i1 [[TMP3]], i32 [[UMIN]], i32 [[TMP2]] 537; CHECK-V8M-NEXT: [[TMP4:%.*]] = icmp ne i32 [[LENGTH_1]], [[UMIN1]] 538; CHECK-V8M-NEXT: [[TMP5:%.*]] = icmp ne i32 [[LENGTH_2]], [[UMIN1]] 539; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 540; CHECK-V8M: loop: 541; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 542; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 543; CHECK-V8M-NEXT: br i1 [[TMP4]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 544; CHECK-V8M: deopt: 545; CHECK-V8M-NEXT: call void @prevent_merging() 546; CHECK-V8M-NEXT: ret i32 -1 547; CHECK-V8M: guarded: 548; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 549; CHECK-V8M-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 550; CHECK-V8M-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 551; CHECK-V8M-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 552; CHECK-V8M-NEXT: br i1 [[TMP5]], label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0 553; CHECK-V8M: deopt2: 554; CHECK-V8M-NEXT: call void @prevent_merging() 555; CHECK-V8M-NEXT: ret i32 -1 556; CHECK-V8M: guarded1: 557; CHECK-V8M-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 558; CHECK-V8M-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 559; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 560; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 561; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 562; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 563; CHECK-V8M: exit: 564; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 565; CHECK-V8M-NEXT: ret i32 [[RESULT]] 566; 567; CHECK-V8A-LABEL: @distinct_checks( 568; CHECK-V8A-NEXT: loop.preheader: 569; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]] 570; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]] 571; CHECK-V8A-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[N:%.*]], 1 572; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP1]], i32 [[N]], i32 1 573; CHECK-V8A-NEXT: [[TMP2:%.*]] = add i32 [[UMAX]], -1 574; CHECK-V8A-NEXT: [[TMP3:%.*]] = icmp ult i32 [[UMIN]], [[TMP2]] 575; CHECK-V8A-NEXT: [[UMIN1:%.*]] = select i1 [[TMP3]], i32 [[UMIN]], i32 [[TMP2]] 576; CHECK-V8A-NEXT: [[TMP4:%.*]] = icmp ne i32 [[LENGTH_1]], [[UMIN1]] 577; CHECK-V8A-NEXT: [[TMP5:%.*]] = icmp ne i32 [[LENGTH_2]], [[UMIN1]] 578; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 579; CHECK-V8A: loop: 580; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 581; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 582; CHECK-V8A-NEXT: br i1 [[TMP4]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 583; CHECK-V8A: deopt: 584; CHECK-V8A-NEXT: call void @prevent_merging() 585; CHECK-V8A-NEXT: ret i32 -1 586; CHECK-V8A: guarded: 587; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 588; CHECK-V8A-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 589; CHECK-V8A-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 590; CHECK-V8A-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 591; CHECK-V8A-NEXT: br i1 [[TMP5]], label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0 592; CHECK-V8A: deopt2: 593; CHECK-V8A-NEXT: call void @prevent_merging() 594; CHECK-V8A-NEXT: ret i32 -1 595; CHECK-V8A: guarded1: 596; CHECK-V8A-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 597; CHECK-V8A-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 598; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 599; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 600; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 601; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 602; CHECK-V8A: exit: 603; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 604; CHECK-V8A-NEXT: ret i32 [[RESULT]] 605; 606loop.preheader: ; preds = %entry 607 br label %loop 608 609loop: ; preds = %guarded4, %loop.preheader 610 %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ] 611 %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ] 612 %within.bounds.1 = icmp ult i32 %i, %length.1 613 br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0 614 615deopt: ; preds = %loop 616 call void @prevent_merging() 617 ret i32 -1 618 619guarded: ; preds = %loop 620 %i.i64 = zext i32 %i to i64 621 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 622 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 623 %loop.acc.1 = add i32 %loop.acc, %array.1.i 624 %within.bounds.2 = icmp ult i32 %i, %length.2 625 br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0 626 627deopt2: ; preds = %guarded 628 call void @prevent_merging() 629 ret i32 -1 630 631guarded1: ; preds = %guarded1 632 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 633 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 634 %loop.acc.next = add i32 %loop.acc.1, %array.3.i 635 %i.next = add nuw i32 %i, 1 636 %continue = icmp ult i32 %i.next, %n 637 br i1 %continue, label %loop, label %exit 638 639exit: 640 %result = phi i32 [ %loop.acc.next, %guarded1 ] 641 ret i32 %result 642} 643 644define i32 @duplicate_checks(i32* %array.1, i32* %array.2, i32* %array.3, i32 %length, i32 %n) #0 { 645; CHECK-V8M-LABEL: @duplicate_checks( 646; CHECK-V8M-NEXT: loop.preheader: 647; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1 648; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1 649; CHECK-V8M-NEXT: [[TMP1:%.*]] = add i32 [[UMAX]], -1 650; CHECK-V8M-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]] 651; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]] 652; CHECK-V8M-NEXT: [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 653; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 654; CHECK-V8M: loop: 655; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 656; CHECK-V8M-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 657; CHECK-V8M-NEXT: br i1 [[TMP3]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 658; CHECK-V8M: deopt: 659; CHECK-V8M-NEXT: call void @prevent_merging() 660; CHECK-V8M-NEXT: ret i32 -1 661; CHECK-V8M: guarded: 662; CHECK-V8M-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 663; CHECK-V8M-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 664; CHECK-V8M-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 665; CHECK-V8M-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 666; CHECK-V8M-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0 667; CHECK-V8M: deopt2: 668; CHECK-V8M-NEXT: call void @prevent_merging() 669; CHECK-V8M-NEXT: ret i32 -1 670; CHECK-V8M: guarded1: 671; CHECK-V8M-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 672; CHECK-V8M-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 673; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 674; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 675; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 676; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 677; CHECK-V8M: exit: 678; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 679; CHECK-V8M-NEXT: ret i32 [[RESULT]] 680; 681; CHECK-V8A-LABEL: @duplicate_checks( 682; CHECK-V8A-NEXT: loop.preheader: 683; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1 684; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1 685; CHECK-V8A-NEXT: [[TMP1:%.*]] = add i32 [[UMAX]], -1 686; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]] 687; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]] 688; CHECK-V8A-NEXT: [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]] 689; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 690; CHECK-V8A: loop: 691; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 692; CHECK-V8A-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ] 693; CHECK-V8A-NEXT: br i1 [[TMP3]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 694; CHECK-V8A: deopt: 695; CHECK-V8A-NEXT: call void @prevent_merging() 696; CHECK-V8A-NEXT: ret i32 -1 697; CHECK-V8A: guarded: 698; CHECK-V8A-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 699; CHECK-V8A-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 700; CHECK-V8A-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 701; CHECK-V8A-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 702; CHECK-V8A-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0 703; CHECK-V8A: deopt2: 704; CHECK-V8A-NEXT: call void @prevent_merging() 705; CHECK-V8A-NEXT: ret i32 -1 706; CHECK-V8A: guarded1: 707; CHECK-V8A-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 708; CHECK-V8A-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 709; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]] 710; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 711; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 712; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 713; CHECK-V8A: exit: 714; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ] 715; CHECK-V8A-NEXT: ret i32 [[RESULT]] 716; 717loop.preheader: ; preds = %entry 718 br label %loop 719 720loop: ; preds = %guarded4, %loop.preheader 721 %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ] 722 %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ] 723 %within.bounds.1 = icmp ult i32 %i, %length 724 br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0 725 726deopt: ; preds = %loop 727 call void @prevent_merging() 728 ret i32 -1 729 730guarded: ; preds = %loop 731 %i.i64 = zext i32 %i to i64 732 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 733 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 734 %loop.acc.1 = add i32 %loop.acc, %array.1.i 735 %within.bounds.2 = icmp ult i32 %i, %length 736 br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0 737 738deopt2: ; preds = %guarded 739 call void @prevent_merging() 740 ret i32 -1 741 742guarded1: ; preds = %guarded1 743 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 744 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 745 %loop.acc.next = add i32 %loop.acc.1, %array.3.i 746 %i.next = add nuw i32 %i, 1 747 %continue = icmp ult i32 %i.next, %n 748 br i1 %continue, label %loop, label %exit 749 750exit: 751 %result = phi i32 [ %loop.acc.next, %guarded1 ] 752 ret i32 %result 753} 754 755; Demonstrate that this approach works with IVs of different steps, and types 756; This version uses a manually lftred exit condition to work around an issue described 757; in detail on next test. 758define i32 @different_ivs(i32* %array, i32 %length, i32 %n) #0 { 759; CHECK-V8M-LABEL: @different_ivs( 760; CHECK-V8M-NEXT: loop.preheader: 761; CHECK-V8M-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64 762; CHECK-V8M-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[N64]], 1 763; CHECK-V8M-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i64 [[N64]], i64 1 764; CHECK-V8M-NEXT: [[TMP1:%.*]] = add nsw i64 [[UMAX]], -1 765; CHECK-V8M-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64 766; CHECK-V8M-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] 767; CHECK-V8M-NEXT: [[UMIN:%.*]] = select i1 [[TMP3]], i64 [[TMP1]], i64 [[TMP2]] 768; CHECK-V8M-NEXT: [[TMP4:%.*]] = zext i32 [[LENGTH]] to i64 769; CHECK-V8M-NEXT: [[TMP5:%.*]] = icmp ne i64 [[TMP4]], [[UMIN]] 770; CHECK-V8M-NEXT: br label [[LOOP:%.*]] 771; CHECK-V8M: loop: 772; CHECK-V8M-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 773; CHECK-V8M-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 774; CHECK-V8M-NEXT: br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 775; CHECK-V8M: deopt: 776; CHECK-V8M-NEXT: call void @prevent_merging() 777; CHECK-V8M-NEXT: ret i32 -1 778; CHECK-V8M: guarded: 779; CHECK-V8M-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]] 780; CHECK-V8M-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 781; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 782; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1 783; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]] 784; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 785; CHECK-V8M: exit: 786; CHECK-V8M-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 787; CHECK-V8M-NEXT: ret i32 [[RESULT]] 788; 789; CHECK-V8A-LABEL: @different_ivs( 790; CHECK-V8A-NEXT: loop.preheader: 791; CHECK-V8A-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64 792; CHECK-V8A-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[N64]], 1 793; CHECK-V8A-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i64 [[N64]], i64 1 794; CHECK-V8A-NEXT: [[TMP1:%.*]] = add nsw i64 [[UMAX]], -1 795; CHECK-V8A-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64 796; CHECK-V8A-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] 797; CHECK-V8A-NEXT: [[UMIN:%.*]] = select i1 [[TMP3]], i64 [[TMP1]], i64 [[TMP2]] 798; CHECK-V8A-NEXT: [[TMP4:%.*]] = zext i32 [[LENGTH]] to i64 799; CHECK-V8A-NEXT: [[TMP5:%.*]] = icmp ne i64 [[TMP4]], [[UMIN]] 800; CHECK-V8A-NEXT: br label [[LOOP:%.*]] 801; CHECK-V8A: loop: 802; CHECK-V8A-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 803; CHECK-V8A-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] 804; CHECK-V8A-NEXT: br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0 805; CHECK-V8A: deopt: 806; CHECK-V8A-NEXT: call void @prevent_merging() 807; CHECK-V8A-NEXT: ret i32 -1 808; CHECK-V8A: guarded: 809; CHECK-V8A-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]] 810; CHECK-V8A-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 811; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 812; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1 813; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]] 814; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 815; CHECK-V8A: exit: 816; CHECK-V8A-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ] 817; CHECK-V8A-NEXT: ret i32 [[RESULT]] 818; 819loop.preheader: 820 %j.start = sub nuw nsw i32 %length, 1 821 %n64 = zext i32 %n to i64 822 br label %loop 823 824loop: 825 %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ] 826 %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ] 827 %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ] 828 %within.bounds = icmp ne i32 %j, -1 829 br i1 %within.bounds, label %guarded, label %deopt, !prof !0 830 831deopt: 832 call void @prevent_merging() 833 ret i32 -1 834 835guarded: 836 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i 837 %array.i = load i32, i32* %array.i.ptr, align 4 838 %loop.acc.next = add i32 %loop.acc, %array.i 839 %i.next = add nuw i64 %i, 1 840 %j.next = sub nuw i32 %j, 1 841 %continue = icmp ult i64 %i.next, %n64 842 br i1 %continue, label %loop, label %exit 843 844exit: 845 %result = phi i32 [ %loop.acc.next, %guarded ] 846 ret i32 %result 847} 848 849declare void @prevent_merging() 850declare void @call() 851 852!0 = !{!"branch_weights", i32 1048576, i32 1} 853!1 = !{i32 1, i32 -2147483648} 854!2 = !{i32 0, i32 50} 855 856attributes #0 = { minsize optsize } 857