blob: 26c1f3e9470def531a0b11cb5fa644751bfe8270 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=wasm32 -mattr=+simd128 %s -o - | FileCheck %s
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20"
target triple = "wasm32"
define hidden void @i32_add(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, i32 noundef %N) {
; CHECK-LABEL: i32_add:
; CHECK: .functype i32_add (i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label0
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 4
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label1
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 4
; CHECK-NEXT: local.set 8
; CHECK-NEXT: .LBB0_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label2:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 6
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label2
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label0
; CHECK-NEXT: .LBB0_5: # %for.body.preheader12
; CHECK-NEXT: end_block # label1:
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: local.tee 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: .LBB0_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label3:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32.store 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label3
; CHECK-NEXT: .LBB0_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label0:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp7.not = icmp eq i32 %N, 0
br i1 %cmp7.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader12, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 16
%wide.load = load <4 x i32>, ptr %0, align 4
%wide.load9 = load <4 x i32>, ptr %1, align 4
%2 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %index
%3 = getelementptr inbounds nuw i8, ptr %2, i32 16
%wide.load10 = load <4 x i32>, ptr %2, align 4
%wide.load11 = load <4 x i32>, ptr %3, align 4
%4 = add nsw <4 x i32> %wide.load10, %wide.load
%5 = add nsw <4 x i32> %wide.load11, %wide.load9
%6 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%7 = getelementptr inbounds nuw i8, ptr %6, i32 16
store <4 x i32> %4, ptr %6, align 4
store <4 x i32> %5, ptr %7, align 4
%index.next = add nuw i32 %index, 8
%8 = icmp eq i32 %index.next, %n.vec
br i1 %8, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader12
for.body.preheader12:
%i.08.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.08 = phi i32 [ %inc, %for.body ], [ %i.08.ph, %for.body.preheader12 ]
%arrayidx = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %i.08
%9 = load i32, ptr %arrayidx, align 4
%arrayidx1 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %i.08
%10 = load i32, ptr %arrayidx1, align 4
%add = add nsw i32 %10, %9
%arrayidx2 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.08
store i32 %add, ptr %arrayidx2, align 4
%inc = add nuw i32 %i.08, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
define hidden void @i32_madd(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, ptr nofree noundef readonly captures(none) %d, i32 noundef %N) {
; CHECK-LABEL: i32_madd:
; CHECK: .functype i32_madd (i32, i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label4
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 5
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label5
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 5
; CHECK-NEXT: local.set 10
; CHECK-NEXT: .LBB1_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label6:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 7
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label6
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label4
; CHECK-NEXT: .LBB1_5: # %for.body.preheader16
; CHECK-NEXT: end_block # label5:
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 10
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: local.tee 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: .LBB1_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label7:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: i32.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32.store 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label7
; CHECK-NEXT: .LBB1_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label4:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp9.not = icmp eq i32 %N, 0
br i1 %cmp9.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader16, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 16
%wide.load = load <4 x i32>, ptr %0, align 4
%wide.load11 = load <4 x i32>, ptr %1, align 4
%2 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %index
%3 = getelementptr inbounds nuw i8, ptr %2, i32 16
%wide.load12 = load <4 x i32>, ptr %2, align 4
%wide.load13 = load <4 x i32>, ptr %3, align 4
%4 = mul nsw <4 x i32> %wide.load12, %wide.load
%5 = mul nsw <4 x i32> %wide.load13, %wide.load11
%6 = getelementptr inbounds nuw [4 x i8], ptr %d, i32 %index
%7 = getelementptr inbounds nuw i8, ptr %6, i32 16
%wide.load14 = load <4 x i32>, ptr %6, align 4
%wide.load15 = load <4 x i32>, ptr %7, align 4
%8 = add nsw <4 x i32> %4, %wide.load14
%9 = add nsw <4 x i32> %5, %wide.load15
%10 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%11 = getelementptr inbounds nuw i8, ptr %10, i32 16
store <4 x i32> %8, ptr %10, align 4
store <4 x i32> %9, ptr %11, align 4
%index.next = add nuw i32 %index, 8
%12 = icmp eq i32 %index.next, %n.vec
br i1 %12, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader16
for.body.preheader16:
%i.010.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.010 = phi i32 [ %inc, %for.body ], [ %i.010.ph, %for.body.preheader16 ]
%arrayidx = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %i.010
%13 = load i32, ptr %arrayidx, align 4
%arrayidx1 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %i.010
%14 = load i32, ptr %arrayidx1, align 4
%mul = mul nsw i32 %14, %13
%arrayidx2 = getelementptr inbounds nuw [4 x i8], ptr %d, i32 %i.010
%15 = load i32, ptr %arrayidx2, align 4
%add = add nsw i32 %mul, %15
%arrayidx3 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.010
store i32 %add, ptr %arrayidx3, align 4
%inc = add nuw i32 %i.010, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
define hidden void @i32_i16_add(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, i32 noundef %N) {
; CHECK-LABEL: i32_i16_add:
; CHECK: .functype i32_i16_add (i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label8
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 4
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label9
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 4
; CHECK-NEXT: local.set 8
; CHECK-NEXT: .LBB2_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label10:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32x4.load16x4_s 0:p2align=1
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32x4.load16x4_s 0:p2align=1
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32x4.load16x4_s 0:p2align=1
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32x4.load16x4_s 0:p2align=1
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label10
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label8
; CHECK-NEXT: .LBB2_5: # %for.body.preheader13
; CHECK-NEXT: end_block # label9:
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 1
; CHECK-NEXT: i32.shl
; CHECK-NEXT: local.tee 6
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: .LBB2_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label11:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.load16_s 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.load16_s 0
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32.store 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label11
; CHECK-NEXT: .LBB2_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label8:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp8.not = icmp eq i32 %N, 0
br i1 %cmp8.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader13, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw [2 x i8], ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 8
%wide.load = load <4 x i16>, ptr %0, align 2
%wide.load10 = load <4 x i16>, ptr %1, align 2
%2 = sext <4 x i16> %wide.load to <4 x i32>
%3 = sext <4 x i16> %wide.load10 to <4 x i32>
%4 = getelementptr inbounds nuw [2 x i8], ptr %c, i32 %index
%5 = getelementptr inbounds nuw i8, ptr %4, i32 8
%wide.load11 = load <4 x i16>, ptr %4, align 2
%wide.load12 = load <4 x i16>, ptr %5, align 2
%6 = sext <4 x i16> %wide.load11 to <4 x i32>
%7 = sext <4 x i16> %wide.load12 to <4 x i32>
%8 = add nsw <4 x i32> %6, %2
%9 = add nsw <4 x i32> %7, %3
%10 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%11 = getelementptr inbounds nuw i8, ptr %10, i32 16
store <4 x i32> %8, ptr %10, align 4
store <4 x i32> %9, ptr %11, align 4
%index.next = add nuw i32 %index, 8
%12 = icmp eq i32 %index.next, %n.vec
br i1 %12, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader13
for.body.preheader13:
%i.09.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.09 = phi i32 [ %inc, %for.body ], [ %i.09.ph, %for.body.preheader13 ]
%arrayidx = getelementptr inbounds nuw [2 x i8], ptr %b, i32 %i.09
%13 = load i16, ptr %arrayidx, align 2
%conv = sext i16 %13 to i32
%arrayidx1 = getelementptr inbounds nuw [2 x i8], ptr %c, i32 %i.09
%14 = load i16, ptr %arrayidx1, align 2
%conv2 = sext i16 %14 to i32
%add = add nsw i32 %conv2, %conv
%arrayidx3 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.09
store i32 %add, ptr %arrayidx3, align 4
%inc = add nuw i32 %i.09, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
define hidden void @i32_i8_madd(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, ptr nofree noundef readonly captures(none) %d, i32 noundef %N) {
; CHECK-LABEL: i32_i8_madd:
; CHECK: .functype i32_i8_madd (i32, i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label12
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 5
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label13
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 5
; CHECK-NEXT: local.set 10
; CHECK-NEXT: .LBB3_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label14:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 7
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: i16x8.extmul_low_i8x16_s
; CHECK-NEXT: i32x4.extend_low_i16x8_s
; CHECK-NEXT: local.get 8
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: i16x8.extend_low_i8x16_s
; CHECK-NEXT: i32x4.extend_low_i16x8_s
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: i16x8.extmul_low_i8x16_s
; CHECK-NEXT: i32x4.extend_low_i16x8_s
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: i16x8.extend_low_i8x16_s
; CHECK-NEXT: i32x4.extend_low_i16x8_s
; CHECK-NEXT: i32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label14
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label12
; CHECK-NEXT: .LBB3_5: # %for.body.preheader18
; CHECK-NEXT: end_block # label13:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 10
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: .LBB3_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label15:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.load8_s 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.load8_s 0
; CHECK-NEXT: i32.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.load8_s 0
; CHECK-NEXT: i32.add
; CHECK-NEXT: i32.store 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label15
; CHECK-NEXT: .LBB3_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label12:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp11.not = icmp eq i32 %N, 0
br i1 %cmp11.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader18, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw i8, ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
%wide.load = load <4 x i8>, ptr %0, align 1
%wide.load13 = load <4 x i8>, ptr %1, align 1
%2 = sext <4 x i8> %wide.load to <4 x i32>
%3 = sext <4 x i8> %wide.load13 to <4 x i32>
%4 = getelementptr inbounds nuw i8, ptr %c, i32 %index
%5 = getelementptr inbounds nuw i8, ptr %4, i32 4
%wide.load14 = load <4 x i8>, ptr %4, align 1
%wide.load15 = load <4 x i8>, ptr %5, align 1
%6 = sext <4 x i8> %wide.load14 to <4 x i32>
%7 = sext <4 x i8> %wide.load15 to <4 x i32>
%8 = mul nsw <4 x i32> %6, %2
%9 = mul nsw <4 x i32> %7, %3
%10 = getelementptr inbounds nuw i8, ptr %d, i32 %index
%11 = getelementptr inbounds nuw i8, ptr %10, i32 4
%wide.load16 = load <4 x i8>, ptr %10, align 1
%wide.load17 = load <4 x i8>, ptr %11, align 1
%12 = sext <4 x i8> %wide.load16 to <4 x i32>
%13 = sext <4 x i8> %wide.load17 to <4 x i32>
%14 = add nsw <4 x i32> %8, %12
%15 = add nsw <4 x i32> %9, %13
%16 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%17 = getelementptr inbounds nuw i8, ptr %16, i32 16
store <4 x i32> %14, ptr %16, align 4
store <4 x i32> %15, ptr %17, align 4
%index.next = add nuw i32 %index, 8
%18 = icmp eq i32 %index.next, %n.vec
br i1 %18, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader18
for.body.preheader18:
%i.012.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.012 = phi i32 [ %inc, %for.body ], [ %i.012.ph, %for.body.preheader18 ]
%arrayidx = getelementptr inbounds nuw i8, ptr %b, i32 %i.012
%19 = load i8, ptr %arrayidx, align 1
%conv = sext i8 %19 to i32
%arrayidx1 = getelementptr inbounds nuw i8, ptr %c, i32 %i.012
%20 = load i8, ptr %arrayidx1, align 1
%conv2 = sext i8 %20 to i32
%mul = mul nsw i32 %conv2, %conv
%arrayidx3 = getelementptr inbounds nuw i8, ptr %d, i32 %i.012
%21 = load i8, ptr %arrayidx3, align 1
%conv4 = sext i8 %21 to i32
%add = add nsw i32 %mul, %conv4
%arrayidx5 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.012
store i32 %add, ptr %arrayidx5, align 4
%inc = add nuw i32 %i.012, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
define hidden void @f32_add(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, i32 noundef %N) {
; CHECK-LABEL: f32_add:
; CHECK: .functype f32_add (i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label16
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 4
; CHECK-NEXT: block
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label17
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 4
; CHECK-NEXT: local.set 8
; CHECK-NEXT: .LBB4_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label18:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 5
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label18
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label16
; CHECK-NEXT: .LBB4_5: # %for.body.preheader12
; CHECK-NEXT: end_block # label17:
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: local.tee 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: .LBB4_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label19:
; CHECK-NEXT: local.get 7
; CHECK-NEXT: local.get 5
; CHECK-NEXT: f32.load 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: f32.load 0
; CHECK-NEXT: f32.add
; CHECK-NEXT: f32.store 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 5
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 8
; CHECK-NEXT: br_if 0 # 0: up to label19
; CHECK-NEXT: .LBB4_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label16:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp7.not = icmp eq i32 %N, 0
br i1 %cmp7.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader12, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 16
%wide.load = load <4 x float>, ptr %0, align 4
%wide.load9 = load <4 x float>, ptr %1, align 4
%2 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %index
%3 = getelementptr inbounds nuw i8, ptr %2, i32 16
%wide.load10 = load <4 x float>, ptr %2, align 4
%wide.load11 = load <4 x float>, ptr %3, align 4
%4 = fadd <4 x float> %wide.load, %wide.load10
%5 = fadd <4 x float> %wide.load9, %wide.load11
%6 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%7 = getelementptr inbounds nuw i8, ptr %6, i32 16
store <4 x float> %4, ptr %6, align 4
store <4 x float> %5, ptr %7, align 4
%index.next = add nuw i32 %index, 8
%8 = icmp eq i32 %index.next, %n.vec
br i1 %8, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader12
for.body.preheader12:
%i.08.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.08 = phi i32 [ %inc, %for.body ], [ %i.08.ph, %for.body.preheader12 ]
%arrayidx = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %i.08
%9 = load float, ptr %arrayidx, align 4
%arrayidx1 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %i.08
%10 = load float, ptr %arrayidx1, align 4
%add = fadd float %9, %10
%arrayidx2 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.08
store float %add, ptr %arrayidx2, align 4
%inc = add nuw i32 %i.08, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
define hidden void @f32_madd(ptr noalias nofree noundef writeonly captures(none) %a, ptr nofree noundef readonly captures(none) %b, ptr nofree noundef readonly captures(none) %c, ptr nofree noundef readonly captures(none) %d, i32 noundef %N) {
; CHECK-LABEL: f32_madd:
; CHECK: .functype f32_madd (i32, i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.eqz
; CHECK-NEXT: br_if 0 # 0: down to label20
; CHECK-NEXT: # %bb.1: # %for.body.preheader
; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.set 5
; CHECK-NEXT: block
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const 8
; CHECK-NEXT: i32.lt_u
; CHECK-NEXT: br_if 0 # 0: down to label21
; CHECK-NEXT: # %bb.2: # %vector.ph
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.and
; CHECK-NEXT: local.tee 5
; CHECK-NEXT: local.set 10
; CHECK-NEXT: .LBB5_3: # %vector.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label22:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 6
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 16
; CHECK-NEXT: i32.add
; CHECK-NEXT: v128.load 0:p2align=2
; CHECK-NEXT: f32x4.add
; CHECK-NEXT: v128.store 0:p2align=2
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 32
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -8
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label22
; CHECK-NEXT: # %bb.4: # %middle.block
; CHECK-NEXT: end_loop
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.eq
; CHECK-NEXT: br_if 1 # 1: down to label20
; CHECK-NEXT: .LBB5_5: # %for.body.preheader16
; CHECK-NEXT: end_block # label21:
; CHECK-NEXT: local.get 4
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.sub
; CHECK-NEXT: local.set 10
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 5
; CHECK-NEXT: i32.const 2
; CHECK-NEXT: i32.shl
; CHECK-NEXT: local.tee 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: .LBB5_6: # %for.body
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: loop # label23:
; CHECK-NEXT: local.get 9
; CHECK-NEXT: local.get 6
; CHECK-NEXT: f32.load 0
; CHECK-NEXT: local.get 7
; CHECK-NEXT: f32.load 0
; CHECK-NEXT: f32.mul
; CHECK-NEXT: local.get 8
; CHECK-NEXT: f32.load 0
; CHECK-NEXT: f32.add
; CHECK-NEXT: f32.store 0
; CHECK-NEXT: local.get 6
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 6
; CHECK-NEXT: local.get 7
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 7
; CHECK-NEXT: local.get 8
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 8
; CHECK-NEXT: local.get 9
; CHECK-NEXT: i32.const 4
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.set 9
; CHECK-NEXT: local.get 10
; CHECK-NEXT: i32.const -1
; CHECK-NEXT: i32.add
; CHECK-NEXT: local.tee 10
; CHECK-NEXT: br_if 0 # 0: up to label23
; CHECK-NEXT: .LBB5_7: # %for.cond.cleanup
; CHECK-NEXT: end_loop
; CHECK-NEXT: end_block # label20:
; CHECK-NEXT: # fallthrough-return
entry:
%cmp9.not = icmp eq i32 %N, 0
br i1 %cmp9.not, label %for.cond.cleanup, label %for.body.preheader
for.body.preheader:
%min.iters.check = icmp ult i32 %N, 8
br i1 %min.iters.check, label %for.body.preheader16, label %vector.ph
vector.ph:
%n.vec = and i32 %N, -8
br label %vector.body
vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %index
%1 = getelementptr inbounds nuw i8, ptr %0, i32 16
%wide.load = load <4 x float>, ptr %0, align 4
%wide.load11 = load <4 x float>, ptr %1, align 4
%2 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %index
%3 = getelementptr inbounds nuw i8, ptr %2, i32 16
%wide.load12 = load <4 x float>, ptr %2, align 4
%wide.load13 = load <4 x float>, ptr %3, align 4
%4 = getelementptr inbounds nuw [4 x i8], ptr %d, i32 %index
%5 = getelementptr inbounds nuw i8, ptr %4, i32 16
%wide.load14 = load <4 x float>, ptr %4, align 4
%wide.load15 = load <4 x float>, ptr %5, align 4
%6 = tail call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %wide.load, <4 x float> %wide.load12, <4 x float> %wide.load14)
%7 = tail call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %wide.load11, <4 x float> %wide.load13, <4 x float> %wide.load15)
%8 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %index
%9 = getelementptr inbounds nuw i8, ptr %8, i32 16
store <4 x float> %6, ptr %8, align 4
store <4 x float> %7, ptr %9, align 4
%index.next = add nuw i32 %index, 8
%10 = icmp eq i32 %index.next, %n.vec
br i1 %10, label %middle.block, label %vector.body
middle.block:
%cmp.n = icmp eq i32 %N, %n.vec
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader16
for.body.preheader16:
%i.010.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
for.cond.cleanup:
ret void
for.body:
%i.010 = phi i32 [ %inc, %for.body ], [ %i.010.ph, %for.body.preheader16 ]
%arrayidx = getelementptr inbounds nuw [4 x i8], ptr %b, i32 %i.010
%11 = load float, ptr %arrayidx, align 4
%arrayidx1 = getelementptr inbounds nuw [4 x i8], ptr %c, i32 %i.010
%12 = load float, ptr %arrayidx1, align 4
%arrayidx2 = getelementptr inbounds nuw [4 x i8], ptr %d, i32 %i.010
%13 = load float, ptr %arrayidx2, align 4
%14 = tail call float @llvm.fmuladd.f32(float %11, float %12, float %13)
%arrayidx3 = getelementptr inbounds nuw [4 x i8], ptr %a, i32 %i.010
store float %14, ptr %arrayidx3, align 4
%inc = add nuw i32 %i.010, 1
%exitcond.not = icmp eq i32 %inc, %N
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}
declare float @llvm.fmuladd.f32(float, float, float)
declare <4 x float> @llvm.fmuladd.v4f32(<4 x float>, <4 x float>, <4 x float>)