1; RUN: opt < %s -loop-vectorize -pass-remarks=loop-vectorize -pass-remarks-analysis=loop-vectorize -pass-remarks-missed=loop-vectorize -mtriple aarch64-unknown-linux-gnu -mattr=+sve,+bf16 -S 2>%t | FileCheck %s -check-prefix=CHECK 2; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARK 3 4; Reduction can be vectorized 5 6; ADD 7 8; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 9define i32 @add(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 10; CHECK-LABEL: @add 11; CHECK: vector.body: 12; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 13; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 14; CHECK: %[[ADD1:.*]] = add <vscale x 8 x i32> %[[LOAD1]] 15; CHECK: %[[ADD2:.*]] = add <vscale x 8 x i32> %[[LOAD2]] 16; CHECK: middle.block: 17; CHECK: %[[ADD:.*]] = add <vscale x 8 x i32> %[[ADD2]], %[[ADD1]] 18; CHECK-NEXT: call i32 @llvm.vector.reduce.add.nxv8i32(<vscale x 8 x i32> %[[ADD]]) 19entry: 20 br label %for.body 21 22for.body: ; preds = %entry, %for.body 23 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 24 %sum.07 = phi i32 [ 2, %entry ], [ %add, %for.body ] 25 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 26 %0 = load i32, i32* %arrayidx, align 4 27 %add = add nsw i32 %0, %sum.07 28 %iv.next = add nuw nsw i64 %iv, 1 29 %exitcond.not = icmp eq i64 %iv.next, %n 30 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 31 32for.end: ; preds = %for.body, %entry 33 ret i32 %add 34} 35 36; OR 37 38; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 39define i32 @or(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 40; CHECK-LABEL: @or 41; CHECK: vector.body: 42; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 43; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 44; CHECK: %[[OR1:.*]] = or <vscale x 8 x i32> %[[LOAD1]] 45; CHECK: %[[OR2:.*]] = or <vscale x 8 x i32> %[[LOAD2]] 46; CHECK: middle.block: 47; CHECK: %[[OR:.*]] = or <vscale x 8 x i32> %[[OR2]], %[[OR1]] 48; CHECK-NEXT: call i32 @llvm.vector.reduce.or.nxv8i32(<vscale x 8 x i32> %[[OR]]) 49entry: 50 br label %for.body 51 52for.body: ; preds = %entry, %for.body 53 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 54 %sum.07 = phi i32 [ 2, %entry ], [ %or, %for.body ] 55 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 56 %0 = load i32, i32* %arrayidx, align 4 57 %or = or i32 %0, %sum.07 58 %iv.next = add nuw nsw i64 %iv, 1 59 %exitcond.not = icmp eq i64 %iv.next, %n 60 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 61 62for.end: ; preds = %for.body, %entry 63 ret i32 %or 64} 65 66; AND 67 68; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 69define i32 @and(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 70; CHECK-LABEL: @and 71; CHECK: vector.body: 72; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 73; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 74; CHECK: %[[AND1:.*]] = and <vscale x 8 x i32> %[[LOAD1]] 75; CHECK: %[[AND2:.*]] = and <vscale x 8 x i32> %[[LOAD2]] 76; CHECK: middle.block: 77; CHECK: %[[ABD:.*]] = and <vscale x 8 x i32> %[[ADD2]], %[[AND1]] 78; CHECK-NEXT: call i32 @llvm.vector.reduce.and.nxv8i32(<vscale x 8 x i32> %[[ADD]]) 79entry: 80 br label %for.body 81 82for.body: ; preds = %entry, %for.body 83 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 84 %sum.07 = phi i32 [ 2, %entry ], [ %and, %for.body ] 85 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 86 %0 = load i32, i32* %arrayidx, align 4 87 %and = and i32 %0, %sum.07 88 %iv.next = add nuw nsw i64 %iv, 1 89 %exitcond.not = icmp eq i64 %iv.next, %n 90 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 91 92for.end: ; preds = %for.body, %entry 93 ret i32 %and 94} 95 96; XOR 97 98; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 99define i32 @xor(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 100; CHECK-LABEL: @xor 101; CHECK: vector.body: 102; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 103; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 104; CHECK: %[[XOR1:.*]] = xor <vscale x 8 x i32> %[[LOAD1]] 105; CHECK: %[[XOR2:.*]] = xor <vscale x 8 x i32> %[[LOAD2]] 106; CHECK: middle.block: 107; CHECK: %[[XOR:.*]] = xor <vscale x 8 x i32> %[[XOR2]], %[[XOR1]] 108; CHECK-NEXT: call i32 @llvm.vector.reduce.xor.nxv8i32(<vscale x 8 x i32> %[[XOR]]) 109entry: 110 br label %for.body 111 112for.body: ; preds = %entry, %for.body 113 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 114 %sum.07 = phi i32 [ 2, %entry ], [ %xor, %for.body ] 115 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 116 %0 = load i32, i32* %arrayidx, align 4 117 %xor = xor i32 %0, %sum.07 118 %iv.next = add nuw nsw i64 %iv, 1 119 %exitcond.not = icmp eq i64 %iv.next, %n 120 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 121 122for.end: ; preds = %for.body, %entry 123 ret i32 %xor 124} 125 126; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 127; SMIN 128 129define i32 @smin(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 130; CHECK-LABEL: @smin 131; CHECK: vector.body: 132; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 133; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 134; CHECK: %[[ICMP1:.*]] = icmp slt <vscale x 8 x i32> %[[LOAD1]] 135; CHECK: %[[ICMP2:.*]] = icmp slt <vscale x 8 x i32> %[[LOAD2]] 136; CHECK: %[[SEL1:.*]] = select <vscale x 8 x i1> %[[ICMP1]], <vscale x 8 x i32> %[[LOAD1]] 137; CHECK: %[[SEL2:.*]] = select <vscale x 8 x i1> %[[ICMP2]], <vscale x 8 x i32> %[[LOAD2]] 138; CHECK: middle.block: 139; CHECK: %[[ICMP:.*]] = icmp slt <vscale x 8 x i32> %[[SEL1]], %[[SEL2]] 140; CHECK-NEXT: %[[SEL:.*]] = select <vscale x 8 x i1> %[[ICMP]], <vscale x 8 x i32> %[[SEL1]], <vscale x 8 x i32> %[[SEL2]] 141; CHECK-NEXT: call i32 @llvm.vector.reduce.smin.nxv8i32(<vscale x 8 x i32> %[[SEL]]) 142entry: 143 br label %for.body 144 145for.body: ; preds = %entry, %for.body 146 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 147 %sum.010 = phi i32 [ 2, %entry ], [ %.sroa.speculated, %for.body ] 148 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 149 %0 = load i32, i32* %arrayidx, align 4 150 %cmp.i = icmp slt i32 %0, %sum.010 151 %.sroa.speculated = select i1 %cmp.i, i32 %0, i32 %sum.010 152 %iv.next = add nuw nsw i64 %iv, 1 153 %exitcond.not = icmp eq i64 %iv.next, %n 154 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 155 156for.end: 157 ret i32 %.sroa.speculated 158} 159 160; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 161; UMAX 162 163define i32 @umax(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 164; CHECK-LABEL: @umax 165; CHECK: vector.body: 166; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x i32> 167; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x i32> 168; CHECK: %[[ICMP1:.*]] = icmp ugt <vscale x 8 x i32> %[[LOAD1]] 169; CHECK: %[[ICMP2:.*]] = icmp ugt <vscale x 8 x i32> %[[LOAD2]] 170; CHECK: %[[SEL1:.*]] = select <vscale x 8 x i1> %[[ICMP1]], <vscale x 8 x i32> %[[LOAD1]] 171; CHECK: %[[SEL2:.*]] = select <vscale x 8 x i1> %[[ICMP2]], <vscale x 8 x i32> %[[LOAD2]] 172; CHECK: middle.block: 173; CHECK: %[[ICMP:.*]] = icmp ugt <vscale x 8 x i32> %[[SEL1]], %[[SEL2]] 174; CHECK-NEXT: %[[SEL:.*]] = select <vscale x 8 x i1> %[[ICMP]], <vscale x 8 x i32> %[[SEL1]], <vscale x 8 x i32> %[[SEL2]] 175; CHECK-NEXT: call i32 @llvm.vector.reduce.umax.nxv8i32(<vscale x 8 x i32> %[[SEL]]) 176entry: 177 br label %for.body 178 179for.body: ; preds = %entry, %for.body 180 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 181 %sum.010 = phi i32 [ 2, %entry ], [ %.sroa.speculated, %for.body ] 182 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 183 %0 = load i32, i32* %arrayidx, align 4 184 %cmp.i = icmp ugt i32 %0, %sum.010 185 %.sroa.speculated = select i1 %cmp.i, i32 %0, i32 %sum.010 186 %iv.next = add nuw nsw i64 %iv, 1 187 %exitcond.not = icmp eq i64 %iv.next, %n 188 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 189 190for.end: 191 ret i32 %.sroa.speculated 192} 193 194; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 195; FADD (FAST) 196 197define float @fadd_fast(float* noalias nocapture readonly %a, i64 %n) { 198; CHECK-LABEL: @fadd_fast 199; CHECK: vector.body: 200; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x float> 201; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x float> 202; CHECK: %[[ADD1:.*]] = fadd fast <vscale x 8 x float> %[[LOAD1]] 203; CHECK: %[[ADD2:.*]] = fadd fast <vscale x 8 x float> %[[LOAD2]] 204; CHECK: middle.block: 205; CHECK: %[[ADD:.*]] = fadd fast <vscale x 8 x float> %[[ADD2]], %[[ADD1]] 206; CHECK-NEXT: call fast float @llvm.vector.reduce.fadd.nxv8f32(float -0.000000e+00, <vscale x 8 x float> %[[ADD]]) 207entry: 208 br label %for.body 209 210for.body: 211 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 212 %sum.07 = phi float [ 0.000000e+00, %entry ], [ %add, %for.body ] 213 %arrayidx = getelementptr inbounds float, float* %a, i64 %iv 214 %0 = load float, float* %arrayidx, align 4 215 %add = fadd fast float %0, %sum.07 216 %iv.next = add nuw nsw i64 %iv, 1 217 %exitcond.not = icmp eq i64 %iv.next, %n 218 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 219 220for.end: 221 ret float %add 222} 223 224; CHECK-REMARK: Scalable vectorization not supported for the reduction operations found in this loop. 225; CHECK-REMARK: vectorized loop (vectorization width: 8, interleaved count: 2) 226define bfloat @fadd_fast_bfloat(bfloat* noalias nocapture readonly %a, i64 %n) { 227; CHECK-LABEL: @fadd_fast_bfloat 228; CHECK: vector.body: 229; CHECK: %[[LOAD1:.*]] = load <8 x bfloat> 230; CHECK: %[[LOAD2:.*]] = load <8 x bfloat> 231; CHECK: %[[FADD1:.*]] = fadd fast <8 x bfloat> %[[LOAD1]] 232; CHECK: %[[FADD2:.*]] = fadd fast <8 x bfloat> %[[LOAD2]] 233; CHECK: middle.block: 234; CHECK: %[[RDX:.*]] = fadd fast <8 x bfloat> %[[FADD2]], %[[FADD1]] 235; CHECK: call fast bfloat @llvm.vector.reduce.fadd.v8bf16(bfloat 0xR8000, <8 x bfloat> %[[RDX]]) 236entry: 237 br label %for.body 238 239for.body: 240 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 241 %sum.07 = phi bfloat [ 0.000000e+00, %entry ], [ %add, %for.body ] 242 %arrayidx = getelementptr inbounds bfloat, bfloat* %a, i64 %iv 243 %0 = load bfloat, bfloat* %arrayidx, align 4 244 %add = fadd fast bfloat %0, %sum.07 245 %iv.next = add nuw nsw i64 %iv, 1 246 %exitcond.not = icmp eq i64 %iv.next, %n 247 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 248 249for.end: 250 ret bfloat %add 251} 252 253; FMIN (FAST) 254 255; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 256define float @fmin_fast(float* noalias nocapture readonly %a, i64 %n) #0 { 257; CHECK-LABEL: @fmin_fast 258; CHECK: vector.body: 259; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x float> 260; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x float> 261; CHECK: %[[FCMP1:.*]] = fcmp olt <vscale x 8 x float> %[[LOAD1]] 262; CHECK: %[[FCMP2:.*]] = fcmp olt <vscale x 8 x float> %[[LOAD2]] 263; CHECK: %[[SEL1:.*]] = select <vscale x 8 x i1> %[[FCMP1]], <vscale x 8 x float> %[[LOAD1]] 264; CHECK: %[[SEL2:.*]] = select <vscale x 8 x i1> %[[FCMP2]], <vscale x 8 x float> %[[LOAD2]] 265; CHECK: middle.block: 266; CHECK: %[[FCMP:.*]] = fcmp olt <vscale x 8 x float> %[[SEL1]], %[[SEL2]] 267; CHECK-NEXT: %[[SEL:.*]] = select <vscale x 8 x i1> %[[FCMP]], <vscale x 8 x float> %[[SEL1]], <vscale x 8 x float> %[[SEL2]] 268; CHECK-NEXT: call float @llvm.vector.reduce.fmin.nxv8f32(<vscale x 8 x float> %[[SEL]]) 269entry: 270 br label %for.body 271 272for.body: 273 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 274 %sum.07 = phi float [ 0.000000e+00, %entry ], [ %.sroa.speculated, %for.body ] 275 %arrayidx = getelementptr inbounds float, float* %a, i64 %iv 276 %0 = load float, float* %arrayidx, align 4 277 %cmp.i = fcmp olt float %0, %sum.07 278 %.sroa.speculated = select i1 %cmp.i, float %0, float %sum.07 279 %iv.next = add nuw nsw i64 %iv, 1 280 %exitcond.not = icmp eq i64 %iv.next, %n 281 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 282 283for.end: 284 ret float %.sroa.speculated 285} 286 287; FMAX (FAST) 288 289; CHECK-REMARK: vectorized loop (vectorization width: vscale x 8, interleaved count: 2) 290define float @fmax_fast(float* noalias nocapture readonly %a, i64 %n) #0 { 291; CHECK-LABEL: @fmax_fast 292; CHECK: vector.body: 293; CHECK: %[[LOAD1:.*]] = load <vscale x 8 x float> 294; CHECK: %[[LOAD2:.*]] = load <vscale x 8 x float> 295; CHECK: %[[FCMP1:.*]] = fcmp fast ogt <vscale x 8 x float> %[[LOAD1]] 296; CHECK: %[[FCMP2:.*]] = fcmp fast ogt <vscale x 8 x float> %[[LOAD2]] 297; CHECK: %[[SEL1:.*]] = select <vscale x 8 x i1> %[[FCMP1]], <vscale x 8 x float> %[[LOAD1]] 298; CHECK: %[[SEL2:.*]] = select <vscale x 8 x i1> %[[FCMP2]], <vscale x 8 x float> %[[LOAD2]] 299; CHECK: middle.block: 300; CHECK: %[[FCMP:.*]] = fcmp fast ogt <vscale x 8 x float> %[[SEL1]], %[[SEL2]] 301; CHECK-NEXT: %[[SEL:.*]] = select fast <vscale x 8 x i1> %[[FCMP]], <vscale x 8 x float> %[[SEL1]], <vscale x 8 x float> %[[SEL2]] 302; CHECK-NEXT: call fast float @llvm.vector.reduce.fmax.nxv8f32(<vscale x 8 x float> %[[SEL]]) 303entry: 304 br label %for.body 305 306for.body: 307 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 308 %sum.07 = phi float [ 0.000000e+00, %entry ], [ %.sroa.speculated, %for.body ] 309 %arrayidx = getelementptr inbounds float, float* %a, i64 %iv 310 %0 = load float, float* %arrayidx, align 4 311 %cmp.i = fcmp fast ogt float %0, %sum.07 312 %.sroa.speculated = select i1 %cmp.i, float %0, float %sum.07 313 %iv.next = add nuw nsw i64 %iv, 1 314 %exitcond.not = icmp eq i64 %iv.next, %n 315 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 316 317for.end: 318 ret float %.sroa.speculated 319} 320 321; ADD (with reduction stored in invariant address) 322 323; CHECK-REMARK: vectorized loop (vectorization width: vscale x 4, interleaved count: 2) 324define void @invariant_store(i32* %dst, i32* readonly %src) { 325; CHECK-LABEL: @invariant_store 326; CHECK: vector.body: 327; CHECK: %[[LOAD1:.*]] = load <vscale x 4 x i32> 328; CHECK: %[[LOAD2:.*]] = load <vscale x 4 x i32> 329; CHECK: %[[ADD1:.*]] = add <vscale x 4 x i32> %{{.*}}, %[[LOAD1]] 330; CHECK: %[[ADD2:.*]] = add <vscale x 4 x i32> %{{.*}}, %[[LOAD2]] 331; CHECK: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> %[[ADD1]] 332; CHECK: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> %[[ADD2]] 333; CHECK: middle.block: 334; CHECK: %[[ADD:.*]] = add <vscale x 4 x i32> %[[ADD2]], %[[ADD1]] 335; CHECK-NEXT: %[[SUM:.*]] = call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32> %[[ADD]]) 336; CHECK-NEXT: store i32 %[[SUM]], i32* %gep.dst, align 4 337entry: 338 %gep.dst = getelementptr inbounds i32, i32* %dst, i64 42 339 store i32 0, i32* %gep.dst, align 4 340 br label %for.body 341for.body: 342 %sum = phi i32 [ 0, %entry ], [ %add, %for.body ] 343 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 344 %gep.src = getelementptr inbounds i32, i32* %src, i64 %indvars.iv 345 %0 = load i32, i32* %gep.src, align 4 346 %add = add nsw i32 %sum, %0 347 store i32 %add, i32* %gep.dst, align 4 348 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 349 %exitcond = icmp eq i64 %indvars.iv.next, 1000 350 br i1 %exitcond, label %for.cond.cleanup, label %for.body 351 352for.cond.cleanup: 353 ret void 354} 355 356; Reduction cannot be vectorized 357 358; MUL 359 360; CHECK-REMARK: Scalable vectorization not supported for the reduction operations found in this loop. 361; CHECK-REMARK: vectorized loop (vectorization width: 4, interleaved count: 2) 362define i32 @mul(i32* nocapture %a, i32* nocapture readonly %b, i64 %n) { 363; CHECK-LABEL: @mul 364; CHECK: vector.body: 365; CHECK: %[[LOAD1:.*]] = load <4 x i32> 366; CHECK: %[[LOAD2:.*]] = load <4 x i32> 367; CHECK: %[[MUL1:.*]] = mul <4 x i32> %[[LOAD1]] 368; CHECK: %[[MUL2:.*]] = mul <4 x i32> %[[LOAD2]] 369; CHECK: middle.block: 370; CHECK: %[[RDX:.*]] = mul <4 x i32> %[[MUL2]], %[[MUL1]] 371; CHECK: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %[[RDX]]) 372entry: 373 br label %for.body 374 375for.body: ; preds = %entry, %for.body 376 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 377 %sum.07 = phi i32 [ 2, %entry ], [ %mul, %for.body ] 378 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %iv 379 %0 = load i32, i32* %arrayidx, align 4 380 %mul = mul nsw i32 %0, %sum.07 381 %iv.next = add nuw nsw i64 %iv, 1 382 %exitcond.not = icmp eq i64 %iv.next, %n 383 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 384 385for.end: ; preds = %for.body, %entry 386 ret i32 %mul 387} 388 389; Note: This test was added to ensure we always check the legality of reductions (end emit a warning if necessary) before checking for memory dependencies 390; CHECK-REMARK: Scalable vectorization not supported for the reduction operations found in this loop. 391; CHECK-REMARK: vectorized loop (vectorization width: 4, interleaved count: 2) 392define i32 @memory_dependence(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i64 %n) { 393; CHECK-LABEL: @memory_dependence 394; CHECK: vector.body: 395; CHECK: %[[LOAD1:.*]] = load <4 x i32> 396; CHECK: %[[LOAD2:.*]] = load <4 x i32> 397; CHECK: %[[LOAD3:.*]] = load <4 x i32> 398; CHECK: %[[LOAD4:.*]] = load <4 x i32> 399; CHECK: %[[ADD1:.*]] = add nsw <4 x i32> %[[LOAD3]], %[[LOAD1]] 400; CHECK: %[[ADD2:.*]] = add nsw <4 x i32> %[[LOAD4]], %[[LOAD2]] 401; CHECK: %[[MUL1:.*]] = mul <4 x i32> %[[LOAD3]] 402; CHECK: %[[MUL2:.*]] = mul <4 x i32> %[[LOAD4]] 403; CHECK: middle.block: 404; CHECK: %[[RDX:.*]] = mul <4 x i32> %[[MUL2]], %[[MUL1]] 405; CHECK: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %[[RDX]]) 406entry: 407 br label %for.body 408 409for.body: 410 %i = phi i64 [ %inc, %for.body ], [ 0, %entry ] 411 %sum = phi i32 [ %mul, %for.body ], [ 2, %entry ] 412 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %i 413 %0 = load i32, i32* %arrayidx, align 4 414 %arrayidx1 = getelementptr inbounds i32, i32* %b, i64 %i 415 %1 = load i32, i32* %arrayidx1, align 4 416 %add = add nsw i32 %1, %0 417 %add2 = add nuw nsw i64 %i, 32 418 %arrayidx3 = getelementptr inbounds i32, i32* %a, i64 %add2 419 store i32 %add, i32* %arrayidx3, align 4 420 %mul = mul nsw i32 %1, %sum 421 %inc = add nuw nsw i64 %i, 1 422 %exitcond.not = icmp eq i64 %inc, %n 423 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 424 425for.end: 426 ret i32 %mul 427} 428 429attributes #0 = { "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" } 430 431!0 = distinct !{!0, !1, !2, !3, !4} 432!1 = !{!"llvm.loop.vectorize.width", i32 8} 433!2 = !{!"llvm.loop.vectorize.scalable.enable", i1 true} 434!3 = !{!"llvm.loop.interleave.count", i32 2} 435!4 = !{!"llvm.loop.vectorize.enable", i1 true} 436