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