1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -p loop-vectorize -force-vector-width=4 -S %s | FileCheck %s 3 4; Test cases with trip counts containing UDIV expressions for 5; https://github.com/llvm/llvm-project/issues/89958. 6 7define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header(ptr %dst, i64 %N) { 8; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header( 9; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 12; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] 13; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) 14; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 15; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 16; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 17; CHECK: vector.ph: 18; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 19; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 20; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 21; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 22; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 23; CHECK: vector.body: 24; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 25; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 26; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] 27; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 28; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 29; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 30; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 31; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 32; CHECK: middle.block: 33; CHECK-NEXT: br label [[SCALAR_PH]] 34; CHECK: scalar.ph: 35; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 36; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 37; CHECK: loop.header: 38; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 39; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 40; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 41; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 42; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 43; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 44; CHECK: loop.latch: 45; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 46; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 47; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP3:![0-9]+]] 48; CHECK: exit: 49; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 50; CHECK-NEXT: ret i64 [[P]] 51; 52entry: 53 br label %loop.header 54 55loop.header: 56 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 57 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 58 store i32 1, ptr %gep 59 %d = udiv i64 42, %N 60 %c.1 = icmp slt i64 %iv, %d 61 br i1 %c.1, label %loop.latch, label %exit 62 63loop.latch: 64 %iv.next = add i64 %iv, 1 65 %c.0 = icmp slt i64 %iv, %N 66 br i1 %c.0, label %loop.header, label %exit 67 68exit: 69 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 70 ret i64 %p 71} 72 73define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header(ptr %dst, i64 %N) { 74; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header( 75; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 76; CHECK-NEXT: entry: 77; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 78; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 79; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) 80; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 81; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 82; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 83; CHECK: vector.ph: 84; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 85; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 86; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 87; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 88; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 89; CHECK: vector.body: 90; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 91; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 92; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] 93; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 94; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 95; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 96; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 97; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] 98; CHECK: middle.block: 99; CHECK-NEXT: br label [[SCALAR_PH]] 100; CHECK: scalar.ph: 101; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 102; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 103; CHECK: loop.header: 104; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 105; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 106; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 107; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 108; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 109; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 110; CHECK: loop.latch: 111; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 112; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 113; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP5:![0-9]+]] 114; CHECK: exit: 115; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 116; CHECK-NEXT: ret i64 [[P]] 117; 118entry: 119 br label %loop.header 120 121loop.header: 122 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 123 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 124 store i32 1, ptr %gep 125 %d = udiv i64 %N, 42 126 %c.1 = icmp slt i64 %iv, %d 127 br i1 %c.1, label %loop.latch, label %exit 128 129loop.latch: 130 %iv.next = add i64 %iv, 1 131 %c.0 = icmp slt i64 %iv, %N 132 br i1 %c.0, label %loop.header, label %exit 133 134exit: 135 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 136 ret i64 %p 137} 138 139define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally(ptr %A, i64 %N) { 140; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally( 141; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { 142; CHECK-NEXT: entry: 143; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 144; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] 145; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) 146; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 147; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 148; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[ENTRY:%.*]] 149; CHECK: vector.ph: 150; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 151; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 152; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 153; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 154; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 155; CHECK: vector.body: 156; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 157; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[IV]], 0 158; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] 159; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 160; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP6]], align 4 161; CHECK-NEXT: [[TMP7:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], splat (i32 10) 162; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 163; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] 164; CHECK: pred.store.if: 165; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] 166; CHECK-NEXT: store i32 1, ptr [[TMP9]], align 4 167; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] 168; CHECK: pred.store.continue: 169; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 170; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2:%.*]] 171; CHECK: pred.store.if1: 172; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[IV]], 1 173; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] 174; CHECK-NEXT: store i32 1, ptr [[TMP12]], align 4 175; CHECK-NEXT: br label [[PRED_STORE_CONTINUE2]] 176; CHECK: pred.store.continue2: 177; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 178; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]] 179; CHECK: pred.store.if3: 180; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[IV]], 2 181; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP14]] 182; CHECK-NEXT: store i32 1, ptr [[TMP15]], align 4 183; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]] 184; CHECK: pred.store.continue4: 185; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 186; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF5:%.*]], label [[LOOP_LATCH]] 187; CHECK: pred.store.if5: 188; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[IV]], 3 189; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP17]] 190; CHECK-NEXT: store i32 1, ptr [[TMP18]], align 4 191; CHECK-NEXT: br label [[LOOP_LATCH]] 192; CHECK: pred.store.continue6: 193; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 4 194; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[IV_NEXT]], [[N_VEC]] 195; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP6:![0-9]+]] 196; CHECK: middle.block: 197; CHECK-NEXT: br label [[SCALAR_PH]] 198; CHECK: scalar.ph: 199; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY1:%.*]] ] 200; CHECK-NEXT: br label [[LOOP_HEADER1:%.*]] 201; CHECK: loop.header: 202; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT1:%.*]], [[LOOP_LATCH1:%.*]] ] 203; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV1]] 204; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 205; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 206; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[CONTINUE:%.*]] 207; CHECK: then: 208; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 209; CHECK-NEXT: br label [[CONTINUE]] 210; CHECK: continue: 211; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 212; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV1]], [[D]] 213; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH1]], label [[EXIT:%.*]] 214; CHECK: loop.latch: 215; CHECK-NEXT: [[IV_NEXT1]] = add i64 [[IV1]], 1 216; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV1]], [[N]] 217; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER1]], label [[EXIT]], !llvm.loop [[LOOP7:![0-9]+]] 218; CHECK: exit: 219; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[CONTINUE]] ], [ 0, [[LOOP_LATCH1]] ] 220; CHECK-NEXT: ret i64 [[P]] 221; 222entry: 223 br label %loop.header 224 225loop.header: 226 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 227 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 228 %l = load i32, ptr %gep 229 %c.2 = icmp eq i32 %l, 10 230 br i1 %c.2, label %then, label %continue 231 232then: 233 store i32 1, ptr %gep 234 br label %continue 235 236continue: 237 %d = udiv i64 42, %N 238 %c.1 = icmp slt i64 %iv, %d 239 br i1 %c.1, label %loop.latch, label %exit 240 241loop.latch: 242 %iv.next = add i64 %iv, 1 243 %c.0 = icmp slt i64 %iv, %N 244 br i1 %c.0, label %loop.header, label %exit 245 246exit: 247 %p = phi i64 [ 1, %continue ], [ 0, %loop.latch] 248 ret i64 %p 249} 250 251define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally(ptr %A, i64 %N) { 252; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally( 253; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { 254; CHECK-NEXT: entry: 255; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 256; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 257; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) 258; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 259; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 260; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[ENTRY:%.*]] 261; CHECK: vector.ph: 262; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 263; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 264; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 265; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 266; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 267; CHECK: vector.body: 268; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 269; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[IV]], 0 270; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] 271; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 272; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP6]], align 4 273; CHECK-NEXT: [[TMP7:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], splat (i32 10) 274; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 275; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] 276; CHECK: pred.store.if: 277; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] 278; CHECK-NEXT: store i32 1, ptr [[TMP9]], align 4 279; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] 280; CHECK: pred.store.continue: 281; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 282; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2:%.*]] 283; CHECK: pred.store.if1: 284; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[IV]], 1 285; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] 286; CHECK-NEXT: store i32 1, ptr [[TMP12]], align 4 287; CHECK-NEXT: br label [[PRED_STORE_CONTINUE2]] 288; CHECK: pred.store.continue2: 289; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 290; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]] 291; CHECK: pred.store.if3: 292; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[IV]], 2 293; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP14]] 294; CHECK-NEXT: store i32 1, ptr [[TMP15]], align 4 295; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]] 296; CHECK: pred.store.continue4: 297; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 298; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF5:%.*]], label [[LOOP_LATCH]] 299; CHECK: pred.store.if5: 300; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[IV]], 3 301; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP17]] 302; CHECK-NEXT: store i32 1, ptr [[TMP18]], align 4 303; CHECK-NEXT: br label [[LOOP_LATCH]] 304; CHECK: pred.store.continue6: 305; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 4 306; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[IV_NEXT]], [[N_VEC]] 307; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP8:![0-9]+]] 308; CHECK: middle.block: 309; CHECK-NEXT: br label [[SCALAR_PH]] 310; CHECK: scalar.ph: 311; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY1:%.*]] ] 312; CHECK-NEXT: br label [[LOOP_HEADER1:%.*]] 313; CHECK: loop.header: 314; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT1:%.*]], [[LOOP_LATCH1:%.*]] ] 315; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV1]] 316; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 317; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 318; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[CONTINUE:%.*]] 319; CHECK: then: 320; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 321; CHECK-NEXT: br label [[CONTINUE]] 322; CHECK: continue: 323; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 324; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV1]], [[D]] 325; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH1]], label [[EXIT:%.*]] 326; CHECK: loop.latch: 327; CHECK-NEXT: [[IV_NEXT1]] = add i64 [[IV1]], 1 328; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV1]], [[N]] 329; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER1]], label [[EXIT]], !llvm.loop [[LOOP9:![0-9]+]] 330; CHECK: exit: 331; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[CONTINUE]] ], [ 0, [[LOOP_LATCH1]] ] 332; CHECK-NEXT: ret i64 [[P]] 333; 334entry: 335 br label %loop.header 336 337loop.header: 338 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 339 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 340 %l = load i32, ptr %gep 341 %c.2 = icmp eq i32 %l, 10 342 br i1 %c.2, label %then, label %continue 343 344then: 345 store i32 1, ptr %gep 346 br label %continue 347 348continue: 349 %d = udiv i64 %N, 42 350 %c.1 = icmp slt i64 %iv, %d 351 br i1 %c.1, label %loop.latch, label %exit 352 353loop.latch: 354 %iv.next = add i64 %iv, 1 355 %c.0 = icmp slt i64 %iv, %N 356 br i1 %c.0, label %loop.header, label %exit 357 358exit: 359 %p = phi i64 [ 1, %continue ], [ 0, %loop.latch] 360 ret i64 %p 361} 362 363define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally(ptr %A, i64 %N) { 364; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally( 365; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { 366; CHECK-NEXT: entry: 367; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 368; CHECK: loop.header: 369; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 370; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] 371; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 372; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 373; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[LOOP_LATCH]] 374; CHECK: then: 375; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 376; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 377; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 378; CHECK: loop.latch: 379; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 380; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 381; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 382; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]] 383; CHECK: exit: 384; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[THEN]] ], [ 0, [[LOOP_LATCH]] ] 385; CHECK-NEXT: ret i64 [[P]] 386; 387entry: 388 br label %loop.header 389 390loop.header: 391 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 392 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 393 %l = load i32, ptr %gep 394 %c.2 = icmp eq i32 %l, 10 395 br i1 %c.2, label %then, label %loop.latch 396 397then: 398 %d = udiv i64 42, %N 399 %c.1 = icmp slt i64 %iv, %d 400 br i1 %c.1, label %loop.latch, label %exit 401 402loop.latch: 403 store i32 1, ptr %gep 404 %iv.next = add i64 %iv, 1 405 %c.0 = icmp slt i64 %iv, %N 406 br i1 %c.0, label %loop.header, label %exit 407 408exit: 409 %p = phi i64 [ 1, %then ], [ 0, %loop.latch] 410 ret i64 %p 411} 412 413define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally(ptr %A, i64 %N) { 414; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally( 415; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { 416; CHECK-NEXT: entry: 417; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 418; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 419; CHECK: loop.header: 420; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 421; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] 422; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 423; CHECK-NEXT: [[C_2:%.*]] = icmp ne i32 [[L]], 10 424; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 425; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C_2]], i1 true, i1 [[C_1]] 426; CHECK-NEXT: br i1 [[OR_COND]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 427; CHECK: loop.latch: 428; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 429; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 430; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 431; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]] 432; CHECK: exit: 433; CHECK-NEXT: [[P:%.*]] = phi i64 [ 0, [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER]] ] 434; CHECK-NEXT: ret i64 [[P]] 435; 436entry: 437 br label %loop.header 438 439loop.header: 440 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 441 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 442 %l = load i32, ptr %gep 443 %c.2 = icmp eq i32 %l, 10 444 br i1 %c.2, label %then, label %loop.latch 445 446then: 447 %d = udiv i64 %N, 42 448 %c.1 = icmp slt i64 %iv, %d 449 br i1 %c.1, label %loop.latch, label %exit 450 451loop.latch: 452 store i32 1, ptr %gep 453 %iv.next = add i64 %iv, 1 454 %c.0 = icmp slt i64 %iv, %N 455 br i1 %c.0, label %loop.header, label %exit 456 457exit: 458 %p = phi i64 [ 1, %then ], [ 0, %loop.latch] 459 ret i64 %p 460} 461 462define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch(ptr %dst, i64 %N) { 463; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch( 464; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 465; CHECK-NEXT: entry: 466; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1) 467; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[TMP10]] 468; CHECK-NEXT: [[TMP8:%.*]] = freeze i64 [[TMP0]] 469; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 470; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP8]], i64 [[SMAX]]) 471; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 472; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 473; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 474; CHECK: vector.ph: 475; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 476; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 477; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 478; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 479; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 480; CHECK: vector.body: 481; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 482; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 483; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] 484; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 485; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 486; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 487; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 488; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] 489; CHECK: middle.block: 490; CHECK-NEXT: br label [[SCALAR_PH]] 491; CHECK: scalar.ph: 492; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 493; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 494; CHECK: loop.header: 495; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 496; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 497; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 498; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 499; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 500; CHECK: loop.latch: 501; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 502; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 503; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 504; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP11:![0-9]+]] 505; CHECK: exit: 506; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 507; CHECK-NEXT: ret i64 [[P]] 508; 509entry: 510 br label %loop.header 511 512loop.header: 513 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 514 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 515 store i32 1, ptr %gep 516 %c.0 = icmp slt i64 %iv, %N 517 br i1 %c.0, label %loop.latch, label %exit 518 519loop.latch: 520 %iv.next = add i64 %iv, 1 521 %d = udiv i64 42, %N 522 %c.1 = icmp slt i64 %iv, %d 523 br i1 %c.1, label %loop.header, label %exit 524 525exit: 526 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 527 ret i64 %p 528} 529 530declare void @foo() 531 532define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_call_before_loop(ptr %dst, i64 %N) { 533; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_call_before_loop( 534; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 535; CHECK-NEXT: entry: 536; CHECK-NEXT: call void @foo() 537; CHECK-NEXT: [[TMP0:%.*]] = freeze i64 [[N]] 538; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1) 539; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 42, [[TMP1]] 540; CHECK-NEXT: [[TMP3:%.*]] = freeze i64 [[TMP2]] 541; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 542; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP3]], i64 [[SMAX]]) 543; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[UMIN]], 1 544; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP4]], 4 545; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 546; CHECK: vector.ph: 547; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP4]], 4 548; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 549; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 4, i64 [[N_MOD_VF]] 550; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP4]], [[TMP6]] 551; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 552; CHECK: vector.body: 553; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 554; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[INDEX]], 0 555; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP7]] 556; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0 557; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP9]], align 4 558; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 559; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 560; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] 561; CHECK: middle.block: 562; CHECK-NEXT: br label [[SCALAR_PH]] 563; CHECK: scalar.ph: 564; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 565; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 566; CHECK: loop.header: 567; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 568; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 569; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 570; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 571; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 572; CHECK: loop.latch: 573; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 574; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 575; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 576; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP13:![0-9]+]] 577; CHECK: exit: 578; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 579; CHECK-NEXT: ret i64 [[P]] 580; 581entry: 582 call void @foo() 583 br label %loop.header 584 585loop.header: 586 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 587 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 588 store i32 1, ptr %gep 589 %c.0 = icmp slt i64 %iv, %N 590 br i1 %c.0, label %loop.latch, label %exit 591 592loop.latch: 593 %iv.next = add i64 %iv, 1 594 %d = udiv i64 42, %N 595 %c.1 = icmp slt i64 %iv, %d 596 br i1 %c.1, label %loop.header, label %exit 597 598exit: 599 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 600 ret i64 %p 601} 602 603define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_loop_may_not_execute(ptr %dst, i64 %N, i1 %c) { 604; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_loop_may_not_execute( 605; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]], i1 [[C:%.*]]) { 606; CHECK-NEXT: entry: 607; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[EXIT:%.*]] 608; CHECK: loop.header.preheader: 609; CHECK-NEXT: [[TMP0:%.*]] = freeze i64 [[N]] 610; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1) 611; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 42, [[TMP1]] 612; CHECK-NEXT: [[TMP3:%.*]] = freeze i64 [[TMP2]] 613; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 614; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP3]], i64 [[SMAX]]) 615; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[UMIN]], 1 616; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP4]], 4 617; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 618; CHECK: vector.ph: 619; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP4]], 4 620; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 621; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 4, i64 [[N_MOD_VF]] 622; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP4]], [[TMP6]] 623; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 624; CHECK: vector.body: 625; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 626; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[INDEX]], 0 627; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP7]] 628; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0 629; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP9]], align 4 630; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 631; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 632; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]] 633; CHECK: middle.block: 634; CHECK-NEXT: br label [[SCALAR_PH]] 635; CHECK: scalar.ph: 636; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_HEADER_PREHEADER]] ] 637; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 638; CHECK: loop.header: 639; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 640; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 641; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 642; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 643; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT_LOOPEXIT:%.*]] 644; CHECK: loop.latch: 645; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 646; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 647; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 648; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP15:![0-9]+]] 649; CHECK: exit.loopexit: 650; CHECK-NEXT: [[P_PH:%.*]] = phi i64 [ 0, [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER]] ] 651; CHECK-NEXT: br label [[EXIT]] 652; CHECK: exit: 653; CHECK-NEXT: [[P:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[P_PH]], [[EXIT_LOOPEXIT]] ] 654; CHECK-NEXT: ret i64 [[P]] 655; 656entry: 657 br i1 %c, label %loop.header, label %exit 658 659loop.header: 660 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 661 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 662 store i32 1, ptr %gep 663 %c.0 = icmp slt i64 %iv, %N 664 br i1 %c.0, label %loop.latch, label %exit 665 666loop.latch: 667 %iv.next = add i64 %iv, 1 668 %d = udiv i64 42, %N 669 %c.1 = icmp slt i64 %iv, %d 670 br i1 %c.1, label %loop.header, label %exit 671 672exit: 673 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch], [ 2, %entry ] 674 ret i64 %p 675} 676 677define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_different_bounds(ptr %dst, i64 %N, i64 %M) { 678; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch_different_bounds( 679; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]], i64 [[M:%.*]]) { 680; CHECK-NEXT: entry: 681; CHECK-NEXT: [[TMP0:%.*]] = freeze i64 [[M]] 682; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1) 683; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 42, [[TMP1]] 684; CHECK-NEXT: [[TMP3:%.*]] = freeze i64 [[TMP2]] 685; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 686; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP3]], i64 [[SMAX]]) 687; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[UMIN]], 1 688; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP4]], 4 689; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 690; CHECK: vector.ph: 691; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP4]], 4 692; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 693; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 4, i64 [[N_MOD_VF]] 694; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP4]], [[TMP6]] 695; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 696; CHECK: vector.body: 697; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 698; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[INDEX]], 0 699; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP7]] 700; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0 701; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP9]], align 4 702; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 703; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 704; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] 705; CHECK: middle.block: 706; CHECK-NEXT: br label [[SCALAR_PH]] 707; CHECK: scalar.ph: 708; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 709; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 710; CHECK: loop.header: 711; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 712; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 713; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 714; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 715; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 716; CHECK: loop.latch: 717; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 718; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[M]] 719; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 720; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP17:![0-9]+]] 721; CHECK: exit: 722; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 723; CHECK-NEXT: ret i64 [[P]] 724; 725entry: 726 br label %loop.header 727 728loop.header: 729 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 730 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 731 store i32 1, ptr %gep 732 %c.0 = icmp slt i64 %iv, %N 733 br i1 %c.0, label %loop.latch, label %exit 734 735loop.latch: 736 %iv.next = add i64 %iv, 1 737 %d = udiv i64 42, %M 738 %c.1 = icmp slt i64 %iv, %d 739 br i1 %c.1, label %loop.header, label %exit 740 741exit: 742 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 743 ret i64 %p 744} 745 746define i64 @multi_exit_4_exit_count_with_udiv_by_frozen_value_in_latch(ptr %dst, i64 %N) { 747; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_frozen_value_in_latch( 748; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 749; CHECK-NEXT: entry: 750; CHECK-NEXT: [[FR_N:%.*]] = freeze i64 [[N]] 751; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umax.i64(i64 [[FR_N]], i64 1) 752; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 42, [[TMP1]] 753; CHECK-NEXT: [[TMP10:%.*]] = freeze i64 [[TMP2]] 754; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 755; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP10]], i64 [[SMAX]]) 756; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[UMIN]], 1 757; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP3]], 4 758; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 759; CHECK: vector.ph: 760; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4 761; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 762; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] 763; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] 764; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 765; CHECK: vector.body: 766; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 767; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 0 768; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP6]] 769; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i32 0 770; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP8]], align 4 771; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 772; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 773; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]] 774; CHECK: middle.block: 775; CHECK-NEXT: br label [[SCALAR_PH]] 776; CHECK: scalar.ph: 777; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 778; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 779; CHECK: loop.header: 780; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 781; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 782; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 783; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 784; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 785; CHECK: loop.latch: 786; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 787; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[FR_N]] 788; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 789; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP19:![0-9]+]] 790; CHECK: exit: 791; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 792; CHECK-NEXT: ret i64 [[P]] 793; 794entry: 795 %fr.N = freeze i64 %N 796 br label %loop.header 797 798loop.header: 799 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 800 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 801 store i32 1, ptr %gep 802 %c.0 = icmp slt i64 %iv, %N 803 br i1 %c.0, label %loop.latch, label %exit 804 805loop.latch: 806 %iv.next = add i64 %iv, 1 807 %d = udiv i64 42, %fr.N 808 %c.1 = icmp slt i64 %iv, %d 809 br i1 %c.1, label %loop.header, label %exit 810 811exit: 812 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 813 ret i64 %p 814} 815 816 817define i64 @multi_exit_4_exit_count_with_udiv_by_constant_in_latch(ptr %dst, i64 %N) { 818; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_constant_in_latch( 819; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 820; CHECK-NEXT: entry: 821; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 822; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 823; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) 824; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 825; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 826; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 827; CHECK: vector.ph: 828; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 829; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 830; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 831; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 832; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 833; CHECK: vector.body: 834; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[LOOP_HEADER]] ] 835; CHECK-NEXT: [[IV:%.*]] = add i64 [[INDEX]], 0 836; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 837; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[GEP]], i32 0 838; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 839; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 840; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 841; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP20:![0-9]+]] 842; CHECK: middle.block: 843; CHECK-NEXT: br label [[SCALAR_PH]] 844; CHECK: scalar.ph: 845; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 846; CHECK-NEXT: br label [[LOOP_HEADER1:%.*]] 847; CHECK: loop.header: 848; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 849; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV1]] 850; CHECK-NEXT: store i32 1, ptr [[GEP1]], align 4 851; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV1]], [[N]] 852; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 853; CHECK: loop.latch: 854; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV1]], 1 855; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 856; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV1]], [[D]] 857; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER1]], label [[EXIT]], !llvm.loop [[LOOP21:![0-9]+]] 858; CHECK: exit: 859; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER1]] ], [ 0, [[LOOP_LATCH]] ] 860; CHECK-NEXT: ret i64 [[P]] 861; 862entry: 863 br label %loop.header 864 865loop.header: 866 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 867 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 868 store i32 1, ptr %gep 869 %c.0 = icmp slt i64 %iv, %N 870 br i1 %c.0, label %loop.latch, label %exit 871 872loop.latch: 873 %iv.next = add i64 %iv, 1 874 %d = udiv i64 %N, 42 875 %c.1 = icmp slt i64 %iv, %d 876 br i1 %c.1, label %loop.header, label %exit 877 878exit: 879 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 880 ret i64 %p 881} 882 883define void @single_exit_tc_with_udiv(ptr %dst, i64 %N) { 884; CHECK-LABEL: define void @single_exit_tc_with_udiv( 885; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 886; CHECK-NEXT: entry: 887; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] 888; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1 889; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4 890; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 891; CHECK: vector.ph: 892; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 893; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[N_MOD_VF]] 894; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 895; CHECK: vector.body: 896; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 897; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 898; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP2]] 899; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i32 0 900; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP4]], align 4 901; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 902; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 903; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] 904; CHECK: middle.block: 905; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP1]], [[N_VEC]] 906; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] 907; CHECK: scalar.ph: 908; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 909; CHECK-NEXT: br label [[LOOP:%.*]] 910; CHECK: loop: 911; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 912; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 913; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 914; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 915; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 916; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 917; CHECK-NEXT: br i1 [[C_1]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP23:![0-9]+]] 918; CHECK: exit: 919; CHECK-NEXT: ret void 920; 921entry: 922 br label %loop 923 924loop: 925 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 926 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 927 store i32 1, ptr %gep 928 %iv.next = add i64 %iv, 1 929 %d = udiv i64 42, %N 930 %c.1 = icmp slt i64 %iv, %d 931 br i1 %c.1, label %loop, label %exit 932 933exit: 934 ret void 935} 936 937define i64 @multi_exit_4_exit_count_with_urem_by_value_in_latch(ptr %dst, i64 %N) { 938; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_urem_by_value_in_latch( 939; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 940; CHECK-NEXT: entry: 941; CHECK-NEXT: [[TMP12:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1) 942; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[TMP12]] 943; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i64 [[N]], [[TMP0]] 944; CHECK-NEXT: [[TMP2:%.*]] = sub i64 42, [[TMP1]] 945; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) 946; CHECK-NEXT: [[TMP10:%.*]] = freeze i64 [[SMAX1]] 947; CHECK-NEXT: [[SMAX2:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 948; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP10]], i64 [[SMAX2]]) 949; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[UMIN]], 1 950; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP3]], 4 951; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 952; CHECK: vector.ph: 953; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4 954; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 955; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] 956; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] 957; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 958; CHECK: vector.body: 959; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 960; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 0 961; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP6]] 962; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i32 0 963; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP8]], align 4 964; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 965; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 966; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] 967; CHECK: middle.block: 968; CHECK-NEXT: br label [[SCALAR_PH]] 969; CHECK: scalar.ph: 970; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 971; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 972; CHECK: loop.header: 973; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 974; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 975; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 976; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 977; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 978; CHECK: loop.latch: 979; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 980; CHECK-NEXT: [[D:%.*]] = urem i64 42, [[N]] 981; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 982; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP25:![0-9]+]] 983; CHECK: exit: 984; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 985; CHECK-NEXT: ret i64 [[P]] 986; 987entry: 988 br label %loop.header 989 990loop.header: 991 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 992 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 993 store i32 1, ptr %gep 994 %c.0 = icmp slt i64 %iv, %N 995 br i1 %c.0, label %loop.latch, label %exit 996 997loop.latch: 998 %iv.next = add i64 %iv, 1 999 %d = urem i64 42, %N 1000 %c.1 = icmp slt i64 %iv, %d 1001 br i1 %c.1, label %loop.header, label %exit 1002 1003exit: 1004 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1005 ret i64 %p 1006} 1007 1008define i64 @multi_exit_4_exit_count_with_urem_by_constant_in_latch(ptr %dst, i64 %N) { 1009; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_urem_by_constant_in_latch( 1010; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 1011; CHECK-NEXT: entry: 1012; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 1013; CHECK-NEXT: [[TMP0:%.*]] = urem i64 [[N]], 42 1014; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP0]], i64 0) 1015; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[SMAX1]]) 1016; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[UMIN]], 1 1017; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 1018; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 1019; CHECK: vector.ph: 1020; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 1021; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 1022; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 1023; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 1024; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1025; CHECK: vector.body: 1026; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[LOOP_HEADER]] ] 1027; CHECK-NEXT: [[IV:%.*]] = add i64 [[INDEX]], 0 1028; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1029; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[GEP]], i32 0 1030; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 1031; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 1032; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 1033; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP26:![0-9]+]] 1034; CHECK: middle.block: 1035; CHECK-NEXT: br label [[SCALAR_PH]] 1036; CHECK: scalar.ph: 1037; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 1038; CHECK-NEXT: br label [[LOOP_HEADER1:%.*]] 1039; CHECK: loop.header: 1040; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1041; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV1]] 1042; CHECK-NEXT: store i32 1, ptr [[GEP1]], align 4 1043; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV1]], [[N]] 1044; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1045; CHECK: loop.latch: 1046; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV1]], 1 1047; CHECK-NEXT: [[D:%.*]] = urem i64 [[N]], 42 1048; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV1]], [[D]] 1049; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER1]], label [[EXIT]], !llvm.loop [[LOOP27:![0-9]+]] 1050; CHECK: exit: 1051; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER1]] ], [ 0, [[LOOP_LATCH]] ] 1052; CHECK-NEXT: ret i64 [[P]] 1053; 1054entry: 1055 br label %loop.header 1056 1057loop.header: 1058 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1059 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1060 store i32 1, ptr %gep 1061 %c.0 = icmp slt i64 %iv, %N 1062 br i1 %c.0, label %loop.latch, label %exit 1063 1064loop.latch: 1065 %iv.next = add i64 %iv, 1 1066 %d = urem i64 %N, 42 1067 %c.1 = icmp slt i64 %iv, %d 1068 br i1 %c.1, label %loop.header, label %exit 1069 1070exit: 1071 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1072 ret i64 %p 1073} 1074 1075define i64 @multi_exit_4_exit_count_with_srem_by_value_in_latch(ptr %dst, i64 %N) { 1076; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_srem_by_value_in_latch( 1077; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 1078; CHECK-NEXT: entry: 1079; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1080; CHECK: loop.header: 1081; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1082; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1083; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 1084; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 1085; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1086; CHECK: loop.latch: 1087; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 1088; CHECK-NEXT: [[D:%.*]] = srem i64 42, [[N]] 1089; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 1090; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]] 1091; CHECK: exit: 1092; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 1093; CHECK-NEXT: ret i64 [[P]] 1094; 1095entry: 1096 br label %loop.header 1097 1098loop.header: 1099 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1100 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1101 store i32 1, ptr %gep 1102 %c.0 = icmp slt i64 %iv, %N 1103 br i1 %c.0, label %loop.latch, label %exit 1104 1105loop.latch: 1106 %iv.next = add i64 %iv, 1 1107 %d = srem i64 42, %N 1108 %c.1 = icmp slt i64 %iv, %d 1109 br i1 %c.1, label %loop.header, label %exit 1110 1111exit: 1112 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1113 ret i64 %p 1114} 1115 1116define i64 @multi_exit_4_exit_count_with_sdiv_by_value_in_latch(ptr %dst, i64 %N) { 1117; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_sdiv_by_value_in_latch( 1118; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 1119; CHECK-NEXT: entry: 1120; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1121; CHECK: loop.header: 1122; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1123; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1124; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 1125; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 1126; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1127; CHECK: loop.latch: 1128; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 1129; CHECK-NEXT: [[D:%.*]] = sdiv i64 42, [[N]] 1130; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 1131; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]] 1132; CHECK: exit: 1133; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 1134; CHECK-NEXT: ret i64 [[P]] 1135; 1136entry: 1137 br label %loop.header 1138 1139loop.header: 1140 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1141 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1142 store i32 1, ptr %gep 1143 %c.0 = icmp slt i64 %iv, %N 1144 br i1 %c.0, label %loop.latch, label %exit 1145 1146loop.latch: 1147 %iv.next = add i64 %iv, 1 1148 %d = sdiv i64 42, %N 1149 %c.1 = icmp slt i64 %iv, %d 1150 br i1 %c.1, label %loop.header, label %exit 1151 1152exit: 1153 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1154 ret i64 %p 1155} 1156 1157define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch1(ptr %dst, i64 %N) { 1158; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch1( 1159; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 1160; CHECK-NEXT: entry: 1161; CHECK-NEXT: [[TMP8:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1) 1162; CHECK-NEXT: [[TMP9:%.*]] = udiv i64 42, [[TMP8]] 1163; CHECK-NEXT: [[TMP10:%.*]] = freeze i64 [[TMP9]] 1164; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 1165; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP10]], i64 [[SMAX]]) 1166; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 1167; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 1168; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 1169; CHECK: vector.ph: 1170; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 1171; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 1172; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] 1173; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] 1174; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 1175; CHECK: vector.body: 1176; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 1177; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 1178; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] 1179; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 1180; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP6]], align 4 1181; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 1182; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 1183; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] 1184; CHECK: middle.block: 1185; CHECK-NEXT: br label [[SCALAR_PH]] 1186; CHECK: scalar.ph: 1187; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 1188; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1189; CHECK: loop.header: 1190; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1191; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1192; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 1193; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 1194; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1195; CHECK: loop.latch: 1196; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 1197; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] 1198; CHECK-NEXT: [[X:%.*]] = sub i64 100, [[D]] 1199; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 1200; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP29:![0-9]+]] 1201; CHECK: exit: 1202; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 1203; CHECK-NEXT: ret i64 [[P]] 1204; 1205entry: 1206 br label %loop.header 1207 1208loop.header: 1209 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1210 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1211 store i32 1, ptr %gep 1212 %c.0 = icmp slt i64 %iv, %N 1213 br i1 %c.0, label %loop.latch, label %exit 1214 1215loop.latch: 1216 %iv.next = add i64 %iv, 1 1217 %d = udiv i64 42, %N 1218 %x = sub i64 100, %d 1219 %c.1 = icmp slt i64 %iv, %d 1220 br i1 %c.1, label %loop.header, label %exit 1221 1222exit: 1223 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1224 ret i64 %p 1225} 1226 1227define i64 @multi_exit_exit_count_with_udiv_by_0_in_latch(ptr %dst, i64 %N) { 1228; CHECK-LABEL: define i64 @multi_exit_exit_count_with_udiv_by_0_in_latch( 1229; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { 1230; CHECK-NEXT: entry: 1231; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1232; CHECK: loop.header: 1233; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1234; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1235; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 1236; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 1237; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1238; CHECK: loop.latch: 1239; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 1240; CHECK-NEXT: [[D:%.*]] = udiv i64 42, 0 1241; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 1242; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]] 1243; CHECK: exit: 1244; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 1245; CHECK-NEXT: ret i64 [[P]] 1246; 1247entry: 1248 br label %loop.header 1249 1250loop.header: 1251 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1252 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1253 store i32 1, ptr %gep 1254 %c.0 = icmp slt i64 %iv, %N 1255 br i1 %c.0, label %loop.latch, label %exit 1256 1257loop.latch: 1258 %iv.next = add i64 %iv, 1 1259 %d = udiv i64 42, 0 1260 %c.1 = icmp slt i64 %iv, %d 1261 br i1 %c.1, label %loop.header, label %exit 1262 1263exit: 1264 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1265 ret i64 %p 1266} 1267 1268define i64 @multi_exit_count_with_udiv_by_value_in_latch_different_bounds_divisor_non_zero_may_be_poison(ptr %dst, i64 %N, i64 %M) { 1269; CHECK-LABEL: define i64 @multi_exit_count_with_udiv_by_value_in_latch_different_bounds_divisor_non_zero_may_be_poison( 1270; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]], i64 [[M:%.*]]) { 1271; CHECK-NEXT: entry: 1272; CHECK-NEXT: [[M_1:%.*]] = call i64 @llvm.umax.i64(i64 [[M]], i64 1) 1273; CHECK-NEXT: [[TMP9:%.*]] = freeze i64 [[M_1]] 1274; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP9]], i64 1) 1275; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[TMP10]] 1276; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]] 1277; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) 1278; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[SMAX]]) 1279; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[UMIN]], 1 1280; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP2]], 4 1281; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 1282; CHECK: vector.ph: 1283; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP2]], 4 1284; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 1285; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 4, i64 [[N_MOD_VF]] 1286; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP2]], [[TMP4]] 1287; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 1288; CHECK: vector.body: 1289; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 1290; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 0 1291; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP5]] 1292; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0 1293; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP7]], align 4 1294; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 1295; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 1296; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP30:![0-9]+]] 1297; CHECK: middle.block: 1298; CHECK-NEXT: br label [[SCALAR_PH]] 1299; CHECK: scalar.ph: 1300; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 1301; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1302; CHECK: loop.header: 1303; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1304; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] 1305; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 1306; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] 1307; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 1308; CHECK: loop.latch: 1309; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 1310; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[M_1]] 1311; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] 1312; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP31:![0-9]+]] 1313; CHECK: exit: 1314; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] 1315; CHECK-NEXT: ret i64 [[P]] 1316; 1317entry: 1318 %M.1 = call i64 @llvm.umax.i64(i64 %M, i64 1) 1319 br label %loop.header 1320 1321loop.header: 1322 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 1323 %gep = getelementptr inbounds i32, ptr %dst, i64 %iv 1324 store i32 1, ptr %gep 1325 %c.0 = icmp slt i64 %iv, %N 1326 br i1 %c.0, label %loop.latch, label %exit 1327 1328loop.latch: 1329 %iv.next = add i64 %iv, 1 1330 %d = udiv i64 42, %M.1 1331 %c.1 = icmp slt i64 %iv, %d 1332 br i1 %c.1, label %loop.header, label %exit 1333 1334exit: 1335 %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] 1336 ret i64 %p 1337} 1338 1339declare i64 @llvm.umax.i64(i64, i64) 1340 1341 1342;. 1343; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} 1344; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} 1345; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} 1346; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} 1347; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} 1348; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} 1349; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} 1350; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]} 1351; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]} 1352; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META1]]} 1353; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]], [[META2]]} 1354; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META1]]} 1355; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META1]], [[META2]]} 1356; CHECK: [[LOOP13]] = distinct !{[[LOOP13]], [[META2]], [[META1]]} 1357; CHECK: [[LOOP14]] = distinct !{[[LOOP14]], [[META1]], [[META2]]} 1358; CHECK: [[LOOP15]] = distinct !{[[LOOP15]], [[META2]], [[META1]]} 1359; CHECK: [[LOOP16]] = distinct !{[[LOOP16]], [[META1]], [[META2]]} 1360; CHECK: [[LOOP17]] = distinct !{[[LOOP17]], [[META2]], [[META1]]} 1361; CHECK: [[LOOP18]] = distinct !{[[LOOP18]], [[META1]], [[META2]]} 1362; CHECK: [[LOOP19]] = distinct !{[[LOOP19]], [[META2]], [[META1]]} 1363; CHECK: [[LOOP20]] = distinct !{[[LOOP20]], [[META1]], [[META2]]} 1364; CHECK: [[LOOP21]] = distinct !{[[LOOP21]], [[META2]], [[META1]]} 1365; CHECK: [[LOOP22]] = distinct !{[[LOOP22]], [[META1]], [[META2]]} 1366; CHECK: [[LOOP23]] = distinct !{[[LOOP23]], [[META2]], [[META1]]} 1367; CHECK: [[LOOP24]] = distinct !{[[LOOP24]], [[META1]], [[META2]]} 1368; CHECK: [[LOOP25]] = distinct !{[[LOOP25]], [[META2]], [[META1]]} 1369; CHECK: [[LOOP26]] = distinct !{[[LOOP26]], [[META1]], [[META2]]} 1370; CHECK: [[LOOP27]] = distinct !{[[LOOP27]], [[META2]], [[META1]]} 1371; CHECK: [[LOOP28]] = distinct !{[[LOOP28]], [[META1]], [[META2]]} 1372; CHECK: [[LOOP29]] = distinct !{[[LOOP29]], [[META2]], [[META1]]} 1373; CHECK: [[LOOP30]] = distinct !{[[LOOP30]], [[META1]], [[META2]]} 1374; CHECK: [[LOOP31]] = distinct !{[[LOOP31]], [[META2]], [[META1]]} 1375;. 1376