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 6 7; The early exit (i.e. unknown exit-not-taken count) is the latch - we don't 8; support this yet. 9define i64 @early_exit_on_last_block() { 10; CHECK-LABEL: define i64 @early_exit_on_last_block() { 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 13; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 14; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 15; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 16; CHECK-NEXT: br label [[LAND_RHS:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[SEARCH:%.*]] ], [ 3, [[ENTRY:%.*]] ] 19; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 20; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 21; CHECK-NEXT: br i1 [[CMP1]], label [[SEARCH]], label [[FOR_END_LOOPEXIT:%.*]] 22; CHECK: search: 23; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 24; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 25; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 26; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 27; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[TMP41]], [[TMP42]] 28; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_END_LOOPEXIT]], label [[LAND_RHS]] 29; CHECK: loop.end: 30; CHECK-NEXT: [[START_0_LCSSA:%.*]] = phi i64 [ 64, [[LAND_RHS]] ], [ [[INDEX]], [[SEARCH]] ] 31; CHECK-NEXT: ret i64 [[START_0_LCSSA]] 32; 33entry: 34 %p1 = alloca [1024 x i8] 35 %p2 = alloca [1024 x i8] 36 call void @init_mem(ptr %p1, i64 1024) 37 call void @init_mem(ptr %p2, i64 1024) 38 br label %loop 39 40loop: 41 %index = phi i64 [ %index.next, %search ], [ 3, %entry ] 42 %index.next = add i64 %index, 1 43 %exitcond = icmp ne i64 %index.next, 67 44 br i1 %exitcond, label %search, label %loop.end 45 46search: 47 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 48 %ld1 = load i8, ptr %arrayidx, align 1 49 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 50 %ld2 = load i8, ptr %arrayidx1, align 1 51 %cmp3 = icmp eq i8 %ld1, %ld2 52 br i1 %cmp3, label %loop.end, label %loop 53 54loop.end: 55 %retval = phi i64 [ 64, %loop ], [ %index, %search ] 56 ret i64 %retval 57} 58 59 60; We don't currently support multiple early exits. 61define i64 @multiple_uncountable_exits() { 62; CHECK-LABEL: define i64 @multiple_uncountable_exits() { 63; CHECK-NEXT: entry: 64; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 65; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 66; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 67; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 68; CHECK-NEXT: br label [[SEARCH1:%.*]] 69; CHECK: search1: 70; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 71; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 72; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 73; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 74; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 75; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 76; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_END:%.*]], label [[SEARCH2:%.*]] 77; CHECK: search2: 78; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[LD1]], 34 79; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_END]], label [[LOOP_INC]] 80; CHECK: loop.inc: 81; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 82; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 83; CHECK-NEXT: br i1 [[EXITCOND]], label [[SEARCH1]], label [[LOOP_END]] 84; CHECK: loop.end: 85; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[SEARCH1]] ], [ 100, [[SEARCH2]] ], [ 43, [[LOOP_INC]] ] 86; CHECK-NEXT: ret i64 [[RETVAL]] 87; 88entry: 89 %p1 = alloca [1024 x i8] 90 %p2 = alloca [1024 x i8] 91 call void @init_mem(ptr %p1, i64 1024) 92 call void @init_mem(ptr %p2, i64 1024) 93 br label %search1 94 95search1: 96 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 97 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 98 %ld1 = load i8, ptr %arrayidx, align 1 99 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 100 %ld2 = load i8, ptr %arrayidx1, align 1 101 %cmp1 = icmp eq i8 %ld1, %ld2 102 br i1 %cmp1, label %loop.end, label %search2 103 104search2: 105 %cmp2 = icmp ult i8 %ld1, 34 106 br i1 %cmp2, label %loop.end, label %loop.inc 107 108loop.inc: 109 %index.next = add i64 %index, 1 110 %exitcond = icmp ne i64 %index.next, 67 111 br i1 %exitcond, label %search1, label %loop.end 112 113loop.end: 114 %retval = phi i64 [ %index, %search1 ], [ 100, %search2 ], [ 43, %loop.inc ] 115 ret i64 %retval 116} 117 118 119define i64 @uncountable_exit_infinite_loop() { 120; CHECK-LABEL: define i64 @uncountable_exit_infinite_loop() { 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 123; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 124; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 125; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 126; CHECK-NEXT: br label [[LOOP:%.*]] 127; CHECK: loop: 128; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 129; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 130; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 131; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 132; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 133; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 134; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 135; CHECK: loop.inc: 136; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 137; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 138; CHECK-NEXT: br label [[LOOP]] 139; CHECK: loop.end: 140; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ] 141; CHECK-NEXT: ret i64 [[RETVAL]] 142; 143entry: 144 %p1 = alloca [1024 x i8] 145 %p2 = alloca [1024 x i8] 146 call void @init_mem(ptr %p1, i64 1024) 147 call void @init_mem(ptr %p2, i64 1024) 148 br label %loop 149 150loop: 151 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 152 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 153 %ld1 = load i8, ptr %arrayidx, align 1 154 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 155 %ld2 = load i8, ptr %arrayidx1, align 1 156 %cmp3 = icmp eq i8 %ld1, %ld2 157 br i1 %cmp3, label %loop.inc, label %loop.end 158 159loop.inc: 160 %index.next = add i64 %index, 1 161 %exitcond = icmp ne i64 %index.next, 67 162 br label %loop 163 164loop.end: 165 %retval = phi i64 [ %index, %loop ] 166 ret i64 %retval 167} 168 169 170define i64 @loop_contains_unsafe_call() { 171; CHECK-LABEL: define i64 @loop_contains_unsafe_call() { 172; CHECK-NEXT: entry: 173; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 174; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 175; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 176; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 177; CHECK-NEXT: br label [[LOOP:%.*]] 178; CHECK: loop: 179; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 180; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]] 181; CHECK-NEXT: [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1 182; CHECK-NEXT: [[BAD_CALL:%.*]] = call i32 @foo(i32 [[LD1]]) #[[ATTR1:[0-9]+]] 183; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[BAD_CALL]], 34 184; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 185; CHECK: loop.inc: 186; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 187; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 188; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 189; CHECK: loop.end: 190; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 191; CHECK-NEXT: ret i64 [[RETVAL]] 192; 193entry: 194 %p1 = alloca [1024 x i8] 195 %p2 = alloca [1024 x i8] 196 call void @init_mem(ptr %p1, i64 1024) 197 call void @init_mem(ptr %p2, i64 1024) 198 br label %loop 199 200loop: 201 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 202 %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index 203 %ld1 = load i32, ptr %arrayidx, align 1 204 %bad_call = call i32 @foo(i32 %ld1) #0 205 %cmp = icmp eq i32 %bad_call, 34 206 br i1 %cmp, label %loop.inc, label %loop.end 207 208loop.inc: 209 %index.next = add i64 %index, 1 210 %exitcond = icmp ne i64 %index.next, 67 211 br i1 %exitcond, label %loop, label %loop.end 212 213loop.end: 214 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 215 ret i64 %retval 216} 217 218 219define i64 @loop_contains_unsafe_div() { 220; CHECK-LABEL: define i64 @loop_contains_unsafe_div() { 221; CHECK-NEXT: entry: 222; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 223; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 224; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 225; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 226; CHECK-NEXT: br label [[LOOP:%.*]] 227; CHECK: loop: 228; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 229; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 230; CHECK-NEXT: [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1 231; CHECK-NEXT: [[DIV:%.*]] = udiv i32 20000, [[LD1]] 232; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[DIV]], 1 233; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 234; CHECK: loop.inc: 235; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 236; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 237; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 238; CHECK: loop.end: 239; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 240; CHECK-NEXT: ret i64 [[RETVAL]] 241; 242entry: 243 %p1 = alloca [1024 x i8] 244 %p2 = alloca [1024 x i8] 245 call void @init_mem(ptr %p1, i64 1024) 246 call void @init_mem(ptr %p2, i64 1024) 247 br label %loop 248 249loop: 250 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 251 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 252 %ld1 = load i32, ptr %arrayidx, align 1 253 %div = udiv i32 20000, %ld1 254 %cmp = icmp eq i32 %div, 1 255 br i1 %cmp, label %loop.inc, label %loop.end 256 257loop.inc: 258 %index.next = add i64 %index, 1 259 %exitcond = icmp ne i64 %index.next, 67 260 br i1 %exitcond, label %loop, label %loop.end 261 262loop.end: 263 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 264 ret i64 %retval 265} 266 267 268define i64 @loop_contains_store(ptr %dest) { 269; CHECK-LABEL: define i64 @loop_contains_store( 270; CHECK-SAME: ptr [[DEST:%.*]]) { 271; CHECK-NEXT: entry: 272; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 273; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 274; CHECK-NEXT: br label [[LOOP:%.*]] 275; CHECK: loop: 276; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 277; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]] 278; CHECK-NEXT: [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1 279; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 [[INDEX]] 280; CHECK-NEXT: store i32 [[LD1]], ptr [[ARRAYIDX2]], align 4 281; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LD1]], 1 282; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 283; CHECK: loop.inc: 284; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 285; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 286; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 287; CHECK: loop.end: 288; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 289; CHECK-NEXT: ret i64 [[RETVAL]] 290; 291entry: 292 %p1 = alloca [1024 x i8] 293 call void @init_mem(ptr %p1, i64 1024) 294 br label %loop 295 296loop: 297 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 298 %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index 299 %ld1 = load i32, ptr %arrayidx, align 1 300 %arrayidx2 = getelementptr inbounds i32, ptr %dest, i64 %index 301 store i32 %ld1, ptr %arrayidx2, align 4 302 %cmp = icmp eq i32 %ld1, 1 303 br i1 %cmp, label %loop.inc, label %loop.end 304 305loop.inc: 306 %index.next = add i64 %index, 1 307 %exitcond = icmp ne i64 %index.next, 67 308 br i1 %exitcond, label %loop, label %loop.end 309 310loop.end: 311 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 312 ret i64 %retval 313} 314 315 316define i64 @uncountable_exit_in_conditional_block(ptr %mask) { 317; CHECK-LABEL: define i64 @uncountable_exit_in_conditional_block( 318; CHECK-SAME: ptr [[MASK:%.*]]) { 319; CHECK-NEXT: entry: 320; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 321; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 322; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 323; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 324; CHECK-NEXT: br label [[LOOP:%.*]] 325; CHECK: loop: 326; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 327; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[MASK]], i64 [[INDEX]] 328; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 329; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[LD1]], 0 330; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_SEARCH:%.*]], label [[LOOP_INC]] 331; CHECK: loop.search: 332; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 333; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1 334; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 335; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[ARRAYIDX3]], align 1 336; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[LD2]], [[LD3]] 337; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_INC]], label [[LOOP_END:%.*]] 338; CHECK: loop.inc: 339; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 340; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 341; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 342; CHECK: loop.end: 343; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP_SEARCH]] ], [ 67, [[LOOP_INC]] ] 344; CHECK-NEXT: ret i64 [[RETVAL]] 345; 346entry: 347 %p1 = alloca [1024 x i8] 348 %p2 = alloca [1024 x i8] 349 call void @init_mem(ptr %p1, i64 1024) 350 call void @init_mem(ptr %p2, i64 1024) 351 br label %loop 352 353loop: 354 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 355 %arrayidx1 = getelementptr inbounds i8, ptr %mask, i64 %index 356 %ld1 = load i8, ptr %arrayidx1, align 1 357 %cmp1 = icmp ne i8 %ld1, 0 358 br i1 %cmp1, label %loop.search, label %loop.inc 359 360loop.search: 361 %arrayidx2 = getelementptr inbounds i8, ptr %p1, i64 %index 362 %ld2 = load i8, ptr %arrayidx2, align 1 363 %arrayidx3 = getelementptr inbounds i8, ptr %p2, i64 %index 364 %ld3 = load i8, ptr %arrayidx3, align 1 365 %cmp2 = icmp eq i8 %ld2, %ld3 366 br i1 %cmp2, label %loop.inc, label %loop.end 367 368loop.inc: 369 %index.next = add i64 %index, 1 370 %exitcond = icmp ne i64 %index.next, 67 371 br i1 %exitcond, label %loop, label %loop.end 372 373loop.end: 374 %retval = phi i64 [ %index, %loop.search ], [ 67, %loop.inc ] 375 ret i64 %retval 376} 377 378 379define i64 @same_exit_block_pre_inc_use1_with_reduction() { 380; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_with_reduction() { 381; CHECK-NEXT: entry: 382; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 383; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 384; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 385; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 386; CHECK-NEXT: br label [[LAND_RHS:%.*]] 387; CHECK: loop: 388; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 389; CHECK-NEXT: [[RED:%.*]] = phi i64 [ [[RED_NEXT:%.*]], [[FOR_INC]] ], [ 0, [[ENTRY]] ] 390; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 391; CHECK-NEXT: [[TMP38:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 392; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 393; CHECK-NEXT: [[TMP39:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 394; CHECK-NEXT: [[LD2_ZEXT:%.*]] = zext i8 [[TMP39]] to i64 395; CHECK-NEXT: [[RED_NEXT]] = add i64 [[RED]], [[LD2_ZEXT]] 396; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[TMP38]], [[TMP39]] 397; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_INC]], label [[FOR_END_LOOPEXIT:%.*]] 398; CHECK: loop.inc: 399; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 400; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 401; CHECK-NEXT: br i1 [[EXITCOND]], label [[LAND_RHS]], label [[FOR_END_LOOPEXIT]] 402; CHECK: loop.end: 403; CHECK-NEXT: [[RED_NEXT_LCSSA:%.*]] = phi i64 [ [[RED_NEXT]], [[FOR_INC]] ], [ [[RED_NEXT]], [[LAND_RHS]] ] 404; CHECK-NEXT: [[FINAL_IND:%.*]] = phi i64 [ [[INDEX]], [[LAND_RHS]] ], [ 67, [[FOR_INC]] ] 405; CHECK-NEXT: [[START_0_LCSSA:%.*]] = add i64 [[RED_NEXT_LCSSA]], [[FINAL_IND]] 406; CHECK-NEXT: ret i64 [[START_0_LCSSA]] 407; 408entry: 409 %p1 = alloca [1024 x i8] 410 %p2 = alloca [1024 x i8] 411 call void @init_mem(ptr %p1, i64 1024) 412 call void @init_mem(ptr %p2, i64 1024) 413 br label %loop 414 415loop: 416 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 417 %red = phi i64 [ %red.next, %loop.inc ], [ 0, %entry ] 418 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 419 %ld1 = load i8, ptr %arrayidx, align 1 420 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 421 %ld2 = load i8, ptr %arrayidx1, align 1 422 %ld2.zext = zext i8 %ld2 to i64 423 %red.next = add i64 %red, %ld2.zext 424 %cmp3 = icmp eq i8 %ld1, %ld2 425 br i1 %cmp3, label %loop.inc, label %loop.end 426 427loop.inc: 428 %index.next = add i64 %index, 1 429 %exitcond = icmp ne i64 %index.next, 67 430 br i1 %exitcond, label %loop, label %loop.end 431 432loop.end: 433 %final.ind = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 434 %retval = add i64 %red.next, %final.ind 435 ret i64 %retval 436} 437 438 439define i64 @uncountable_exit_has_multiple_outside_successors() { 440; CHECK-LABEL: define i64 @uncountable_exit_has_multiple_outside_successors() { 441; CHECK-NEXT: entry: 442; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 443; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 444; CHECK-NEXT: br label [[LOOP:%.*]] 445; CHECK: loop: 446; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 447; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 448; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 449; CHECK-NEXT: switch i8 [[LD1]], label [[LOOP_INC]] [ 450; CHECK-NEXT: i8 2, label [[LOOP_END:%.*]] 451; CHECK-NEXT: i8 3, label [[LOOP_SURPRISE:%.*]] 452; CHECK-NEXT: ] 453; CHECK: loop.inc: 454; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 455; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67 456; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 457; CHECK: loop.surprise: 458; CHECK-NEXT: ret i64 3 459; CHECK: loop.end: 460; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ] 461; CHECK-NEXT: ret i64 [[RETVAL]] 462; 463entry: 464 %p1 = alloca [1024 x i8] 465 call void @init_mem(ptr %p1, i64 1024) 466 br label %loop 467 468loop: 469 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 470 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 471 %ld1 = load i8, ptr %arrayidx, align 1 472 switch i8 %ld1, label %loop.inc [ 473 i8 2, label %loop.end 474 i8 3, label %loop.surprise 475 ] 476 477loop.inc: 478 %index.next = add i64 %index, 1 479 %exitcond = icmp ne i64 %index.next, 67 480 br i1 %exitcond, label %loop, label %loop.end 481 482loop.surprise: 483 ret i64 3 484 485loop.end: 486 %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ] 487 ret i64 %retval 488} 489 490 491declare i32 @foo(i32) readonly 492declare <vscale x 4 x i32> @foo_vec(<vscale x 4 x i32>) 493 494attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" } 495