1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S < %s -p loop-vectorize -enable-early-exit-vectorization -force-vector-width=4 | FileCheck %s 3 4declare void @init_mem(ptr, i64); 5 6define i64 @same_exit_block_pre_inc_use1() { 7; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1() { 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 10; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 11; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 12; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 13; CHECK-NEXT: br label [[LOOP:%.*]] 14; CHECK: loop: 15; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 16; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 17; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 18; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 19; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 20; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 21; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 22; CHECK: loop.inc: 23; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 24; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 25; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 26; CHECK: loop.end: 27; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 28; CHECK-NEXT: ret i64 [[RETVAL]] 29; 30entry: 31 %p1 = alloca [1024 x i8] 32 %p2 = alloca [1024 x i8] 33 call void @init_mem(ptr %p1, i64 1024) 34 call void @init_mem(ptr %p2, i64 1024) 35 br label %loop 36 37loop: 38 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 39 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 40 %ld1 = load i8, ptr %arrayidx, align 1 41 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 42 %ld2 = load i8, ptr %arrayidx1, align 1 43 %cmp3 = icmp eq i8 %ld1, %ld2 44 br i1 %cmp3, label %loop.inc, label %loop.end 45 46loop.inc: 47 %index.next = add i64 %index, 1 48 %exitcond = icmp ne i64 %index.next, 67 49 br i1 %exitcond, label %loop, label %loop.end 50 51loop.end: 52 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 53 ret i64 %retval 54} 55 56 57define i64 @same_exit_block_pre_inc1_use_inv_cond(i1 %cond) { 58; CHECK-LABEL: define i64 @same_exit_block_pre_inc1_use_inv_cond( 59; CHECK-SAME: i1 [[COND:%.*]]) { 60; CHECK-NEXT: entry: 61; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 62; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 63; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 64; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 65; CHECK-NEXT: br label [[LOOP:%.*]] 66; CHECK: loop: 67; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 68; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 69; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 70; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 71; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 72; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 73; CHECK-NEXT: [[CMP4:%.*]] = select i1 [[COND]], i1 [[CMP3]], i1 false 74; CHECK-NEXT: br i1 [[CMP4]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 75; CHECK: loop.inc: 76; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 77; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 78; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 79; CHECK: loop.end: 80; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 81; CHECK-NEXT: ret i64 [[RETVAL]] 82; 83entry: 84 %p1 = alloca [1024 x i8] 85 %p2 = alloca [1024 x i8] 86 call void @init_mem(ptr %p1, i64 1024) 87 call void @init_mem(ptr %p2, i64 1024) 88 br label %loop 89 90loop: 91 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 92 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 93 %ld1 = load i8, ptr %arrayidx, align 1 94 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 95 %ld2 = load i8, ptr %arrayidx1, align 1 96 %cmp3 = icmp eq i8 %ld1, %ld2 97 %cmp4 = select i1 %cond, i1 %cmp3, i1 false 98 br i1 %cmp4, label %loop.inc, label %loop.end 99 100loop.inc: 101 %index.next = add i64 %index, 1 102 %exitcond = icmp ne i64 %index.next, 67 103 br i1 %exitcond, label %loop, label %loop.end 104 105loop.end: 106 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 107 ret i64 %retval 108} 109 110 111define i64 @same_exit_block_pre_inc_use1_gep_two_indices() { 112; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_gep_two_indices() { 113; CHECK-NEXT: entry: 114; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 115; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 116; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 117; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 118; CHECK-NEXT: br label [[LOOP:%.*]] 119; CHECK: loop: 120; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 121; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr [[P1]], i64 0, i64 [[INDEX]] 122; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 123; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[P2]], i64 0, i64 [[INDEX]] 124; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 125; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 126; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 127; CHECK: loop.inc: 128; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 129; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 130; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 131; CHECK: loop.end: 132; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 133; CHECK-NEXT: ret i64 [[RETVAL]] 134; 135entry: 136 %p1 = alloca [1024 x i8] 137 %p2 = alloca [1024 x i8] 138 call void @init_mem(ptr %p1, i64 1024) 139 call void @init_mem(ptr %p2, i64 1024) 140 br label %loop 141 142loop: 143 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 144 %arrayidx = getelementptr inbounds [1024 x i8], ptr %p1, i64 0, i64 %index 145 %ld1 = load i8, ptr %arrayidx, align 1 146 %arrayidx1 = getelementptr inbounds [1024 x i8], ptr %p2, i64 0, i64 %index 147 %ld2 = load i8, ptr %arrayidx1, align 1 148 %cmp3 = icmp eq i8 %ld1, %ld2 149 br i1 %cmp3, label %loop.inc, label %loop.end 150 151loop.inc: 152 %index.next = add i64 %index, 1 153 %exitcond = icmp ne i64 %index.next, 67 154 br i1 %exitcond, label %loop, label %loop.end 155 156loop.end: 157 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 158 ret i64 %retval 159} 160 161 162define i64 @same_exit_block_pre_inc_use1_alloca_diff_type() { 163; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_alloca_diff_type() { 164; CHECK-NEXT: entry: 165; CHECK-NEXT: [[P1:%.*]] = alloca [40 x i32], align 4 166; CHECK-NEXT: [[P2:%.*]] = alloca [40 x i32], align 4 167; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 168; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 169; CHECK-NEXT: br label [[LOOP:%.*]] 170; CHECK: loop: 171; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 172; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 173; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 174; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 175; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 176; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 177; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 178; CHECK: loop.inc: 179; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 180; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 181; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 182; CHECK: loop.end: 183; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 184; CHECK-NEXT: ret i64 [[RETVAL]] 185; 186entry: 187 %p1 = alloca [40 x i32] 188 %p2 = alloca [40 x i32] 189 call void @init_mem(ptr %p1, i64 1024) 190 call void @init_mem(ptr %p2, i64 1024) 191 br label %loop 192 193loop: 194 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 195 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 196 %ld1 = load i8, ptr %arrayidx, align 1 197 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 198 %ld2 = load i8, ptr %arrayidx1, align 1 199 %cmp3 = icmp eq i8 %ld1, %ld2 200 br i1 %cmp3, label %loop.inc, label %loop.end 201 202loop.inc: 203 %index.next = add i64 %index, 1 204 %exitcond = icmp ne i64 %index.next, 67 205 br i1 %exitcond, label %loop, label %loop.end 206 207loop.end: 208 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 209 ret i64 %retval 210} 211 212 213define i64 @same_exit_block_pre_inc_use2() { 214; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use2() { 215; CHECK-NEXT: entry: 216; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 217; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 218; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 219; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 220; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 221; CHECK: vector.ph: 222; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 223; CHECK: vector.body: 224; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VECTOR_BODY]] ] 225; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 3, i64 4, i64 5, i64 6>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] 226; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 3, [[INDEX1]] 227; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 228; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[TMP0]] 229; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i32 0 230; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP2]], align 1 231; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[TMP0]] 232; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 0 233; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i8>, ptr [[TMP4]], align 1 234; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], [[WIDE_LOAD2]] 235; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX1]], 4 236; CHECK-NEXT: [[TMP6:%.*]] = xor <4 x i1> [[TMP5]], splat (i1 true) 237; CHECK-NEXT: [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP6]]) 238; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 64 239; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4) 240; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP7]], [[TMP8]] 241; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_SPLIT:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 242; CHECK: middle.split: 243; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 3 244; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP_END:%.*]], label [[MIDDLE_BLOCK:%.*]] 245; CHECK: middle.block: 246; CHECK-NEXT: br i1 true, label [[LOOP_END]], label [[SCALAR_PH]] 247; CHECK: scalar.ph: 248; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 67, [[MIDDLE_BLOCK]] ], [ 3, [[ENTRY:%.*]] ] 249; CHECK-NEXT: br label [[LOOP:%.*]] 250; CHECK: loop: 251; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 252; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 253; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 254; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 255; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 256; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 257; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END]] 258; CHECK: loop.inc: 259; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 260; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 261; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]], !llvm.loop [[LOOP3:![0-9]+]] 262; CHECK: loop.end: 263; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 67, [[LOOP]] ], [ [[INDEX]], [[LOOP_INC]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 67, [[MIDDLE_SPLIT]] ] 264; CHECK-NEXT: ret i64 [[RETVAL]] 265; 266entry: 267 %p1 = alloca [1024 x i8] 268 %p2 = alloca [1024 x i8] 269 call void @init_mem(ptr %p1, i64 1024) 270 call void @init_mem(ptr %p2, i64 1024) 271 br label %loop 272 273loop: 274 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 275 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 276 %ld1 = load i8, ptr %arrayidx, align 1 277 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 278 %ld2 = load i8, ptr %arrayidx1, align 1 279 %cmp3 = icmp eq i8 %ld1, %ld2 280 br i1 %cmp3, label %loop.inc, label %loop.end 281 282loop.inc: 283 %index.next = add i64 %index, 1 284 %exitcond = icmp ne i64 %index.next, 67 285 br i1 %exitcond, label %loop, label %loop.end 286 287loop.end: 288 %retval = phi i64 [ 67, %loop ], [ %index, %loop.inc ] 289 ret i64 %retval 290} 291 292 293define i64 @same_exit_block_pre_inc_use3() { 294; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use3() { 295; CHECK-NEXT: entry: 296; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 297; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 298; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 299; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 300; CHECK-NEXT: br label [[LOOP:%.*]] 301; CHECK: loop: 302; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 303; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 304; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 305; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 306; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 307; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 308; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 309; CHECK: loop.inc: 310; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 311; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 312; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 313; CHECK: loop.end: 314; CHECK-NEXT: [[INDEX_LCSSA:%.*]] = phi i64 [ [[INDEX]], [[LOOP_INC]] ], [ [[INDEX]], [[LOOP]] ] 315; CHECK-NEXT: ret i64 [[INDEX_LCSSA]] 316; 317entry: 318 %p1 = alloca [1024 x i8] 319 %p2 = alloca [1024 x i8] 320 call void @init_mem(ptr %p1, i64 1024) 321 call void @init_mem(ptr %p2, i64 1024) 322 br label %loop 323 324loop: 325 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 326 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 327 %ld1 = load i8, ptr %arrayidx, align 1 328 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 329 %ld2 = load i8, ptr %arrayidx1, align 1 330 %cmp3 = icmp eq i8 %ld1, %ld2 331 br i1 %cmp3, label %loop.inc, label %loop.end 332 333loop.inc: 334 %index.next = add i64 %index, 1 335 %exitcond = icmp ne i64 %index.next, 67 336 br i1 %exitcond, label %loop, label %loop.end 337 338loop.end: 339 ret i64 %index 340} 341 342 343; In this example the early exit block appears in the list of ExitNotTaken 344; SCEVs, but is not computable. 345define i64 @same_exit_block_pre_inc_use4() { 346; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use4() { 347; CHECK-NEXT: entry: 348; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i64], align 8 349; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i64], align 8 350; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 351; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 352; CHECK-NEXT: br label [[LOOP:%.*]] 353; CHECK: loop: 354; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 355; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[P1]], i64 [[INDEX]] 356; CHECK-NEXT: [[LD1:%.*]] = load i64, ptr [[ARRAYIDX]], align 1 357; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i64 [[INDEX]], [[LD1]] 358; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 359; CHECK: loop.inc: 360; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 361; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 362; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 363; CHECK: loop.end: 364; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 365; CHECK-NEXT: ret i64 [[RETVAL]] 366; 367entry: 368 %p1 = alloca [1024 x i64] 369 %p2 = alloca [1024 x i64] 370 call void @init_mem(ptr %p1, i64 1024) 371 call void @init_mem(ptr %p2, i64 1024) 372 br label %loop 373 374loop: 375 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 376 %arrayidx = getelementptr inbounds i64, ptr %p1, i64 %index 377 %ld1 = load i64, ptr %arrayidx, align 1 378 %cmp3 = icmp ult i64 %index, %ld1 379 br i1 %cmp3, label %loop.inc, label %loop.end 380 381loop.inc: 382 %index.next = add i64 %index, 1 383 %exitcond = icmp ne i64 %index.next, 67 384 br i1 %exitcond, label %loop, label %loop.end 385 386loop.end: 387 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 388 ret i64 %retval 389} 390 391 392define i64 @same_exit_block_post_inc_use() { 393; CHECK-LABEL: define i64 @same_exit_block_post_inc_use() { 394; CHECK-NEXT: entry: 395; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 396; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 397; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 398; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 399; CHECK-NEXT: br label [[LOOP:%.*]] 400; CHECK: loop: 401; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 402; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 403; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 404; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 405; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 406; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 407; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 408; CHECK: loop.inc: 409; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 410; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 411; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 412; CHECK: loop.end: 413; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ [[INDEX_NEXT]], [[LOOP_INC]] ] 414; CHECK-NEXT: ret i64 [[RETVAL]] 415; 416entry: 417 %p1 = alloca [1024 x i8] 418 %p2 = alloca [1024 x i8] 419 call void @init_mem(ptr %p1, i64 1024) 420 call void @init_mem(ptr %p2, i64 1024) 421 br label %loop 422 423loop: 424 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 425 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 426 %ld1 = load i8, ptr %arrayidx, align 1 427 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 428 %ld2 = load i8, ptr %arrayidx1, align 1 429 %cmp3 = icmp eq i8 %ld1, %ld2 430 br i1 %cmp3, label %loop.inc, label %loop.end 431 432loop.inc: 433 %index.next = add i64 %index, 1 434 %exitcond = icmp ne i64 %index.next, 67 435 br i1 %exitcond, label %loop, label %loop.end 436 437loop.end: 438 %retval = phi i64 [ %index, %loop ], [ %index.next, %loop.inc ] 439 ret i64 %retval 440} 441 442 443define i64 @same_exit_block_post_inc_use2() { 444; CHECK-LABEL: define i64 @same_exit_block_post_inc_use2() { 445; CHECK-NEXT: entry: 446; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 447; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 448; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 449; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 450; CHECK-NEXT: br label [[LOOP:%.*]] 451; CHECK: loop: 452; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 453; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 454; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 455; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 456; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 457; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 458; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 459; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 460; CHECK: loop.inc: 461; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 462; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 463; CHECK: loop.end: 464; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX_NEXT]], [[LOOP]] ], [ [[INDEX]], [[LOOP_INC]] ] 465; CHECK-NEXT: ret i64 [[RETVAL]] 466; 467entry: 468 %p1 = alloca [1024 x i8] 469 %p2 = alloca [1024 x i8] 470 call void @init_mem(ptr %p1, i64 1024) 471 call void @init_mem(ptr %p2, i64 1024) 472 br label %loop 473 474loop: 475 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 476 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 477 %ld1 = load i8, ptr %arrayidx, align 1 478 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 479 %ld2 = load i8, ptr %arrayidx1, align 1 480 %index.next = add i64 %index, 1 481 %cmp3 = icmp eq i8 %ld1, %ld2 482 br i1 %cmp3, label %loop.inc, label %loop.end 483 484loop.inc: 485 %exitcond = icmp ne i64 %index.next, 67 486 br i1 %exitcond, label %loop, label %loop.end 487 488loop.end: 489 %retval = phi i64 [ %index.next, %loop ], [ %index, %loop.inc ] 490 ret i64 %retval 491} 492 493 494define i64 @diff_exit_block_pre_inc_use1() { 495; CHECK-LABEL: define i64 @diff_exit_block_pre_inc_use1() { 496; CHECK-NEXT: entry: 497; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 498; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 499; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 500; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 501; CHECK-NEXT: br label [[LOOP:%.*]] 502; CHECK: loop: 503; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 504; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 505; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 506; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 507; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 508; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 509; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_EARLY_EXIT:%.*]] 510; CHECK: loop.inc: 511; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 512; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 513; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END:%.*]] 514; CHECK: loop.early.exit: 515; CHECK-NEXT: [[RETVAL1:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ] 516; CHECK-NEXT: ret i64 [[RETVAL1]] 517; CHECK: loop.end: 518; CHECK-NEXT: [[RETVAL2:%.*]] = phi i64 [ 67, [[LOOP_INC]] ] 519; CHECK-NEXT: ret i64 [[RETVAL2]] 520; 521entry: 522 %p1 = alloca [1024 x i8] 523 %p2 = alloca [1024 x i8] 524 call void @init_mem(ptr %p1, i64 1024) 525 call void @init_mem(ptr %p2, i64 1024) 526 br label %loop 527 528loop: 529 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 530 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 531 %ld1 = load i8, ptr %arrayidx, align 1 532 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 533 %ld2 = load i8, ptr %arrayidx1, align 1 534 %cmp3 = icmp eq i8 %ld1, %ld2 535 br i1 %cmp3, label %loop.inc, label %loop.early.exit 536 537loop.inc: 538 %index.next = add i64 %index, 1 539 %exitcond = icmp ne i64 %index.next, 67 540 br i1 %exitcond, label %loop, label %loop.end 541 542loop.early.exit: 543 %retval1 = phi i64 [ %index, %loop ] 544 ret i64 %retval1 545 546loop.end: 547 %retval2 = phi i64 [ 67, %loop.inc ] 548 ret i64 %retval2 549} 550 551 552define i64 @diff_exit_block_pre_inc_use2() { 553; CHECK-LABEL: define i64 @diff_exit_block_pre_inc_use2() { 554; CHECK-NEXT: entry: 555; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 556; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 557; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 558; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 559; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 560; CHECK: vector.ph: 561; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 562; CHECK: vector.body: 563; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VECTOR_BODY]] ] 564; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 3, i64 4, i64 5, i64 6>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] 565; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 3, [[INDEX1]] 566; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 567; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[TMP0]] 568; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i32 0 569; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP2]], align 1 570; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[TMP0]] 571; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 0 572; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i8>, ptr [[TMP4]], align 1 573; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], [[WIDE_LOAD2]] 574; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX1]], 4 575; CHECK-NEXT: [[TMP6:%.*]] = xor <4 x i1> [[TMP5]], splat (i1 true) 576; CHECK-NEXT: [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP6]]) 577; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 64 578; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4) 579; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP7]], [[TMP8]] 580; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_SPLIT:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] 581; CHECK: middle.split: 582; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP_EARLY_EXIT:%.*]], label [[MIDDLE_BLOCK:%.*]] 583; CHECK: middle.block: 584; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 3 585; CHECK-NEXT: br i1 true, label [[LOOP_END:%.*]], label [[SCALAR_PH]] 586; CHECK: scalar.ph: 587; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 67, [[MIDDLE_BLOCK]] ], [ 3, [[ENTRY:%.*]] ] 588; CHECK-NEXT: br label [[LOOP:%.*]] 589; CHECK: loop: 590; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 591; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 592; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 593; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 594; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 595; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 596; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_EARLY_EXIT]] 597; CHECK: loop.inc: 598; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 599; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 600; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]], !llvm.loop [[LOOP5:![0-9]+]] 601; CHECK: loop.early.exit: 602; CHECK-NEXT: [[RETVAL1:%.*]] = phi i64 [ 67, [[LOOP]] ], [ 67, [[MIDDLE_SPLIT]] ] 603; CHECK-NEXT: ret i64 [[RETVAL1]] 604; CHECK: loop.end: 605; CHECK-NEXT: [[RETVAL2:%.*]] = phi i64 [ [[INDEX]], [[LOOP_INC]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] 606; CHECK-NEXT: ret i64 [[RETVAL2]] 607; 608entry: 609 %p1 = alloca [1024 x i8] 610 %p2 = alloca [1024 x i8] 611 call void @init_mem(ptr %p1, i64 1024) 612 call void @init_mem(ptr %p2, i64 1024) 613 br label %loop 614 615loop: 616 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 617 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 618 %ld1 = load i8, ptr %arrayidx, align 1 619 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 620 %ld2 = load i8, ptr %arrayidx1, align 1 621 %cmp3 = icmp eq i8 %ld1, %ld2 622 br i1 %cmp3, label %loop.inc, label %loop.early.exit 623 624loop.inc: 625 %index.next = add i64 %index, 1 626 %exitcond = icmp ne i64 %index.next, 67 627 br i1 %exitcond, label %loop, label %loop.end 628 629loop.early.exit: 630 %retval1 = phi i64 [ 67, %loop ] 631 ret i64 %retval1 632 633loop.end: 634 %retval2 = phi i64 [ %index, %loop.inc ] 635 ret i64 %retval2 636} 637 638 639define i64 @diff_exit_block_pre_inc_use3() { 640; CHECK-LABEL: define i64 @diff_exit_block_pre_inc_use3() { 641; CHECK-NEXT: entry: 642; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 643; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 644; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 645; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 646; CHECK-NEXT: br label [[LOOP:%.*]] 647; CHECK: loop: 648; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 649; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 650; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 651; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 652; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 653; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 654; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_EARLY_EXIT:%.*]] 655; CHECK: loop.inc: 656; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 657; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 658; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END:%.*]] 659; CHECK: loop.early.exit: 660; CHECK-NEXT: [[INDEX_LCSSA:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ] 661; CHECK-NEXT: ret i64 [[INDEX_LCSSA]] 662; CHECK: loop.end: 663; CHECK-NEXT: [[INDEX_LCSSA1:%.*]] = phi i64 [ [[INDEX]], [[LOOP_INC]] ] 664; CHECK-NEXT: ret i64 [[INDEX_LCSSA1]] 665; 666entry: 667 %p1 = alloca [1024 x i8] 668 %p2 = alloca [1024 x i8] 669 call void @init_mem(ptr %p1, i64 1024) 670 call void @init_mem(ptr %p2, i64 1024) 671 br label %loop 672 673loop: 674 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 675 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 676 %ld1 = load i8, ptr %arrayidx, align 1 677 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 678 %ld2 = load i8, ptr %arrayidx1, align 1 679 %cmp3 = icmp eq i8 %ld1, %ld2 680 br i1 %cmp3, label %loop.inc, label %loop.early.exit 681 682loop.inc: 683 %index.next = add i64 %index, 1 684 %exitcond = icmp ne i64 %index.next, 67 685 br i1 %exitcond, label %loop, label %loop.end 686 687loop.early.exit: 688 ret i64 %index 689 690loop.end: 691 ret i64 %index 692} 693 694 695define i64 @diff_exit_block_post_inc_use1() { 696; CHECK-LABEL: define i64 @diff_exit_block_post_inc_use1() { 697; CHECK-NEXT: entry: 698; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 699; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 700; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 701; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 702; CHECK-NEXT: br label [[LOOP:%.*]] 703; CHECK: loop: 704; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 705; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 706; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 707; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 708; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 709; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 710; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_EARLY_EXIT:%.*]] 711; CHECK: loop.inc: 712; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 713; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 714; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END:%.*]] 715; CHECK: loop.early.exit: 716; CHECK-NEXT: [[RETVAL1:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ] 717; CHECK-NEXT: ret i64 [[RETVAL1]] 718; CHECK: loop.end: 719; CHECK-NEXT: [[RETVAL2:%.*]] = phi i64 [ [[INDEX_NEXT]], [[LOOP_INC]] ] 720; CHECK-NEXT: ret i64 [[RETVAL2]] 721; 722entry: 723 %p1 = alloca [1024 x i8] 724 %p2 = alloca [1024 x i8] 725 call void @init_mem(ptr %p1, i64 1024) 726 call void @init_mem(ptr %p2, i64 1024) 727 br label %loop 728 729loop: 730 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 731 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 732 %ld1 = load i8, ptr %arrayidx, align 1 733 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 734 %ld2 = load i8, ptr %arrayidx1, align 1 735 %cmp3 = icmp eq i8 %ld1, %ld2 736 br i1 %cmp3, label %loop.inc, label %loop.early.exit 737 738loop.inc: 739 %index.next = add i64 %index, 1 740 %exitcond = icmp ne i64 %index.next, 67 741 br i1 %exitcond, label %loop, label %loop.end 742 743loop.early.exit: 744 %retval1 = phi i64 [ %index, %loop ] 745 ret i64 %retval1 746 747loop.end: 748 %retval2 = phi i64 [ %index.next, %loop.inc ] 749 ret i64 %retval2 750} 751 752 753define i64 @diff_exit_block_post_inc_use2() { 754; CHECK-LABEL: define i64 @diff_exit_block_post_inc_use2() { 755; CHECK-NEXT: entry: 756; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 757; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 758; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 759; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 760; CHECK-NEXT: br label [[LOOP:%.*]] 761; CHECK: loop: 762; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 763; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 764; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 765; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 766; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 767; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 768; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 769; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_EARLY_EXIT:%.*]] 770; CHECK: loop.inc: 771; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 772; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END:%.*]] 773; CHECK: loop.early.exit: 774; CHECK-NEXT: [[RETVAL1:%.*]] = phi i64 [ [[INDEX_NEXT]], [[LOOP]] ] 775; CHECK-NEXT: ret i64 [[RETVAL1]] 776; CHECK: loop.end: 777; CHECK-NEXT: [[RETVAL2:%.*]] = phi i64 [ [[INDEX]], [[LOOP_INC]] ] 778; CHECK-NEXT: ret i64 [[RETVAL2]] 779; 780entry: 781 %p1 = alloca [1024 x i8] 782 %p2 = alloca [1024 x i8] 783 call void @init_mem(ptr %p1, i64 1024) 784 call void @init_mem(ptr %p2, i64 1024) 785 br label %loop 786 787loop: 788 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 789 %index.next = add i64 %index, 1 790 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 791 %ld1 = load i8, ptr %arrayidx, align 1 792 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 793 %ld2 = load i8, ptr %arrayidx1, align 1 794 %cmp3 = icmp eq i8 %ld1, %ld2 795 br i1 %cmp3, label %loop.inc, label %loop.early.exit 796 797loop.inc: 798 %exitcond = icmp ne i64 %index.next, 67 799 br i1 %exitcond, label %loop, label %loop.end 800 801loop.early.exit: 802 %retval1 = phi i64 [ %index.next, %loop ] 803 ret i64 %retval1 804 805loop.end: 806 %retval2 = phi i64 [ %index, %loop.inc ] 807 ret i64 %retval2 808} 809 810 811define i64 @loop_contains_safe_call() { 812; CHECK-LABEL: define i64 @loop_contains_safe_call() { 813; CHECK-NEXT: entry: 814; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 815; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 816; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 817; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 818; CHECK-NEXT: br label [[LOOP:%.*]] 819; CHECK: loop: 820; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 821; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[P1]], i64 [[INDEX]] 822; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[ARRAYIDX]], align 1 823; CHECK-NEXT: [[SQRT:%.*]] = tail call fast float @llvm.sqrt.f32(float [[LD1]]) 824; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ult float [[SQRT]], 3.000000e+00 825; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 826; CHECK: loop.inc: 827; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 828; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 829; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 830; CHECK: loop.end: 831; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 832; CHECK-NEXT: ret i64 [[RETVAL]] 833; 834entry: 835 %p1 = alloca [1024 x i8] 836 %p2 = alloca [1024 x i8] 837 call void @init_mem(ptr %p1, i64 1024) 838 call void @init_mem(ptr %p2, i64 1024) 839 br label %loop 840 841loop: 842 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 843 %arrayidx = getelementptr inbounds float, ptr %p1, i64 %index 844 %ld1 = load float, ptr %arrayidx, align 1 845 %sqrt = tail call fast float @llvm.sqrt.f32(float %ld1) 846 %cmp = fcmp fast ult float %sqrt, 3.0e+00 847 br i1 %cmp, label %loop.inc, label %loop.end 848 849loop.inc: 850 %index.next = add i64 %index, 1 851 %exitcond = icmp ne i64 %index.next, 67 852 br i1 %exitcond, label %loop, label %loop.end 853 854loop.end: 855 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 856 ret i64 %retval 857} 858 859 860define i64 @loop_contains_safe_div() { 861; CHECK-LABEL: define i64 @loop_contains_safe_div() { 862; CHECK-NEXT: entry: 863; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 864; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 865; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 866; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 867; CHECK-NEXT: br label [[LOOP:%.*]] 868; CHECK: loop: 869; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 870; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]] 871; CHECK-NEXT: [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1 872; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[LD1]], 20000 873; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[DIV]], 1 874; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 875; CHECK: loop.inc: 876; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 877; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 878; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 879; CHECK: loop.end: 880; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 881; CHECK-NEXT: ret i64 [[RETVAL]] 882; 883entry: 884 %p1 = alloca [1024 x i8] 885 %p2 = alloca [1024 x i8] 886 call void @init_mem(ptr %p1, i64 1024) 887 call void @init_mem(ptr %p2, i64 1024) 888 br label %loop 889 890loop: 891 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 892 %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index 893 %ld1 = load i32, ptr %arrayidx, align 1 894 %div = udiv i32 %ld1, 20000 895 %cmp = icmp eq i32 %div, 1 896 br i1 %cmp, label %loop.inc, label %loop.end 897 898loop.inc: 899 %index.next = add i64 %index, 1 900 %exitcond = icmp ne i64 %index.next, 67 901 br i1 %exitcond, label %loop, label %loop.end 902 903loop.end: 904 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 905 ret i64 %retval 906} 907 908 909define i64 @loop_contains_load_after_early_exit(ptr dereferenceable(1024) align(8) %p2) { 910; CHECK-LABEL: define i64 @loop_contains_load_after_early_exit( 911; CHECK-SAME: ptr align 8 dereferenceable(1024) [[P2:%.*]]) { 912; CHECK-NEXT: entry: 913; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 914; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 915; CHECK-NEXT: br label [[LOOP:%.*]] 916; CHECK: loop: 917; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 918; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]] 919; CHECK-NEXT: [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1 920; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LD1]], 1 921; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 922; CHECK: loop.inc: 923; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[INDEX]] 924; CHECK-NEXT: [[LD2:%.*]] = load i64, ptr [[ARRAYIDX2]], align 8 925; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 926; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 927; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 928; CHECK: loop.end: 929; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ [[LD2]], [[LOOP_INC]] ] 930; CHECK-NEXT: ret i64 [[RETVAL]] 931; 932entry: 933 %p1 = alloca [1024 x i8] 934 call void @init_mem(ptr %p1, i64 1024) 935 br label %loop 936 937loop: 938 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 939 %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index 940 %ld1 = load i32, ptr %arrayidx, align 1 941 %cmp = icmp eq i32 %ld1, 1 942 br i1 %cmp, label %loop.inc, label %loop.end 943 944loop.inc: 945 %arrayidx2 = getelementptr inbounds i64, ptr %p2, i64 %index 946 %ld2 = load i64, ptr %arrayidx2, align 8 947 %index.next = add i64 %index, 1 948 %exitcond = icmp ne i64 %index.next, 67 949 br i1 %exitcond, label %loop, label %loop.end 950 951loop.end: 952 %retval = phi i64 [ %index, %loop ], [ %ld2, %loop.inc ] 953 ret i64 %retval 954} 955 956 957define i64 @same_exit_block_pre_inc_use1_reverse() { 958; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_reverse() { 959; CHECK-NEXT: entry: 960; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 961; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 962; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 963; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 964; CHECK-NEXT: br label [[LOOP:%.*]] 965; CHECK: loop: 966; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 1023, [[ENTRY:%.*]] ] 967; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 968; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 969; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 970; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 971; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 972; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 973; CHECK: loop.inc: 974; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], -1 975; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDEX_NEXT]], 0 976; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_END]], label [[LOOP]] 977; CHECK: loop.end: 978; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 1024, [[LOOP_INC]] ] 979; CHECK-NEXT: ret i64 [[RETVAL]] 980; 981entry: 982 %p1 = alloca [1024 x i8] 983 %p2 = alloca [1024 x i8] 984 call void @init_mem(ptr %p1, i64 1024) 985 call void @init_mem(ptr %p2, i64 1024) 986 br label %loop 987 988loop: 989 %index = phi i64 [ %index.next, %loop.inc ], [ 1023, %entry ] 990 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 991 %ld1 = load i8, ptr %arrayidx, align 1 992 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 993 %ld2 = load i8, ptr %arrayidx1, align 1 994 %cmp3 = icmp eq i8 %ld1, %ld2 995 br i1 %cmp3, label %loop.inc, label %loop.end 996 997loop.inc: 998 %index.next = add i64 %index, -1 999 %exitcond = icmp eq i64 %index.next, 0 1000 br i1 %exitcond, label %loop.end, label %loop 1001 1002loop.end: 1003 %retval = phi i64 [ %index, %loop ], [ 1024, %loop.inc ] 1004 ret i64 %retval 1005} 1006 1007 1008define i64 @same_exit_block_pre_inc_use1_deref_ptrs(ptr dereferenceable(1024) %p1, ptr dereferenceable(1024) %p2) { 1009; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_deref_ptrs( 1010; CHECK-SAME: ptr dereferenceable(1024) [[P1:%.*]], ptr dereferenceable(1024) [[P2:%.*]]) { 1011; CHECK-NEXT: entry: 1012; CHECK-NEXT: br label [[LOOP:%.*]] 1013; CHECK: loop: 1014; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 1015; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 1016; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 1017; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 1018; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 1019; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 1020; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 1021; CHECK: loop.inc: 1022; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 1023; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 1024; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 1025; CHECK: loop.end: 1026; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 1027; CHECK-NEXT: ret i64 [[RETVAL]] 1028; 1029entry: 1030 br label %loop 1031 1032loop: 1033 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 1034 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 1035 %ld1 = load i8, ptr %arrayidx, align 1 1036 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 1037 %ld2 = load i8, ptr %arrayidx1, align 1 1038 %cmp3 = icmp eq i8 %ld1, %ld2 1039 br i1 %cmp3, label %loop.inc, label %loop.end 1040 1041loop.inc: 1042 %index.next = add i64 %index, 1 1043 %exitcond = icmp ne i64 %index.next, 67 1044 br i1 %exitcond, label %loop, label %loop.end 1045 1046loop.end: 1047 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 1048 ret i64 %retval 1049} 1050 1051 1052declare i32 @foo(i32) readonly 1053declare <vscale x 4 x i32> @foo_vec(<vscale x 4 x i32>) 1054 1055attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" } 1056;. 1057; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} 1058; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} 1059; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} 1060; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} 1061; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} 1062; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} 1063;. 1064