1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -p loop-unroll -mcpu=apple-m1 -S %s | FileCheck --check-prefix=APPLE %s 3; RUN: opt -p loop-unroll -mcpu=apple-m2 -S %s | FileCheck --check-prefix=APPLE %s 4; RUN: opt -p loop-unroll -mcpu=apple-m3 -S %s | FileCheck --check-prefix=APPLE %s 5; RUN: opt -p loop-unroll -mcpu=apple-m4 -S %s | FileCheck --check-prefix=APPLE %s 6; RUN: opt -p loop-unroll -mcpu=cortex-a57 -S %s | FileCheck --check-prefix=OTHER %s 7 8target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" 9target triple = "arm64-apple-macosx15.0.0" 10 11define i1 @multi_2_exit_find_i8_loop(ptr %vec, i8 %tgt) { 12; APPLE-LABEL: define i1 @multi_2_exit_find_i8_loop( 13; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0:[0-9]+]] { 14; APPLE-NEXT: [[ENTRY:.*]]: 15; APPLE-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 16; APPLE-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 17; APPLE-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 18; APPLE-NEXT: br label %[[LOOP_HEADER:.*]] 19; APPLE: [[LOOP_HEADER]]: 20; APPLE-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 21; APPLE-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 22; APPLE-NEXT: [[C_1:%.*]] = icmp eq i8 [[L]], [[TGT]] 23; APPLE-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 24; APPLE: [[LOOP_LATCH]]: 25; APPLE-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 26; APPLE-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 27; APPLE-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 28; APPLE: [[EXIT]]: 29; APPLE-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 30; APPLE-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 31; APPLE-NEXT: ret i1 [[C_3]] 32; 33; OTHER-LABEL: define i1 @multi_2_exit_find_i8_loop( 34; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0:[0-9]+]] { 35; OTHER-NEXT: [[ENTRY:.*]]: 36; OTHER-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 37; OTHER-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 38; OTHER-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 39; OTHER-NEXT: br label %[[LOOP_HEADER:.*]] 40; OTHER: [[LOOP_HEADER]]: 41; OTHER-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 42; OTHER-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 43; OTHER-NEXT: [[C_1:%.*]] = icmp eq i8 [[L]], [[TGT]] 44; OTHER-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 45; OTHER: [[LOOP_LATCH]]: 46; OTHER-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 47; OTHER-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 48; OTHER-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 49; OTHER: [[EXIT]]: 50; OTHER-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 51; OTHER-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 52; OTHER-NEXT: ret i1 [[C_3]] 53; 54entry: 55 %start = load ptr, ptr %vec, align 8 56 %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1 57 %end = load ptr, ptr %gep.end, align 8 58 br label %loop.header 59 60loop.header: 61 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ] 62 %l = load i8, ptr %ptr.iv, align 8 63 %c.1 = icmp eq i8 %l, %tgt 64 br i1 %c.1, label %exit, label %loop.latch 65 66loop.latch: 67 %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1 68 %c.2 = icmp eq ptr %ptr.iv.next, %end 69 br i1 %c.2, label %exit, label %loop.header 70 71exit: 72 %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ] 73 %c.3 = icmp eq ptr %res, %end 74 ret i1 %c.3 75} 76 77 78define i1 @multi_2_exit_find_ptr_loop(ptr %vec, ptr %tgt) { 79; APPLE-LABEL: define i1 @multi_2_exit_find_ptr_loop( 80; APPLE-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]]) #[[ATTR0]] { 81; APPLE-NEXT: [[ENTRY:.*]]: 82; APPLE-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 83; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ] 84; APPLE-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8 85; APPLE-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 86; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 87; APPLE-NEXT: br label %[[LOOP_HEADER:.*]] 88; APPLE: [[LOOP_HEADER]]: 89; APPLE-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 90; APPLE-NEXT: [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8 91; APPLE-NEXT: [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]] 92; APPLE-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 93; APPLE: [[LOOP_LATCH]]: 94; APPLE-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8 95; APPLE-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 96; APPLE-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 97; APPLE: [[EXIT]]: 98; APPLE-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 99; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 100; APPLE-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 101; APPLE-NEXT: ret i1 [[C_3]] 102; 103; OTHER-LABEL: define i1 @multi_2_exit_find_ptr_loop( 104; OTHER-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]]) #[[ATTR0]] { 105; OTHER-NEXT: [[ENTRY:.*]]: 106; OTHER-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 107; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ] 108; OTHER-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8 109; OTHER-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 110; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 111; OTHER-NEXT: br label %[[LOOP_HEADER:.*]] 112; OTHER: [[LOOP_HEADER]]: 113; OTHER-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 114; OTHER-NEXT: [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8 115; OTHER-NEXT: [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]] 116; OTHER-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 117; OTHER: [[LOOP_LATCH]]: 118; OTHER-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8 119; OTHER-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 120; OTHER-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 121; OTHER: [[EXIT]]: 122; OTHER-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 123; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 124; OTHER-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 125; OTHER-NEXT: ret i1 [[C_3]] 126; 127entry: 128 %start = load ptr, ptr %vec, align 8 129 call void @llvm.assume(i1 true) [ "align"(ptr %start, i64 8) ] 130 %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 8 131 %end = load ptr, ptr %gep.end, align 8 132 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ] 133 br label %loop.header 134 135loop.header: 136 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ] 137 %l = load ptr, ptr %ptr.iv, align 8 138 %c.1 = icmp eq ptr %l, %tgt 139 br i1 %c.1, label %exit, label %loop.latch 140 141loop.latch: 142 %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 8 143 %c.2 = icmp eq ptr %ptr.iv.next, %end 144 br i1 %c.2, label %exit, label %loop.header 145 146exit: 147 %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ] 148 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ] 149 %c.3 = icmp eq ptr %res, %end 150 ret i1 %c.3 151} 152 153define i1 @multi_2_exit_find_i8_loop_too_large(ptr %vec, i8 %tgt) { 154; APPLE-LABEL: define i1 @multi_2_exit_find_i8_loop_too_large( 155; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] { 156; APPLE-NEXT: [[ENTRY:.*]]: 157; APPLE-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 158; APPLE-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 159; APPLE-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 160; APPLE-NEXT: br label %[[LOOP_HEADER:.*]] 161; APPLE: [[LOOP_HEADER]]: 162; APPLE-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 163; APPLE-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 164; APPLE-NEXT: [[UDIV:%.*]] = udiv i8 [[L]], [[TGT]] 165; APPLE-NEXT: [[UDIV_2:%.*]] = udiv i8 [[UDIV]], 10 166; APPLE-NEXT: [[C_1:%.*]] = icmp eq i8 [[UDIV_2]], 2 167; APPLE-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 168; APPLE: [[LOOP_LATCH]]: 169; APPLE-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 170; APPLE-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 171; APPLE-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 172; APPLE: [[EXIT]]: 173; APPLE-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 174; APPLE-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 175; APPLE-NEXT: ret i1 [[C_3]] 176; 177; OTHER-LABEL: define i1 @multi_2_exit_find_i8_loop_too_large( 178; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] { 179; OTHER-NEXT: [[ENTRY:.*]]: 180; OTHER-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 181; OTHER-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 182; OTHER-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 183; OTHER-NEXT: br label %[[LOOP_HEADER:.*]] 184; OTHER: [[LOOP_HEADER]]: 185; OTHER-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 186; OTHER-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 187; OTHER-NEXT: [[UDIV:%.*]] = udiv i8 [[L]], [[TGT]] 188; OTHER-NEXT: [[UDIV_2:%.*]] = udiv i8 [[UDIV]], 10 189; OTHER-NEXT: [[C_1:%.*]] = icmp eq i8 [[UDIV_2]], 2 190; OTHER-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 191; OTHER: [[LOOP_LATCH]]: 192; OTHER-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 193; OTHER-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 194; OTHER-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 195; OTHER: [[EXIT]]: 196; OTHER-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 197; OTHER-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 198; OTHER-NEXT: ret i1 [[C_3]] 199; 200entry: 201 %start = load ptr, ptr %vec, align 8 202 %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1 203 %end = load ptr, ptr %gep.end, align 8 204 br label %loop.header 205 206loop.header: 207 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ] 208 %l = load i8, ptr %ptr.iv, align 8 209 %udiv = udiv i8 %l, %tgt 210 %udiv.2 = udiv i8 %udiv, 10 211 %c.1 = icmp eq i8 %udiv.2, 2 212 br i1 %c.1, label %exit, label %loop.latch 213 214loop.latch: 215 %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1 216 %c.2 = icmp eq ptr %ptr.iv.next, %end 217 br i1 %c.2, label %exit, label %loop.header 218 219exit: 220 %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ] 221 %c.3 = icmp eq ptr %res, %end 222 ret i1 %c.3 223} 224define i1 @multi_3_exit_find_ptr_loop(ptr %vec, ptr %tgt, ptr %tgt2) { 225; APPLE-LABEL: define i1 @multi_3_exit_find_ptr_loop( 226; APPLE-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]], ptr [[TGT2:%.*]]) #[[ATTR0]] { 227; APPLE-NEXT: [[ENTRY:.*]]: 228; APPLE-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 229; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ] 230; APPLE-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8 231; APPLE-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 232; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 233; APPLE-NEXT: br label %[[LOOP_HEADER:.*]] 234; APPLE: [[LOOP_HEADER]]: 235; APPLE-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 236; APPLE-NEXT: [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8 237; APPLE-NEXT: [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]] 238; APPLE-NEXT: [[C_2:%.*]] = icmp eq ptr [[L]], [[TGT2]] 239; APPLE-NEXT: [[OR_COND:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]] 240; APPLE-NEXT: br i1 [[OR_COND]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 241; APPLE: [[LOOP_LATCH]]: 242; APPLE-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8 243; APPLE-NEXT: [[C_3:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 244; APPLE-NEXT: br i1 [[C_3]], label %[[EXIT]], label %[[LOOP_HEADER]] 245; APPLE: [[EXIT]]: 246; APPLE-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 247; APPLE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 248; APPLE-NEXT: [[C_4:%.*]] = icmp eq ptr [[RES]], [[END]] 249; APPLE-NEXT: ret i1 [[C_4]] 250; 251; OTHER-LABEL: define i1 @multi_3_exit_find_ptr_loop( 252; OTHER-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]], ptr [[TGT2:%.*]]) #[[ATTR0]] { 253; OTHER-NEXT: [[ENTRY:.*]]: 254; OTHER-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 255; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ] 256; OTHER-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8 257; OTHER-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 258; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 259; OTHER-NEXT: br label %[[LOOP_HEADER:.*]] 260; OTHER: [[LOOP_HEADER]]: 261; OTHER-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 262; OTHER-NEXT: [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8 263; OTHER-NEXT: [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]] 264; OTHER-NEXT: [[C_2:%.*]] = icmp eq ptr [[L]], [[TGT2]] 265; OTHER-NEXT: [[OR_COND:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]] 266; OTHER-NEXT: br i1 [[OR_COND]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 267; OTHER: [[LOOP_LATCH]]: 268; OTHER-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8 269; OTHER-NEXT: [[C_3:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 270; OTHER-NEXT: br i1 [[C_3]], label %[[EXIT]], label %[[LOOP_HEADER]] 271; OTHER: [[EXIT]]: 272; OTHER-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 273; OTHER-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ] 274; OTHER-NEXT: [[C_4:%.*]] = icmp eq ptr [[RES]], [[END]] 275; OTHER-NEXT: ret i1 [[C_4]] 276; 277entry: 278 %start = load ptr, ptr %vec, align 8 279 call void @llvm.assume(i1 true) [ "align"(ptr %start, i64 8) ] 280 %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 8 281 %end = load ptr, ptr %gep.end, align 8 282 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ] 283 br label %loop.header 284 285loop.header: 286 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ] 287 %l = load ptr, ptr %ptr.iv, align 8 288 %c.1 = icmp eq ptr %l, %tgt 289 br i1 %c.1, label %exit, label %then 290 291then: 292 %c.2 = icmp eq ptr %l, %tgt2 293 br i1 %c.2, label %exit, label %loop.latch 294 295loop.latch: 296 %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 8 297 %c.3 = icmp eq ptr %ptr.iv.next, %end 298 br i1 %c.3, label %exit, label %loop.header 299 300exit: 301 %res = phi ptr [ %ptr.iv, %loop.header ], [ %ptr.iv, %then], [ %end, %loop.latch ] 302 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ] 303 %c.4 = icmp eq ptr %res, %end 304 ret i1 %c.4 305} 306 307define i1 @multi_3_exit_find_i8_loop_switch(ptr %vec, i8 %tgt) { 308; APPLE-LABEL: define i1 @multi_3_exit_find_i8_loop_switch( 309; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] { 310; APPLE-NEXT: [[ENTRY:.*]]: 311; APPLE-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 312; APPLE-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 313; APPLE-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 314; APPLE-NEXT: br label %[[LOOP_HEADER:.*]] 315; APPLE: [[LOOP_HEADER]]: 316; APPLE-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 317; APPLE-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 318; APPLE-NEXT: switch i8 [[L]], label %[[LOOP_LATCH]] [ 319; APPLE-NEXT: i8 0, label %[[EXIT_1:.*]] 320; APPLE-NEXT: i8 1, label %[[EXIT_2:.*]] 321; APPLE-NEXT: i8 2, label %[[EXIT:.*]] 322; APPLE-NEXT: ] 323; APPLE: [[LOOP_LATCH]]: 324; APPLE-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 325; APPLE-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 326; APPLE-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 327; APPLE: [[EXIT]]: 328; APPLE-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 329; APPLE-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 330; APPLE-NEXT: ret i1 [[C_3]] 331; APPLE: [[EXIT_1]]: 332; APPLE-NEXT: ret i1 false 333; APPLE: [[EXIT_2]]: 334; APPLE-NEXT: ret i1 true 335; 336; OTHER-LABEL: define i1 @multi_3_exit_find_i8_loop_switch( 337; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] { 338; OTHER-NEXT: [[ENTRY:.*]]: 339; OTHER-NEXT: [[START:%.*]] = load ptr, ptr [[VEC]], align 8 340; OTHER-NEXT: [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1 341; OTHER-NEXT: [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8 342; OTHER-NEXT: br label %[[LOOP_HEADER:.*]] 343; OTHER: [[LOOP_HEADER]]: 344; OTHER-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ] 345; OTHER-NEXT: [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8 346; OTHER-NEXT: switch i8 [[L]], label %[[LOOP_LATCH]] [ 347; OTHER-NEXT: i8 0, label %[[EXIT_1:.*]] 348; OTHER-NEXT: i8 1, label %[[EXIT_2:.*]] 349; OTHER-NEXT: i8 2, label %[[EXIT:.*]] 350; OTHER-NEXT: ] 351; OTHER: [[LOOP_LATCH]]: 352; OTHER-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1 353; OTHER-NEXT: [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]] 354; OTHER-NEXT: br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]] 355; OTHER: [[EXIT]]: 356; OTHER-NEXT: [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ] 357; OTHER-NEXT: [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]] 358; OTHER-NEXT: ret i1 [[C_3]] 359; OTHER: [[EXIT_1]]: 360; OTHER-NEXT: ret i1 false 361; OTHER: [[EXIT_2]]: 362; OTHER-NEXT: ret i1 true 363; 364entry: 365 %start = load ptr, ptr %vec, align 8 366 %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1 367 %end = load ptr, ptr %gep.end, align 8 368 br label %loop.header 369 370loop.header: 371 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ] 372 %l = load i8, ptr %ptr.iv, align 8 373 switch i8 %l, label %loop.latch [ 374 i8 0, label %exit.1 375 i8 1, label %exit.2 376 i8 2, label %exit ] 377 378loop.latch: 379 %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1 380 %c.2 = icmp eq ptr %ptr.iv.next, %end 381 br i1 %c.2, label %exit, label %loop.header 382 383exit: 384 %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ] 385 %c.3 = icmp eq ptr %res, %end 386 ret i1 %c.3 387 388exit.1: 389 ret i1 0 390 391exit.2: 392 ret i1 1 393} 394 395declare void @llvm.assume(i1 noundef) 396