1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve.fp \ 3; RUN: -tail-predication=enabled -passes=loop-vectorize -S < %s | \ 4; RUN: FileCheck %s 5 6target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 7 8define void @trunc_not_allowed_different_vec_elemns(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C, ptr noalias nocapture %D) #0 { 9; CHECK-LABEL: @trunc_not_allowed_different_vec_elemns( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 12; CHECK: vector.ph: 13; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 14; CHECK: vector.body: 15; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 16; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 17; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 [[TMP0]] 18; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 19; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 20; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i32 [[TMP0]] 21; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i32 0 22; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, ptr [[TMP4]], align 4 23; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] 24; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[TMP0]] 25; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0 26; CHECK-NEXT: store <4 x i32> [[TMP5]], ptr [[TMP7]], align 4 27; CHECK-NEXT: [[TMP8:%.*]] = trunc <4 x i32> [[TMP5]] to <4 x i16> 28; CHECK-NEXT: [[TMP9:%.*]] = shl <4 x i16> [[TMP8]], splat (i16 1) 29; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i16, ptr [[D:%.*]], i32 [[TMP0]] 30; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i16, ptr [[TMP10]], i32 0 31; CHECK-NEXT: store <4 x i16> [[TMP9]], ptr [[TMP11]], align 2 32; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 33; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[INDEX_NEXT]], 428 34; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 35; CHECK: middle.block: 36; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 37; CHECK: scalar.ph: 38; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 428, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 39; CHECK-NEXT: br label [[FOR_BODY:%.*]] 40; CHECK: for.cond.cleanup: 41; CHECK-NEXT: ret void 42; CHECK: for.body: 43; CHECK-NEXT: [[I_021:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD9:%.*]], [[FOR_BODY]] ] 44; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[I_021]] 45; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 46; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 [[I_021]] 47; CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4 48; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP14]], [[TMP13]] 49; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[I_021]] 50; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX2]], align 4 51; CHECK-NEXT: [[ADD_TR:%.*]] = trunc i32 [[ADD]] to i16 52; CHECK-NEXT: [[CONV7:%.*]] = shl i16 [[ADD_TR]], 1 53; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds i16, ptr [[D]], i32 [[I_021]] 54; CHECK-NEXT: store i16 [[CONV7]], ptr [[ARRAYIDX8]], align 2 55; CHECK-NEXT: [[ADD9]] = add nuw nsw i32 [[I_021]], 1 56; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD9]], 431 57; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] 58; 59entry: 60 br label %for.body 61 62for.cond.cleanup: 63 ret void 64 65for.body: 66 %i.021 = phi i32 [ 0, %entry ], [ %add9, %for.body ] 67 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.021 68 %0 = load i32, ptr %arrayidx, align 4 69 %arrayidx1 = getelementptr inbounds i32, ptr %C, i32 %i.021 70 %1 = load i32, ptr %arrayidx1, align 4 71 %add = add nsw i32 %1, %0 72 %arrayidx2 = getelementptr inbounds i32, ptr %A, i32 %i.021 73 store i32 %add, ptr %arrayidx2, align 4 74 %add.tr = trunc i32 %add to i16 75 %conv7 = shl i16 %add.tr, 1 76 %arrayidx8 = getelementptr inbounds i16, ptr %D, i32 %i.021 77 store i16 %conv7, ptr %arrayidx8, align 2 78 %add9 = add nuw nsw i32 %i.021, 1 79 %exitcond = icmp eq i32 %add9, 431 80 br i1 %exitcond, label %for.cond.cleanup, label %for.body 81} 82 83define void @unsupported_i64_type(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C) #0 { 84; CHECK-LABEL: @unsupported_i64_type( 85; CHECK-NEXT: entry: 86; CHECK-NEXT: br label [[FOR_BODY:%.*]] 87; CHECK: for.cond.cleanup: 88; CHECK-NEXT: ret void 89; CHECK: for.body: 90; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD3:%.*]], [[FOR_BODY]] ] 91; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[B:%.*]], i32 [[I_09]] 92; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 93; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i64, ptr [[C:%.*]], i32 [[I_09]] 94; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARRAYIDX1]], align 8 95; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP1]], [[TMP0]] 96; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i32 [[I_09]] 97; CHECK-NEXT: store i64 [[ADD]], ptr [[ARRAYIDX2]], align 8 98; CHECK-NEXT: [[ADD3]] = add nuw nsw i32 [[I_09]], 1 99; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD3]], 431 100; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 101; 102entry: 103 br label %for.body 104 105for.cond.cleanup: 106 ret void 107 108for.body: 109 %i.09 = phi i32 [ 0, %entry ], [ %add3, %for.body ] 110 %arrayidx = getelementptr inbounds i64, ptr %B, i32 %i.09 111 %0 = load i64, ptr %arrayidx, align 8 112 %arrayidx1 = getelementptr inbounds i64, ptr %C, i32 %i.09 113 %1 = load i64, ptr %arrayidx1, align 8 114 %add = add nsw i64 %1, %0 115 %arrayidx2 = getelementptr inbounds i64, ptr %A, i32 %i.09 116 store i64 %add, ptr %arrayidx2, align 8 117 %add3 = add nuw nsw i32 %i.09, 1 118 %exitcond = icmp eq i32 %add3, 431 119 br i1 %exitcond, label %for.cond.cleanup, label %for.body 120} 121 122define void @narrowing_load_not_allowed(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C) #0 { 123; CHECK-LABEL: @narrowing_load_not_allowed( 124; CHECK-NEXT: entry: 125; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 126; CHECK: vector.ph: 127; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 128; CHECK: vector.body: 129; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 130; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 131; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[C:%.*]], i32 [[TMP0]] 132; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0 133; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[TMP2]], align 2 134; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[B:%.*]], i32 [[TMP0]] 135; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 0 136; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <8 x i8>, ptr [[TMP4]], align 1 137; CHECK-NEXT: [[TMP5:%.*]] = trunc <8 x i16> [[WIDE_LOAD]] to <8 x i8> 138; CHECK-NEXT: [[TMP6:%.*]] = add <8 x i8> [[WIDE_LOAD1]], [[TMP5]] 139; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[TMP0]] 140; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i8, ptr [[TMP7]], i32 0 141; CHECK-NEXT: store <8 x i8> [[TMP6]], ptr [[TMP8]], align 1 142; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8 143; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], 424 144; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] 145; CHECK: middle.block: 146; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 147; CHECK: scalar.ph: 148; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 424, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 149; CHECK-NEXT: br label [[FOR_BODY:%.*]] 150; CHECK: for.cond.cleanup: 151; CHECK-NEXT: ret void 152; CHECK: for.body: 153; CHECK-NEXT: [[I_012:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD6:%.*]], [[FOR_BODY]] ] 154; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[C]], i32 [[I_012]] 155; CHECK-NEXT: [[TMP10:%.*]] = load i16, ptr [[ARRAYIDX]], align 2 156; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[B]], i32 [[I_012]] 157; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 158; CHECK-NEXT: [[CONV3:%.*]] = trunc i16 [[TMP10]] to i8 159; CHECK-NEXT: [[ADD:%.*]] = add i8 [[TMP11]], [[CONV3]] 160; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 [[I_012]] 161; CHECK-NEXT: store i8 [[ADD]], ptr [[ARRAYIDX5]], align 1 162; CHECK-NEXT: [[ADD6]] = add nuw nsw i32 [[I_012]], 1 163; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD6]], 431 164; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] 165; 166entry: 167 br label %for.body 168 169for.cond.cleanup: ; preds = %for.body 170 ret void 171 172for.body: ; preds = %for.body, %entry 173 %i.012 = phi i32 [ 0, %entry ], [ %add6, %for.body ] 174 %arrayidx = getelementptr inbounds i16, ptr %C, i32 %i.012 175 %0 = load i16, ptr %arrayidx, align 2 176 %arrayidx1 = getelementptr inbounds i8, ptr %B, i32 %i.012 177 %1 = load i8, ptr %arrayidx1, align 1 178 %conv3 = trunc i16 %0 to i8 179 %add = add i8 %1, %conv3 180 %arrayidx5 = getelementptr inbounds i8, ptr %A, i32 %i.012 181 store i8 %add, ptr %arrayidx5, align 1 182 %add6 = add nuw nsw i32 %i.012, 1 183 %exitcond = icmp eq i32 %add6, 431 184 br i1 %exitcond, label %for.cond.cleanup, label %for.body 185} 186 187; This is a trunc not connected to a store, so we don't allow this. 188; TODO: this is conservative, because the trunc is only used in the 189; loop control statements, and thus not affecting element sizes, so 190; we could allow this case. 191; 192define void @trunc_not_allowed(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C) #0 { 193; CHECK-LABEL: @trunc_not_allowed( 194; CHECK-NEXT: entry: 195; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 196; CHECK: vector.ph: 197; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 198; CHECK: vector.body: 199; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 200; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 201; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 [[TMP0]] 202; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 203; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 204; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i32 [[TMP0]] 205; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i32 0 206; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, ptr [[TMP4]], align 4 207; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] 208; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[TMP0]] 209; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0 210; CHECK-NEXT: store <4 x i32> [[TMP5]], ptr [[TMP7]], align 4 211; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 212; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[INDEX_NEXT]], 428 213; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] 214; CHECK: middle.block: 215; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 216; CHECK: scalar.ph: 217; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 428, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 218; CHECK-NEXT: br label [[FOR_BODY:%.*]] 219; CHECK: for.cond.cleanup: 220; CHECK-NEXT: ret void 221; CHECK: for.body: 222; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD3:%.*]], [[FOR_BODY]] ] 223; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[I_09]] 224; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 225; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 [[I_09]] 226; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4 227; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP10]], [[TMP9]] 228; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[I_09]] 229; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX2]], align 4 230; CHECK-NEXT: [[ADD3]] = add nuw nsw i32 [[I_09]], 1 231; CHECK-NEXT: [[ADD_IV:%.*]] = trunc i32 [[ADD3]] to i16 232; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i16 [[ADD_IV]], 431 233; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] 234; 235entry: 236 br label %for.body 237 238for.cond.cleanup: 239 ret void 240 241for.body: 242 %i.09 = phi i32 [ 0, %entry ], [ %add3, %for.body ] 243 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.09 244 %0 = load i32, ptr %arrayidx, align 4 245 %arrayidx1 = getelementptr inbounds i32, ptr %C, i32 %i.09 246 %1 = load i32, ptr %arrayidx1, align 4 247 %add = add nsw i32 %1, %0 248 %arrayidx2 = getelementptr inbounds i32, ptr %A, i32 %i.09 249 store i32 %add, ptr %arrayidx2, align 4 250 %add3 = add nuw nsw i32 %i.09, 1 251 252 %add.iv = trunc i32 %add3 to i16 253 254 %exitcond = icmp eq i16 %add.iv, 431 255 br i1 %exitcond, label %for.cond.cleanup, label %for.body 256} 257 258; Test directions for array indices i and N-1. I.e. check strides 1 and -1, and 259; force vectorisation with a loop hint. 260; 261define void @strides_different_direction(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C, i32 %N) #0 { 262; CHECK-LABEL: @strides_different_direction( 263; CHECK-NEXT: entry: 264; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 265; CHECK: vector.ph: 266; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 267; CHECK: vector.body: 268; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 269; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 270; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 [[TMP0]] 271; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 272; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 273; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[N:%.*]], [[TMP0]] 274; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i32 [[TMP3]] 275; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i32 0 276; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 -3 277; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, ptr [[TMP6]], align 4 278; CHECK-NEXT: [[REVERSE:%.*]] = shufflevector <4 x i32> [[WIDE_LOAD1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 279; CHECK-NEXT: [[TMP7:%.*]] = add nsw <4 x i32> [[REVERSE]], [[WIDE_LOAD]] 280; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[TMP0]] 281; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0 282; CHECK-NEXT: store <4 x i32> [[TMP7]], ptr [[TMP9]], align 4 283; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 284; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[INDEX_NEXT]], 428 285; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] 286; CHECK: middle.block: 287; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 288; CHECK: scalar.ph: 289; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 428, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 290; CHECK-NEXT: br label [[FOR_BODY:%.*]] 291; CHECK: for.cond.cleanup: 292; CHECK-NEXT: ret void 293; CHECK: for.body: 294; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD3:%.*]], [[FOR_BODY]] ] 295; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[I_09]] 296; CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 297; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[N]], [[I_09]] 298; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 [[SUB]] 299; CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4 300; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP12]], [[TMP11]] 301; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[I_09]] 302; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX2]], align 4 303; CHECK-NEXT: [[ADD3]] = add nuw nsw i32 [[I_09]], 1 304; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD3]], 431 305; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] 306; 307entry: 308 br label %for.body 309 310for.cond.cleanup: 311 ret void 312 313for.body: 314 %i.09 = phi i32 [ 0, %entry ], [ %add3, %for.body ] 315 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.09 316 %0 = load i32, ptr %arrayidx, align 4 317 %sub = sub nsw i32 %N, %i.09 318 %arrayidx1 = getelementptr inbounds i32, ptr %C, i32 %sub 319 %1 = load i32, ptr %arrayidx1, align 4 320 %add = add nsw i32 %1, %0 321 %arrayidx2 = getelementptr inbounds i32, ptr %A, i32 %i.09 322 store i32 %add, ptr %arrayidx2, align 4 323 %add3 = add nuw nsw i32 %i.09, 1 324 %exitcond = icmp eq i32 %add3, 431 325 br i1 %exitcond, label %for.cond.cleanup, label %for.body, !llvm.loop !10 326} 327 328define void @too_many_loop_blocks(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C) #0 { 329; CHECK-LABEL: @too_many_loop_blocks( 330; CHECK-NEXT: entry: 331; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 332; CHECK: vector.ph: 333; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 334; CHECK: vector.body: 335; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 336; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 337; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 [[TMP0]] 338; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 339; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 340; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i32 [[TMP0]] 341; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i32 0 342; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, ptr [[TMP4]], align 4 343; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] 344; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[TMP0]] 345; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0 346; CHECK-NEXT: store <4 x i32> [[TMP5]], ptr [[TMP7]], align 4 347; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 348; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[INDEX_NEXT]], 428 349; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] 350; CHECK: middle.block: 351; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 352; CHECK: scalar.ph: 353; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 428, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 354; CHECK-NEXT: br label [[FOR_BODY:%.*]] 355; CHECK: for.cond.cleanup: 356; CHECK-NEXT: ret void 357; CHECK: for.body: 358; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD3:%.*]], [[LOOPINCR:%.*]] ] 359; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[I_09]] 360; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 361; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 [[I_09]] 362; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4 363; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP10]], [[TMP9]] 364; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[I_09]] 365; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX2]], align 4 366; CHECK-NEXT: br label [[LOOPINCR]] 367; CHECK: loopincr: 368; CHECK-NEXT: [[ADD3]] = add nuw nsw i32 [[I_09]], 1 369; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD3]], 431 370; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]] 371; 372entry: 373 br label %for.body 374 375for.cond.cleanup: 376 ret void 377 378for.body: 379 %i.09 = phi i32 [ 0, %entry ], [ %add3, %loopincr ] 380 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.09 381 %0 = load i32, ptr %arrayidx, align 4 382 %arrayidx1 = getelementptr inbounds i32, ptr %C, i32 %i.09 383 %1 = load i32, ptr %arrayidx1, align 4 384 %add = add nsw i32 %1, %0 385 %arrayidx2 = getelementptr inbounds i32, ptr %A, i32 %i.09 386 store i32 %add, ptr %arrayidx2, align 4 387 br label %loopincr 388 389loopincr: 390 %add3 = add nuw nsw i32 %i.09, 1 391 %exitcond = icmp eq i32 %add3, 431 392 br i1 %exitcond, label %for.cond.cleanup, label %for.body 393} 394 395define void @double(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C) #0 { 396; CHECK-LABEL: @double( 397; CHECK-NEXT: entry: 398; CHECK-NEXT: br label [[FOR_BODY:%.*]] 399; CHECK: for.cond.cleanup: 400; CHECK-NEXT: ret void 401; CHECK: for.body: 402; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD3:%.*]], [[FOR_BODY]] ] 403; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[B:%.*]], i32 [[I_09]] 404; CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8 405; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, ptr [[C:%.*]], i32 [[I_09]] 406; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[ARRAYIDX1]], align 8 407; CHECK-NEXT: [[ADD:%.*]] = fadd fast double [[TMP1]], [[TMP0]] 408; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i32 [[I_09]] 409; CHECK-NEXT: store double [[ADD]], ptr [[ARRAYIDX2]], align 8 410; CHECK-NEXT: [[ADD3]] = add nuw nsw i32 [[I_09]], 1 411; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD3]], 431 412; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 413; 414entry: 415 br label %for.body 416 417for.cond.cleanup: 418 ret void 419 420for.body: 421 %i.09 = phi i32 [ 0, %entry ], [ %add3, %for.body ] 422 %arrayidx = getelementptr inbounds double, ptr %B, i32 %i.09 423 %0 = load double, ptr %arrayidx, align 8 424 %arrayidx1 = getelementptr inbounds double, ptr %C, i32 %i.09 425 %1 = load double, ptr %arrayidx1, align 8 426 %add = fadd fast double %1, %0 427 %arrayidx2 = getelementptr inbounds double, ptr %A, i32 %i.09 428 store double %add, ptr %arrayidx2, align 8 429 %add3 = add nuw nsw i32 %i.09, 1 430 %exitcond = icmp eq i32 %add3, 431 431 br i1 %exitcond, label %for.cond.cleanup, label %for.body 432} 433 434define void @fptrunc_not_allowed(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C, ptr noalias nocapture %D) #0 { 435; CHECK-LABEL: @fptrunc_not_allowed( 436; CHECK-NEXT: entry: 437; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 438; CHECK: vector.ph: 439; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 440; CHECK: vector.body: 441; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 442; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 443; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds float, ptr [[B:%.*]], i32 [[TMP0]] 444; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds float, ptr [[TMP1]], i32 0 445; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 446; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds float, ptr [[C:%.*]], i32 [[TMP0]] 447; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds float, ptr [[TMP3]], i32 0 448; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP4]], align 4 449; CHECK-NEXT: [[TMP5:%.*]] = fadd fast <4 x float> [[WIDE_LOAD1]], [[WIDE_LOAD]] 450; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds float, ptr [[A:%.*]], i32 [[TMP0]] 451; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds float, ptr [[TMP6]], i32 0 452; CHECK-NEXT: store <4 x float> [[TMP5]], ptr [[TMP7]], align 4 453; CHECK-NEXT: [[TMP8:%.*]] = fptrunc <4 x float> [[TMP5]] to <4 x half> 454; CHECK-NEXT: [[TMP9:%.*]] = fmul fast <4 x half> [[TMP8]], splat (half 0xH4000) 455; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds half, ptr [[D:%.*]], i32 [[TMP0]] 456; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds half, ptr [[TMP10]], i32 0 457; CHECK-NEXT: store <4 x half> [[TMP9]], ptr [[TMP11]], align 2 458; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 459; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[INDEX_NEXT]], 428 460; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] 461; CHECK: middle.block: 462; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] 463; CHECK: scalar.ph: 464; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 428, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 465; CHECK-NEXT: br label [[FOR_BODY:%.*]] 466; CHECK: for.cond.cleanup: 467; CHECK-NEXT: ret void 468; CHECK: for.body: 469; CHECK-NEXT: [[I_017:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD6:%.*]], [[FOR_BODY]] ] 470; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[B]], i32 [[I_017]] 471; CHECK-NEXT: [[TMP13:%.*]] = load float, ptr [[ARRAYIDX]], align 4 472; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds float, ptr [[C]], i32 [[I_017]] 473; CHECK-NEXT: [[TMP14:%.*]] = load float, ptr [[ARRAYIDX1]], align 4 474; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[TMP14]], [[TMP13]] 475; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, ptr [[A]], i32 [[I_017]] 476; CHECK-NEXT: store float [[ADD]], ptr [[ARRAYIDX2]], align 4 477; CHECK-NEXT: [[CONV:%.*]] = fptrunc float [[ADD]] to half 478; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast half [[CONV]], 0xH4000 479; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds half, ptr [[D]], i32 [[I_017]] 480; CHECK-NEXT: store half [[FACTOR]], ptr [[ARRAYIDX5]], align 2 481; CHECK-NEXT: [[ADD6]] = add nuw nsw i32 [[I_017]], 1 482; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[ADD6]], 431 483; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP13:![0-9]+]] 484; 485entry: 486 br label %for.body 487 488for.cond.cleanup: 489 ret void 490 491for.body: 492 %i.017 = phi i32 [ 0, %entry ], [ %add6, %for.body ] 493 %arrayidx = getelementptr inbounds float, ptr %B, i32 %i.017 494 %0 = load float, ptr %arrayidx, align 4 495 %arrayidx1 = getelementptr inbounds float, ptr %C, i32 %i.017 496 %1 = load float, ptr %arrayidx1, align 4 497 %add = fadd fast float %1, %0 498 %arrayidx2 = getelementptr inbounds float, ptr %A, i32 %i.017 499 store float %add, ptr %arrayidx2, align 4 500 %conv = fptrunc float %add to half 501 %factor = fmul fast half %conv, 0xH4000 502 %arrayidx5 = getelementptr inbounds half, ptr %D, i32 %i.017 503 store half %factor, ptr %arrayidx5, align 2 504 %add6 = add nuw nsw i32 %i.017, 1 505 %exitcond = icmp eq i32 %add6, 431 506 br i1 %exitcond, label %for.cond.cleanup, label %for.body 507} 508 509; This is a select which isn't a max or min (it isn't live-out), that we don't 510; want to tail-fold. Because this select will result in some mov lanes, 511; which aren't supported by the lowoverhead loop pass, causing the tail-predication 512; to be reverted which is expensive and what we would like to avoid. 513; 514define dso_local void @select_not_allowed(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C, i32 %N, ptr noalias nocapture readonly %Cond) { 515; CHECK-LABEL: @select_not_allowed( 516; CHECK-NEXT: entry: 517; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[N:%.*]], 0 518; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] 519; CHECK: for.body.preheader: 520; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 521; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 522; CHECK: vector.ph: 523; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 524; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] 525; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x ptr> poison, ptr [[C:%.*]], i64 0 526; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x ptr> [[BROADCAST_SPLATINSERT]], <4 x ptr> poison, <4 x i32> zeroinitializer 527; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x ptr> poison, ptr [[B:%.*]], i64 0 528; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x ptr> [[BROADCAST_SPLATINSERT1]], <4 x ptr> poison, <4 x i32> zeroinitializer 529; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 530; CHECK: vector.body: 531; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 532; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i32> [ <i32 0, i32 1, i32 2, i32 3>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] 533; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 534; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[COND:%.*]], i32 [[TMP0]] 535; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 536; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 537; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], zeroinitializer 538; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x ptr> [[BROADCAST_SPLAT]], <4 x ptr> [[BROADCAST_SPLAT2]] 539; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, <4 x ptr> [[TMP4]], <4 x i32> [[VEC_IND]] 540; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP5]], i32 4, <4 x i1> splat (i1 true), <4 x i32> poison) 541; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[TMP0]] 542; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0 543; CHECK-NEXT: store <4 x i32> [[WIDE_MASKED_GATHER]], ptr [[TMP7]], align 4 544; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 545; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i32> [[VEC_IND]], splat (i32 4) 546; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] 547; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]] 548; CHECK: middle.block: 549; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] 550; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] 551; CHECK: scalar.ph: 552; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 553; CHECK-NEXT: br label [[FOR_BODY:%.*]] 554; CHECK: for.cond.cleanup.loopexit: 555; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 556; CHECK: for.cond.cleanup: 557; CHECK-NEXT: ret void 558; CHECK: for.body: 559; CHECK-NEXT: [[I_011:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 560; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[COND]], i32 [[I_011]] 561; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 562; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP9]], 0 563; CHECK-NEXT: [[C_B:%.*]] = select i1 [[TOBOOL_NOT]], ptr [[C]], ptr [[B]] 564; CHECK-NEXT: [[COND_IN:%.*]] = getelementptr inbounds i32, ptr [[C_B]], i32 [[I_011]] 565; CHECK-NEXT: [[COND:%.*]] = load i32, ptr [[COND_IN]], align 4 566; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[I_011]] 567; CHECK-NEXT: store i32 [[COND]], ptr [[ARRAYIDX3]], align 4 568; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_011]], 1 569; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] 570; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop [[LOOP15:![0-9]+]] 571; 572entry: 573 %cmp10 = icmp sgt i32 %N, 0 574 br i1 %cmp10, label %for.body.preheader, label %for.cond.cleanup 575 576for.body.preheader: ; preds = %entry 577 br label %for.body 578 579for.cond.cleanup.loopexit: ; preds = %for.body 580 br label %for.cond.cleanup 581 582for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry 583 ret void 584 585for.body: ; preds = %for.body.preheader, %for.body 586 %i.011 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ] 587 %arrayidx = getelementptr inbounds i32, ptr %Cond, i32 %i.011 588 %0 = load i32, ptr %arrayidx, align 4 589 %tobool.not = icmp eq i32 %0, 0 590 %C.B = select i1 %tobool.not, ptr %C, ptr %B 591 %cond.in = getelementptr inbounds i32, ptr %C.B, i32 %i.011 592 %cond = load i32, ptr %cond.in, align 4 593 %arrayidx3 = getelementptr inbounds i32, ptr %A, i32 %i.011 594 store i32 %cond, ptr %arrayidx3, align 4 595 %inc = add nuw nsw i32 %i.011, 1 596 %exitcond.not = icmp eq i32 %inc, %N 597 br i1 %exitcond.not, label %for.cond.cleanup.loopexit, label %for.body 598} 599 600define i32 @i32_smin_reduction(ptr nocapture readonly %x, i32 %n) #0 { 601; CHECK-LABEL: @i32_smin_reduction( 602; CHECK-NEXT: entry: 603; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 604; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] 605; CHECK: for.body.preheader: 606; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 607; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 608; CHECK: vector.ph: 609; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 610; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] 611; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 612; CHECK: vector.body: 613; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 614; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ splat (i32 2147483647), [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] 615; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 616; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i32 [[TMP0]] 617; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 618; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 619; CHECK-NEXT: [[TMP3:%.*]] = icmp slt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] 620; CHECK-NEXT: [[TMP4]] = select <4 x i1> [[TMP3]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] 621; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 622; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] 623; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] 624; CHECK: middle.block: 625; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[TMP4]]) 626; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] 627; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] 628; CHECK: scalar.ph: 629; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 630; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP6]], [[MIDDLE_BLOCK]] ], [ 2147483647, [[FOR_BODY_PREHEADER]] ] 631; CHECK-NEXT: br label [[FOR_BODY:%.*]] 632; CHECK: for.body: 633; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 634; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] 635; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 [[I_08]] 636; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 637; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[R_07]], [[TMP7]] 638; CHECK-NEXT: [[ADD]] = select i1 [[C]], i32 [[R_07]], i32 [[TMP7]] 639; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 640; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] 641; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop [[LOOP17:![0-9]+]] 642; CHECK: for.cond.cleanup.loopexit: 643; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] 644; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 645; CHECK: for.cond.cleanup: 646; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] 647; CHECK-NEXT: ret i32 [[R_0_LCSSA]] 648; 649entry: 650 %cmp6 = icmp sgt i32 %n, 0 651 br i1 %cmp6, label %for.body, label %for.cond.cleanup 652 653for.body: ; preds = %entry, %for.body 654 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 655 %r.07 = phi i32 [ %add, %for.body ], [ 2147483647, %entry ] 656 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.08 657 %0 = load i32, ptr %arrayidx, align 4 658 %c = icmp slt i32 %r.07, %0 659 %add = select i1 %c, i32 %r.07, i32 %0 660 %inc = add nuw nsw i32 %i.08, 1 661 %exitcond = icmp eq i32 %inc, %n 662 br i1 %exitcond, label %for.cond.cleanup, label %for.body 663 664for.cond.cleanup: ; preds = %for.body, %entry 665 %r.0.lcssa = phi i32 [ 2147483647, %entry ], [ %add, %for.body ] 666 ret i32 %r.0.lcssa 667} 668 669define i32 @i32_smax_reduction(ptr nocapture readonly %x, i32 %n) #0 { 670; CHECK-LABEL: @i32_smax_reduction( 671; CHECK-NEXT: entry: 672; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 673; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] 674; CHECK: for.body.preheader: 675; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 676; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 677; CHECK: vector.ph: 678; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 679; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] 680; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 681; CHECK: vector.body: 682; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 683; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ splat (i32 -2147483648), [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] 684; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 685; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i32 [[TMP0]] 686; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 687; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 688; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] 689; CHECK-NEXT: [[TMP4]] = select <4 x i1> [[TMP3]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] 690; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 691; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] 692; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]] 693; CHECK: middle.block: 694; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP4]]) 695; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] 696; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] 697; CHECK: scalar.ph: 698; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 699; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP6]], [[MIDDLE_BLOCK]] ], [ -2147483648, [[FOR_BODY_PREHEADER]] ] 700; CHECK-NEXT: br label [[FOR_BODY:%.*]] 701; CHECK: for.body: 702; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 703; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] 704; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 [[I_08]] 705; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 706; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[R_07]], [[TMP7]] 707; CHECK-NEXT: [[ADD]] = select i1 [[C]], i32 [[R_07]], i32 [[TMP7]] 708; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 709; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] 710; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop [[LOOP19:![0-9]+]] 711; CHECK: for.cond.cleanup.loopexit: 712; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] 713; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 714; CHECK: for.cond.cleanup: 715; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] 716; CHECK-NEXT: ret i32 [[R_0_LCSSA]] 717; 718entry: 719 %cmp6 = icmp sgt i32 %n, 0 720 br i1 %cmp6, label %for.body, label %for.cond.cleanup 721 722for.body: ; preds = %entry, %for.body 723 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 724 %r.07 = phi i32 [ %add, %for.body ], [ -2147483648, %entry ] 725 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.08 726 %0 = load i32, ptr %arrayidx, align 4 727 %c = icmp sgt i32 %r.07, %0 728 %add = select i1 %c, i32 %r.07, i32 %0 729 %inc = add nuw nsw i32 %i.08, 1 730 %exitcond = icmp eq i32 %inc, %n 731 br i1 %exitcond, label %for.cond.cleanup, label %for.body 732 733for.cond.cleanup: ; preds = %for.body, %entry 734 %r.0.lcssa = phi i32 [ -2147483648, %entry ], [ %add, %for.body ] 735 ret i32 %r.0.lcssa 736} 737 738define i32 @i32_umin_reduction(ptr nocapture readonly %x, i32 %n) #0 { 739; CHECK-LABEL: @i32_umin_reduction( 740; CHECK-NEXT: entry: 741; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 742; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] 743; CHECK: for.body.preheader: 744; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 745; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 746; CHECK: vector.ph: 747; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 748; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] 749; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 750; CHECK: vector.body: 751; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 752; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ splat (i32 -1), [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] 753; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 754; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i32 [[TMP0]] 755; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 756; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 757; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] 758; CHECK-NEXT: [[TMP4]] = select <4 x i1> [[TMP3]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] 759; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 760; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] 761; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]] 762; CHECK: middle.block: 763; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP4]]) 764; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] 765; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] 766; CHECK: scalar.ph: 767; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 768; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP6]], [[MIDDLE_BLOCK]] ], [ -1, [[FOR_BODY_PREHEADER]] ] 769; CHECK-NEXT: br label [[FOR_BODY:%.*]] 770; CHECK: for.body: 771; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 772; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] 773; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 [[I_08]] 774; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 775; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[R_07]], [[TMP7]] 776; CHECK-NEXT: [[ADD]] = select i1 [[C]], i32 [[R_07]], i32 [[TMP7]] 777; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 778; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] 779; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop [[LOOP21:![0-9]+]] 780; CHECK: for.cond.cleanup.loopexit: 781; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] 782; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 783; CHECK: for.cond.cleanup: 784; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] 785; CHECK-NEXT: ret i32 [[R_0_LCSSA]] 786; 787entry: 788 %cmp6 = icmp sgt i32 %n, 0 789 br i1 %cmp6, label %for.body, label %for.cond.cleanup 790 791for.body: ; preds = %entry, %for.body 792 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 793 %r.07 = phi i32 [ %add, %for.body ], [ 4294967295, %entry ] 794 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.08 795 %0 = load i32, ptr %arrayidx, align 4 796 %c = icmp ult i32 %r.07, %0 797 %add = select i1 %c, i32 %r.07, i32 %0 798 %inc = add nuw nsw i32 %i.08, 1 799 %exitcond = icmp eq i32 %inc, %n 800 br i1 %exitcond, label %for.cond.cleanup, label %for.body 801 802for.cond.cleanup: ; preds = %for.body, %entry 803 %r.0.lcssa = phi i32 [ 4294967295, %entry ], [ %add, %for.body ] 804 ret i32 %r.0.lcssa 805} 806 807define i32 @i32_umax_reduction(ptr nocapture readonly %x, i32 %n) #0 { 808; CHECK-LABEL: @i32_umax_reduction( 809; CHECK-NEXT: entry: 810; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 811; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] 812; CHECK: for.body.preheader: 813; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 814; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 815; CHECK: vector.ph: 816; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 817; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] 818; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 819; CHECK: vector.body: 820; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 821; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] 822; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 823; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i32 [[TMP0]] 824; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 825; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 826; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] 827; CHECK-NEXT: [[TMP4]] = select <4 x i1> [[TMP3]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] 828; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 829; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] 830; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] 831; CHECK: middle.block: 832; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP4]]) 833; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] 834; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] 835; CHECK: scalar.ph: 836; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 837; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP6]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 838; CHECK-NEXT: br label [[FOR_BODY:%.*]] 839; CHECK: for.body: 840; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 841; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] 842; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 [[I_08]] 843; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 844; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[R_07]], [[TMP7]] 845; CHECK-NEXT: [[ADD]] = select i1 [[C]], i32 [[R_07]], i32 [[TMP7]] 846; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 847; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] 848; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop [[LOOP23:![0-9]+]] 849; CHECK: for.cond.cleanup.loopexit: 850; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] 851; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 852; CHECK: for.cond.cleanup: 853; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] 854; CHECK-NEXT: ret i32 [[R_0_LCSSA]] 855; 856entry: 857 %cmp6 = icmp sgt i32 %n, 0 858 br i1 %cmp6, label %for.body, label %for.cond.cleanup 859 860for.body: ; preds = %entry, %for.body 861 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 862 %r.07 = phi i32 [ %add, %for.body ], [ 0, %entry ] 863 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.08 864 %0 = load i32, ptr %arrayidx, align 4 865 %c = icmp ugt i32 %r.07, %0 866 %add = select i1 %c, i32 %r.07, i32 %0 867 %inc = add nuw nsw i32 %i.08, 1 868 %exitcond = icmp eq i32 %inc, %n 869 br i1 %exitcond, label %for.cond.cleanup, label %for.body 870 871for.cond.cleanup: ; preds = %for.body, %entry 872 %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] 873 ret i32 %r.0.lcssa 874} 875 876!10 = distinct !{!10, !11} 877!11 = !{!"llvm.loop.vectorize.width", i32 4} 878