| ; 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: i16x8.extend_low_i8x16_s | |
| ; CHECK-NEXT: local.get 6 | |
| ; CHECK-NEXT: v128.load32_zero 0:p2align=0 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s | |
| ; CHECK-NEXT: i32x4.extmul_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: i16x8.extend_low_i8x16_s | |
| ; 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.extend_low_i8x16_s | |
| ; CHECK-NEXT: i32x4.extmul_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>) | |