| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 |
| ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=alderlake -verify-machineinstrs| FileCheck %s --check-prefixes=AVX,ADL |
| ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=sapphirerapids -verify-machineinstrs | FileCheck %s --check-prefixes=AVX,SPR |
| ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=icelake-server -verify-machineinstrs | FileCheck %s --check-prefixes=AVX512 |
| |
| define <2 x i64> @foo_reg_128(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2, <2 x i64> %3, <2 x i64> %4, <2 x i64> %5) { |
| ; AVX-LABEL: foo_reg_128: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: {vex} vpdpwssd %xmm2, %xmm1, %xmm0 |
| ; AVX-NEXT: vpmaddwd %xmm3, %xmm1, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX-NEXT: vpmaddwd %xmm4, %xmm1, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX-NEXT: vpmaddwd %xmm5, %xmm1, %xmm1 |
| ; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: foo_reg_128: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: vpdpwssd %xmm2, %xmm1, %xmm0 |
| ; AVX512-NEXT: vpmaddwd %xmm3, %xmm1, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX512-NEXT: vpmaddwd %xmm4, %xmm1, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX512-NEXT: vpmaddwd %xmm5, %xmm1, %xmm1 |
| ; AVX512-NEXT: vpaddd %xmm1, %xmm0, %xmm0 |
| ; AVX512-NEXT: retq |
| %7 = bitcast <2 x i64> %0 to <4 x i32> |
| %8 = bitcast <2 x i64> %1 to <4 x i32> |
| %9 = bitcast <2 x i64> %2 to <4 x i32> |
| %10 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %7, <4 x i32> %8, <4 x i32> %9) |
| %11 = bitcast <2 x i64> %3 to <4 x i32> |
| %12 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %10, <4 x i32> %8, <4 x i32> %11) |
| %13 = bitcast <2 x i64> %4 to <4 x i32> |
| %14 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %12, <4 x i32> %8, <4 x i32> %13) |
| %15 = bitcast <2 x i64> %5 to <4 x i32> |
| %16 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %14, <4 x i32> %8, <4 x i32> %15) |
| %17 = bitcast <4 x i32> %16 to <2 x i64> |
| ret <2 x i64> %17 |
| } |
| |
| declare <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32>, <4 x i32>, <4 x i32>) #1 |
| |
| define <2 x i64> @foo_128(i32 %0, <2 x i64> %1, <2 x i64> %2, ptr %3) { |
| ; AVX-LABEL: foo_128: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: testl %edi, %edi |
| ; AVX-NEXT: jle .LBB1_6 |
| ; AVX-NEXT: # %bb.1: |
| ; AVX-NEXT: movl %edi, %edx |
| ; AVX-NEXT: movl %edx, %eax |
| ; AVX-NEXT: andl $3, %eax |
| ; AVX-NEXT: cmpl $4, %edi |
| ; AVX-NEXT: jae .LBB1_7 |
| ; AVX-NEXT: # %bb.2: |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: jmp .LBB1_3 |
| ; AVX-NEXT: .LBB1_7: |
| ; AVX-NEXT: andl $-4, %edx |
| ; AVX-NEXT: leaq 48(%rsi), %rdi |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB1_8: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: {vex} vpdpwssd -48(%rdi), %xmm1, %xmm0 |
| ; AVX-NEXT: vpmaddwd -32(%rdi), %xmm1, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX-NEXT: vpmaddwd -16(%rdi), %xmm1, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX-NEXT: vpmaddwd (%rdi), %xmm1, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX-NEXT: addq $4, %rcx |
| ; AVX-NEXT: addq $64, %rdi |
| ; AVX-NEXT: cmpq %rcx, %rdx |
| ; AVX-NEXT: jne .LBB1_8 |
| ; AVX-NEXT: .LBB1_3: |
| ; AVX-NEXT: testq %rax, %rax |
| ; AVX-NEXT: je .LBB1_6 |
| ; AVX-NEXT: # %bb.4: # %.preheader |
| ; AVX-NEXT: shlq $4, %rcx |
| ; AVX-NEXT: addq %rcx, %rsi |
| ; AVX-NEXT: shll $4, %eax |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB1_5: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: {vex} vpdpwssd (%rsi,%rcx), %xmm1, %xmm0 |
| ; AVX-NEXT: addq $16, %rcx |
| ; AVX-NEXT: cmpq %rcx, %rax |
| ; AVX-NEXT: jne .LBB1_5 |
| ; AVX-NEXT: .LBB1_6: |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: foo_128: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: testl %edi, %edi |
| ; AVX512-NEXT: jle .LBB1_6 |
| ; AVX512-NEXT: # %bb.1: |
| ; AVX512-NEXT: movl %edi, %edx |
| ; AVX512-NEXT: movl %edx, %eax |
| ; AVX512-NEXT: andl $3, %eax |
| ; AVX512-NEXT: cmpl $4, %edi |
| ; AVX512-NEXT: jae .LBB1_7 |
| ; AVX512-NEXT: # %bb.2: |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: jmp .LBB1_3 |
| ; AVX512-NEXT: .LBB1_7: |
| ; AVX512-NEXT: andl $-4, %edx |
| ; AVX512-NEXT: leaq 48(%rsi), %rdi |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB1_8: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vpdpwssd -48(%rdi), %xmm1, %xmm0 |
| ; AVX512-NEXT: vpmaddwd -32(%rdi), %xmm1, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX512-NEXT: vpmaddwd -16(%rdi), %xmm1, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX512-NEXT: vpmaddwd (%rdi), %xmm1, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm0, %xmm0 |
| ; AVX512-NEXT: addq $4, %rcx |
| ; AVX512-NEXT: addq $64, %rdi |
| ; AVX512-NEXT: cmpq %rcx, %rdx |
| ; AVX512-NEXT: jne .LBB1_8 |
| ; AVX512-NEXT: .LBB1_3: |
| ; AVX512-NEXT: testq %rax, %rax |
| ; AVX512-NEXT: je .LBB1_6 |
| ; AVX512-NEXT: # %bb.4: # %.preheader |
| ; AVX512-NEXT: shlq $4, %rcx |
| ; AVX512-NEXT: addq %rcx, %rsi |
| ; AVX512-NEXT: shll $4, %eax |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB1_5: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vpdpwssd (%rsi,%rcx), %xmm1, %xmm0 |
| ; AVX512-NEXT: addq $16, %rcx |
| ; AVX512-NEXT: cmpq %rcx, %rax |
| ; AVX512-NEXT: jne .LBB1_5 |
| ; AVX512-NEXT: .LBB1_6: |
| ; AVX512-NEXT: retq |
| %5 = icmp sgt i32 %0, 0 |
| br i1 %5, label %6, label %33 |
| |
| 6: ; preds = %4 |
| %7 = bitcast <2 x i64> %2 to <8 x i16> |
| %8 = bitcast <2 x i64> %1 to <4 x i32> |
| %9 = zext i32 %0 to i64 |
| %10 = and i64 %9, 3 |
| %11 = icmp ult i32 %0, 4 |
| br i1 %11, label %14, label %12 |
| |
| 12: ; preds = %6 |
| %13 = and i64 %9, 4294967292 |
| br label %35 |
| |
| 14: ; preds = %35, %6 |
| %15 = phi <4 x i32> [ undef, %6 ], [ %57, %35 ] |
| %16 = phi i64 [ 0, %6 ], [ %58, %35 ] |
| %17 = phi <4 x i32> [ %8, %6 ], [ %57, %35 ] |
| %18 = icmp eq i64 %10, 0 |
| br i1 %18, label %30, label %19 |
| |
| 19: ; preds = %14, %19 |
| %20 = phi i64 [ %27, %19 ], [ %16, %14 ] |
| %21 = phi <4 x i32> [ %26, %19 ], [ %17, %14 ] |
| %22 = phi i64 [ %28, %19 ], [ 0, %14 ] |
| %23 = getelementptr inbounds <2 x i64>, ptr %3, i64 %20 |
| %24 = load <8 x i16>, ptr %23, align 16 |
| %25 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %7, <8 x i16> %24) |
| %26 = add <4 x i32> %25, %21 |
| %27 = add nuw nsw i64 %20, 1 |
| %28 = add i64 %22, 1 |
| %29 = icmp eq i64 %28, %10 |
| br i1 %29, label %30, label %19 |
| |
| 30: ; preds = %19, %14 |
| %31 = phi <4 x i32> [ %15, %14 ], [ %26, %19 ] |
| %32 = bitcast <4 x i32> %31 to <2 x i64> |
| br label %33 |
| |
| 33: ; preds = %30, %4 |
| %34 = phi <2 x i64> [ %32, %30 ], [ %1, %4 ] |
| ret <2 x i64> %34 |
| |
| 35: ; preds = %35, %12 |
| %36 = phi i64 [ 0, %12 ], [ %58, %35 ] |
| %37 = phi <4 x i32> [ %8, %12 ], [ %57, %35 ] |
| %38 = phi i64 [ 0, %12 ], [ %59, %35 ] |
| %39 = getelementptr inbounds <2 x i64>, ptr %3, i64 %36 |
| %40 = load <8 x i16>, ptr %39, align 16 |
| %41 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %7, <8 x i16> %40) |
| %42 = add <4 x i32> %41, %37 |
| %43 = or disjoint i64 %36, 1 |
| %44 = getelementptr inbounds <2 x i64>, ptr %3, i64 %43 |
| %45 = load <8 x i16>, ptr %44, align 16 |
| %46 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %7, <8 x i16> %45) |
| %47 = add <4 x i32> %46, %42 |
| %48 = or disjoint i64 %36, 2 |
| %49 = getelementptr inbounds <2 x i64>, ptr %3, i64 %48 |
| %50 = load <8 x i16>, ptr %49, align 16 |
| %51 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %7, <8 x i16> %50) |
| %52 = add <4 x i32> %51, %47 |
| %53 = or disjoint i64 %36, 3 |
| %54 = getelementptr inbounds <2 x i64>, ptr %3, i64 %53 |
| %55 = load <8 x i16>, ptr %54, align 16 |
| %56 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %7, <8 x i16> %55) |
| %57 = add <4 x i32> %56, %52 |
| %58 = add nuw nsw i64 %36, 4 |
| %59 = add i64 %38, 4 |
| %60 = icmp eq i64 %59, %13 |
| br i1 %60, label %14, label %35 |
| } |
| |
| define void @bar_128(i32 %0, ptr %1, <2 x i64> %2, ptr %3) { |
| ; AVX-LABEL: bar_128: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: testl %edi, %edi |
| ; AVX-NEXT: jle .LBB2_5 |
| ; AVX-NEXT: # %bb.1: |
| ; AVX-NEXT: movl %edi, %eax |
| ; AVX-NEXT: cmpl $1, %edi |
| ; AVX-NEXT: jne .LBB2_6 |
| ; AVX-NEXT: # %bb.2: |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: jmp .LBB2_3 |
| ; AVX-NEXT: .LBB2_6: |
| ; AVX-NEXT: movl %eax, %edi |
| ; AVX-NEXT: andl $-2, %edi |
| ; AVX-NEXT: movl $16, %r8d |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB2_7: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: vmovdqa (%rsi,%r8), %xmm1 |
| ; AVX-NEXT: vpmaddwd -16(%rdx,%r8), %xmm0, %xmm2 |
| ; AVX-NEXT: vpaddd -16(%rsi,%r8), %xmm2, %xmm2 |
| ; AVX-NEXT: vmovdqa %xmm2, -16(%rsi,%r8) |
| ; AVX-NEXT: vpmaddwd (%rdx,%r8), %xmm0, %xmm2 |
| ; AVX-NEXT: vpaddd %xmm2, %xmm1, %xmm1 |
| ; AVX-NEXT: vmovdqa %xmm1, (%rsi,%r8) |
| ; AVX-NEXT: addq $2, %rcx |
| ; AVX-NEXT: addq $32, %r8 |
| ; AVX-NEXT: cmpq %rcx, %rdi |
| ; AVX-NEXT: jne .LBB2_7 |
| ; AVX-NEXT: .LBB2_3: |
| ; AVX-NEXT: testb $1, %al |
| ; AVX-NEXT: je .LBB2_5 |
| ; AVX-NEXT: # %bb.4: |
| ; AVX-NEXT: shlq $4, %rcx |
| ; AVX-NEXT: vmovdqa (%rsi,%rcx), %xmm1 |
| ; AVX-NEXT: {vex} vpdpwssd (%rdx,%rcx), %xmm0, %xmm1 |
| ; AVX-NEXT: vmovdqa %xmm1, (%rsi,%rcx) |
| ; AVX-NEXT: .LBB2_5: |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: bar_128: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: testl %edi, %edi |
| ; AVX512-NEXT: jle .LBB2_5 |
| ; AVX512-NEXT: # %bb.1: |
| ; AVX512-NEXT: movl %edi, %eax |
| ; AVX512-NEXT: cmpl $1, %edi |
| ; AVX512-NEXT: jne .LBB2_6 |
| ; AVX512-NEXT: # %bb.2: |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: jmp .LBB2_3 |
| ; AVX512-NEXT: .LBB2_6: |
| ; AVX512-NEXT: movl %eax, %edi |
| ; AVX512-NEXT: andl $-2, %edi |
| ; AVX512-NEXT: movl $16, %r8d |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB2_7: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vmovdqa (%rsi,%r8), %xmm1 |
| ; AVX512-NEXT: vpmaddwd -16(%rdx,%r8), %xmm0, %xmm2 |
| ; AVX512-NEXT: vpaddd -16(%rsi,%r8), %xmm2, %xmm2 |
| ; AVX512-NEXT: vmovdqa %xmm2, -16(%rsi,%r8) |
| ; AVX512-NEXT: vpmaddwd (%rdx,%r8), %xmm0, %xmm2 |
| ; AVX512-NEXT: vpaddd %xmm2, %xmm1, %xmm1 |
| ; AVX512-NEXT: vmovdqa %xmm1, (%rsi,%r8) |
| ; AVX512-NEXT: addq $2, %rcx |
| ; AVX512-NEXT: addq $32, %r8 |
| ; AVX512-NEXT: cmpq %rcx, %rdi |
| ; AVX512-NEXT: jne .LBB2_7 |
| ; AVX512-NEXT: .LBB2_3: |
| ; AVX512-NEXT: testb $1, %al |
| ; AVX512-NEXT: je .LBB2_5 |
| ; AVX512-NEXT: # %bb.4: |
| ; AVX512-NEXT: shlq $4, %rcx |
| ; AVX512-NEXT: vpmaddwd (%rdx,%rcx), %xmm0, %xmm0 |
| ; AVX512-NEXT: vpaddd (%rsi,%rcx), %xmm0, %xmm0 |
| ; AVX512-NEXT: vmovdqa %xmm0, (%rsi,%rcx) |
| ; AVX512-NEXT: .LBB2_5: |
| ; AVX512-NEXT: retq |
| %5 = icmp sgt i32 %0, 0 |
| br i1 %5, label %6, label %22 |
| |
| 6: ; preds = %4 |
| %7 = bitcast <2 x i64> %2 to <4 x i32> |
| %8 = zext i32 %0 to i64 |
| %9 = and i64 %8, 1 |
| %10 = icmp eq i32 %0, 1 |
| br i1 %10, label %13, label %11 |
| |
| 11: ; preds = %6 |
| %12 = and i64 %8, 4294967294 |
| br label %23 |
| |
| 13: ; preds = %23, %6 |
| %14 = phi i64 [ 0, %6 ], [ %37, %23 ] |
| %15 = icmp eq i64 %9, 0 |
| br i1 %15, label %22, label %16 |
| |
| 16: ; preds = %13 |
| %17 = getelementptr inbounds <2 x i64>, ptr %3, i64 %14 |
| %18 = load <4 x i32>, ptr %17, align 16 |
| %19 = getelementptr inbounds <2 x i64>, ptr %1, i64 %14 |
| %20 = load <4 x i32>, ptr %19, align 16 |
| %21 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %20, <4 x i32> %7, <4 x i32> %18) |
| store <4 x i32> %21, ptr %19, align 16 |
| br label %22 |
| |
| 22: ; preds = %16, %13, %4 |
| ret void |
| |
| 23: ; preds = %23, %11 |
| %24 = phi i64 [ 0, %11 ], [ %37, %23 ] |
| %25 = phi i64 [ 0, %11 ], [ %38, %23 ] |
| %26 = getelementptr inbounds <2 x i64>, ptr %3, i64 %24 |
| %27 = load <4 x i32>, ptr %26, align 16 |
| %28 = getelementptr inbounds <2 x i64>, ptr %1, i64 %24 |
| %29 = load <4 x i32>, ptr %28, align 16 |
| %30 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %29, <4 x i32> %7, <4 x i32> %27) |
| store <4 x i32> %30, ptr %28, align 16 |
| %31 = or disjoint i64 %24, 1 |
| %32 = getelementptr inbounds <2 x i64>, ptr %3, i64 %31 |
| %33 = load <4 x i32>, ptr %32, align 16 |
| %34 = getelementptr inbounds <2 x i64>, ptr %1, i64 %31 |
| %35 = load <4 x i32>, ptr %34, align 16 |
| %36 = tail call <4 x i32> @llvm.x86.avx512.vpdpwssd.128(<4 x i32> %35, <4 x i32> %7, <4 x i32> %33) |
| store <4 x i32> %36, ptr %34, align 16 |
| %37 = add nuw nsw i64 %24, 2 |
| %38 = add i64 %25, 2 |
| %39 = icmp eq i64 %38, %12 |
| br i1 %39, label %13, label %23 |
| } |
| |
| declare <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16>, <8 x i16>) #1 |
| |
| define <4 x i64> @foo_reg_256(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2, <4 x i64> %3, <4 x i64> %4, <4 x i64> %5) { |
| ; AVX-LABEL: foo_reg_256: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: {vex} vpdpwssd %ymm2, %ymm1, %ymm0 |
| ; AVX-NEXT: vpmaddwd %ymm3, %ymm1, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX-NEXT: vpmaddwd %ymm4, %ymm1, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX-NEXT: vpmaddwd %ymm5, %ymm1, %ymm1 |
| ; AVX-NEXT: vpaddd %ymm1, %ymm0, %ymm0 |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: foo_reg_256: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: vpdpwssd %ymm2, %ymm1, %ymm0 |
| ; AVX512-NEXT: vpmaddwd %ymm3, %ymm1, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX512-NEXT: vpmaddwd %ymm4, %ymm1, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX512-NEXT: vpmaddwd %ymm5, %ymm1, %ymm1 |
| ; AVX512-NEXT: vpaddd %ymm1, %ymm0, %ymm0 |
| ; AVX512-NEXT: retq |
| %7 = bitcast <4 x i64> %0 to <8 x i32> |
| %8 = bitcast <4 x i64> %1 to <8 x i32> |
| %9 = bitcast <4 x i64> %2 to <8 x i32> |
| %10 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %7, <8 x i32> %8, <8 x i32> %9) |
| %11 = bitcast <4 x i64> %3 to <8 x i32> |
| %12 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %10, <8 x i32> %8, <8 x i32> %11) |
| %13 = bitcast <4 x i64> %4 to <8 x i32> |
| %14 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %12, <8 x i32> %8, <8 x i32> %13) |
| %15 = bitcast <4 x i64> %5 to <8 x i32> |
| %16 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %14, <8 x i32> %8, <8 x i32> %15) |
| %17 = bitcast <8 x i32> %16 to <4 x i64> |
| ret <4 x i64> %17 |
| } |
| |
| ; __m256i foo(int cnt, __m256i c, __m256i b, __m256i *p) { |
| ; for (int i = 0; i < cnt; ++i) { |
| ; __m256i a = p[i]; |
| ; __m256i m = _mm256_madd_epi16 (b, a); |
| ; c = _mm256_add_epi32(m, c); |
| ; } |
| ; return c; |
| ; } |
| |
| define <4 x i64> @foo_256(i32 %0, <4 x i64> %1, <4 x i64> %2, ptr %3) { |
| ; AVX-LABEL: foo_256: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: testl %edi, %edi |
| ; AVX-NEXT: jle .LBB4_6 |
| ; AVX-NEXT: # %bb.1: |
| ; AVX-NEXT: movl %edi, %edx |
| ; AVX-NEXT: movl %edx, %eax |
| ; AVX-NEXT: andl $3, %eax |
| ; AVX-NEXT: cmpl $4, %edi |
| ; AVX-NEXT: jae .LBB4_7 |
| ; AVX-NEXT: # %bb.2: |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: jmp .LBB4_3 |
| ; AVX-NEXT: .LBB4_7: |
| ; AVX-NEXT: andl $-4, %edx |
| ; AVX-NEXT: leaq 96(%rsi), %rdi |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB4_8: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: {vex} vpdpwssd -96(%rdi), %ymm1, %ymm0 |
| ; AVX-NEXT: vpmaddwd -64(%rdi), %ymm1, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX-NEXT: vpmaddwd -32(%rdi), %ymm1, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX-NEXT: vpmaddwd (%rdi), %ymm1, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX-NEXT: addq $4, %rcx |
| ; AVX-NEXT: subq $-128, %rdi |
| ; AVX-NEXT: cmpq %rcx, %rdx |
| ; AVX-NEXT: jne .LBB4_8 |
| ; AVX-NEXT: .LBB4_3: |
| ; AVX-NEXT: testq %rax, %rax |
| ; AVX-NEXT: je .LBB4_6 |
| ; AVX-NEXT: # %bb.4: # %.preheader |
| ; AVX-NEXT: shlq $5, %rcx |
| ; AVX-NEXT: addq %rcx, %rsi |
| ; AVX-NEXT: shll $5, %eax |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB4_5: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: {vex} vpdpwssd (%rsi,%rcx), %ymm1, %ymm0 |
| ; AVX-NEXT: addq $32, %rcx |
| ; AVX-NEXT: cmpq %rcx, %rax |
| ; AVX-NEXT: jne .LBB4_5 |
| ; AVX-NEXT: .LBB4_6: |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: foo_256: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: testl %edi, %edi |
| ; AVX512-NEXT: jle .LBB4_6 |
| ; AVX512-NEXT: # %bb.1: |
| ; AVX512-NEXT: movl %edi, %edx |
| ; AVX512-NEXT: movl %edx, %eax |
| ; AVX512-NEXT: andl $3, %eax |
| ; AVX512-NEXT: cmpl $4, %edi |
| ; AVX512-NEXT: jae .LBB4_7 |
| ; AVX512-NEXT: # %bb.2: |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: jmp .LBB4_3 |
| ; AVX512-NEXT: .LBB4_7: |
| ; AVX512-NEXT: andl $-4, %edx |
| ; AVX512-NEXT: leaq 96(%rsi), %rdi |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB4_8: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vpdpwssd -96(%rdi), %ymm1, %ymm0 |
| ; AVX512-NEXT: vpmaddwd -64(%rdi), %ymm1, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX512-NEXT: vpmaddwd -32(%rdi), %ymm1, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX512-NEXT: vpmaddwd (%rdi), %ymm1, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm0 |
| ; AVX512-NEXT: addq $4, %rcx |
| ; AVX512-NEXT: subq $-128, %rdi |
| ; AVX512-NEXT: cmpq %rcx, %rdx |
| ; AVX512-NEXT: jne .LBB4_8 |
| ; AVX512-NEXT: .LBB4_3: |
| ; AVX512-NEXT: testq %rax, %rax |
| ; AVX512-NEXT: je .LBB4_6 |
| ; AVX512-NEXT: # %bb.4: # %.preheader |
| ; AVX512-NEXT: shlq $5, %rcx |
| ; AVX512-NEXT: addq %rcx, %rsi |
| ; AVX512-NEXT: shll $5, %eax |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB4_5: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vpdpwssd (%rsi,%rcx), %ymm1, %ymm0 |
| ; AVX512-NEXT: addq $32, %rcx |
| ; AVX512-NEXT: cmpq %rcx, %rax |
| ; AVX512-NEXT: jne .LBB4_5 |
| ; AVX512-NEXT: .LBB4_6: |
| ; AVX512-NEXT: retq |
| %5 = icmp sgt i32 %0, 0 |
| br i1 %5, label %6, label %33 |
| |
| 6: ; preds = %4 |
| %7 = bitcast <4 x i64> %2 to <16 x i16> |
| %8 = bitcast <4 x i64> %1 to <8 x i32> |
| %9 = zext i32 %0 to i64 |
| %10 = and i64 %9, 3 |
| %11 = icmp ult i32 %0, 4 |
| br i1 %11, label %14, label %12 |
| |
| 12: ; preds = %6 |
| %13 = and i64 %9, 4294967292 |
| br label %35 |
| |
| 14: ; preds = %35, %6 |
| %15 = phi <8 x i32> [ undef, %6 ], [ %57, %35 ] |
| %16 = phi i64 [ 0, %6 ], [ %58, %35 ] |
| %17 = phi <8 x i32> [ %8, %6 ], [ %57, %35 ] |
| %18 = icmp eq i64 %10, 0 |
| br i1 %18, label %30, label %19 |
| |
| 19: ; preds = %14, %19 |
| %20 = phi i64 [ %27, %19 ], [ %16, %14 ] |
| %21 = phi <8 x i32> [ %26, %19 ], [ %17, %14 ] |
| %22 = phi i64 [ %28, %19 ], [ 0, %14 ] |
| %23 = getelementptr inbounds <4 x i64>, ptr %3, i64 %20 |
| %24 = load <16 x i16>, ptr %23, align 32 |
| %25 = tail call <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16> %7, <16 x i16> %24) |
| %26 = add <8 x i32> %25, %21 |
| %27 = add nuw nsw i64 %20, 1 |
| %28 = add i64 %22, 1 |
| %29 = icmp eq i64 %28, %10 |
| br i1 %29, label %30, label %19 |
| |
| 30: ; preds = %19, %14 |
| %31 = phi <8 x i32> [ %15, %14 ], [ %26, %19 ] |
| %32 = bitcast <8 x i32> %31 to <4 x i64> |
| br label %33 |
| |
| 33: ; preds = %30, %4 |
| %34 = phi <4 x i64> [ %32, %30 ], [ %1, %4 ] |
| ret <4 x i64> %34 |
| |
| 35: ; preds = %35, %12 |
| %36 = phi i64 [ 0, %12 ], [ %58, %35 ] |
| %37 = phi <8 x i32> [ %8, %12 ], [ %57, %35 ] |
| %38 = phi i64 [ 0, %12 ], [ %59, %35 ] |
| %39 = getelementptr inbounds <4 x i64>, ptr %3, i64 %36 |
| %40 = load <16 x i16>, ptr %39, align 32 |
| %41 = tail call <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16> %7, <16 x i16> %40) |
| %42 = add <8 x i32> %41, %37 |
| %43 = or disjoint i64 %36, 1 |
| %44 = getelementptr inbounds <4 x i64>, ptr %3, i64 %43 |
| %45 = load <16 x i16>, ptr %44, align 32 |
| %46 = tail call <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16> %7, <16 x i16> %45) |
| %47 = add <8 x i32> %46, %42 |
| %48 = or disjoint i64 %36, 2 |
| %49 = getelementptr inbounds <4 x i64>, ptr %3, i64 %48 |
| %50 = load <16 x i16>, ptr %49, align 32 |
| %51 = tail call <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16> %7, <16 x i16> %50) |
| %52 = add <8 x i32> %51, %47 |
| %53 = or disjoint i64 %36, 3 |
| %54 = getelementptr inbounds <4 x i64>, ptr %3, i64 %53 |
| %55 = load <16 x i16>, ptr %54, align 32 |
| %56 = tail call <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16> %7, <16 x i16> %55) |
| %57 = add <8 x i32> %56, %52 |
| %58 = add nuw nsw i64 %36, 4 |
| %59 = add i64 %38, 4 |
| %60 = icmp eq i64 %59, %13 |
| br i1 %60, label %14, label %35 |
| } |
| declare <8 x i32> @llvm.x86.avx2.pmadd.wd(<16 x i16>, <16 x i16>) |
| |
| ; void bar(int cnt, __m256i *c, __m256i b, __m256i *p) { |
| ; for (int i = 0; i < cnt; ++i) { |
| ; __m256i a = p[i]; |
| ; c[i] = _mm256_dpwssd_epi32(c[i], b, a); |
| ; } |
| ; } |
| define void @bar_256(i32 %0, ptr %1, <4 x i64> %2, ptr %3) { |
| ; AVX-LABEL: bar_256: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: testl %edi, %edi |
| ; AVX-NEXT: jle .LBB5_5 |
| ; AVX-NEXT: # %bb.1: |
| ; AVX-NEXT: movl %edi, %eax |
| ; AVX-NEXT: cmpl $1, %edi |
| ; AVX-NEXT: jne .LBB5_6 |
| ; AVX-NEXT: # %bb.2: |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: jmp .LBB5_3 |
| ; AVX-NEXT: .LBB5_6: |
| ; AVX-NEXT: movl %eax, %edi |
| ; AVX-NEXT: andl $-2, %edi |
| ; AVX-NEXT: movl $32, %r8d |
| ; AVX-NEXT: xorl %ecx, %ecx |
| ; AVX-NEXT: .p2align 4, 0x90 |
| ; AVX-NEXT: .LBB5_7: # =>This Inner Loop Header: Depth=1 |
| ; AVX-NEXT: vmovdqa (%rsi,%r8), %ymm1 |
| ; AVX-NEXT: vpmaddwd -32(%rdx,%r8), %ymm0, %ymm2 |
| ; AVX-NEXT: vpaddd -32(%rsi,%r8), %ymm2, %ymm2 |
| ; AVX-NEXT: vmovdqa %ymm2, -32(%rsi,%r8) |
| ; AVX-NEXT: vpmaddwd (%rdx,%r8), %ymm0, %ymm2 |
| ; AVX-NEXT: vpaddd %ymm2, %ymm1, %ymm1 |
| ; AVX-NEXT: vmovdqa %ymm1, (%rsi,%r8) |
| ; AVX-NEXT: addq $2, %rcx |
| ; AVX-NEXT: addq $64, %r8 |
| ; AVX-NEXT: cmpq %rcx, %rdi |
| ; AVX-NEXT: jne .LBB5_7 |
| ; AVX-NEXT: .LBB5_3: |
| ; AVX-NEXT: testb $1, %al |
| ; AVX-NEXT: je .LBB5_5 |
| ; AVX-NEXT: # %bb.4: |
| ; AVX-NEXT: shlq $5, %rcx |
| ; AVX-NEXT: vmovdqa (%rsi,%rcx), %ymm1 |
| ; AVX-NEXT: {vex} vpdpwssd (%rdx,%rcx), %ymm0, %ymm1 |
| ; AVX-NEXT: vmovdqa %ymm1, (%rsi,%rcx) |
| ; AVX-NEXT: .LBB5_5: |
| ; AVX-NEXT: vzeroupper |
| ; AVX-NEXT: retq |
| ; |
| ; AVX512-LABEL: bar_256: |
| ; AVX512: # %bb.0: |
| ; AVX512-NEXT: testl %edi, %edi |
| ; AVX512-NEXT: jle .LBB5_5 |
| ; AVX512-NEXT: # %bb.1: |
| ; AVX512-NEXT: movl %edi, %eax |
| ; AVX512-NEXT: cmpl $1, %edi |
| ; AVX512-NEXT: jne .LBB5_6 |
| ; AVX512-NEXT: # %bb.2: |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: jmp .LBB5_3 |
| ; AVX512-NEXT: .LBB5_6: |
| ; AVX512-NEXT: movl %eax, %edi |
| ; AVX512-NEXT: andl $-2, %edi |
| ; AVX512-NEXT: movl $32, %r8d |
| ; AVX512-NEXT: xorl %ecx, %ecx |
| ; AVX512-NEXT: .p2align 4, 0x90 |
| ; AVX512-NEXT: .LBB5_7: # =>This Inner Loop Header: Depth=1 |
| ; AVX512-NEXT: vmovdqa (%rsi,%r8), %ymm1 |
| ; AVX512-NEXT: vpmaddwd -32(%rdx,%r8), %ymm0, %ymm2 |
| ; AVX512-NEXT: vpaddd -32(%rsi,%r8), %ymm2, %ymm2 |
| ; AVX512-NEXT: vmovdqa %ymm2, -32(%rsi,%r8) |
| ; AVX512-NEXT: vpmaddwd (%rdx,%r8), %ymm0, %ymm2 |
| ; AVX512-NEXT: vpaddd %ymm2, %ymm1, %ymm1 |
| ; AVX512-NEXT: vmovdqa %ymm1, (%rsi,%r8) |
| ; AVX512-NEXT: addq $2, %rcx |
| ; AVX512-NEXT: addq $64, %r8 |
| ; AVX512-NEXT: cmpq %rcx, %rdi |
| ; AVX512-NEXT: jne .LBB5_7 |
| ; AVX512-NEXT: .LBB5_3: |
| ; AVX512-NEXT: testb $1, %al |
| ; AVX512-NEXT: je .LBB5_5 |
| ; AVX512-NEXT: # %bb.4: |
| ; AVX512-NEXT: shlq $5, %rcx |
| ; AVX512-NEXT: vpmaddwd (%rdx,%rcx), %ymm0, %ymm0 |
| ; AVX512-NEXT: vpaddd (%rsi,%rcx), %ymm0, %ymm0 |
| ; AVX512-NEXT: vmovdqa %ymm0, (%rsi,%rcx) |
| ; AVX512-NEXT: .LBB5_5: |
| ; AVX512-NEXT: vzeroupper |
| ; AVX512-NEXT: retq |
| %5 = icmp sgt i32 %0, 0 |
| br i1 %5, label %6, label %22 |
| |
| 6: ; preds = %4 |
| %7 = bitcast <4 x i64> %2 to <8 x i32> |
| %8 = zext i32 %0 to i64 |
| %9 = and i64 %8, 1 |
| %10 = icmp eq i32 %0, 1 |
| br i1 %10, label %13, label %11 |
| |
| 11: ; preds = %6 |
| %12 = and i64 %8, 4294967294 |
| br label %23 |
| |
| 13: ; preds = %23, %6 |
| %14 = phi i64 [ 0, %6 ], [ %37, %23 ] |
| %15 = icmp eq i64 %9, 0 |
| br i1 %15, label %22, label %16 |
| |
| 16: ; preds = %13 |
| %17 = getelementptr inbounds <4 x i64>, ptr %3, i64 %14 |
| %18 = load <8 x i32>, ptr %17, align 32 |
| %19 = getelementptr inbounds <4 x i64>, ptr %1, i64 %14 |
| %20 = load <8 x i32>, ptr %19, align 32 |
| %21 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %20, <8 x i32> %7, <8 x i32> %18) |
| store <8 x i32> %21, ptr %19, align 32 |
| br label %22 |
| |
| 22: ; preds = %16, %13, %4 |
| ret void |
| |
| 23: ; preds = %23, %11 |
| %24 = phi i64 [ 0, %11 ], [ %37, %23 ] |
| %25 = phi i64 [ 0, %11 ], [ %38, %23 ] |
| %26 = getelementptr inbounds <4 x i64>, ptr %3, i64 %24 |
| %27 = load <8 x i32>, ptr %26, align 32 |
| %28 = getelementptr inbounds <4 x i64>, ptr %1, i64 %24 |
| %29 = load <8 x i32>, ptr %28, align 32 |
| %30 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %29, <8 x i32> %7, <8 x i32> %27) |
| store <8 x i32> %30, ptr %28, align 32 |
| %31 = or disjoint i64 %24, 1 |
| %32 = getelementptr inbounds <4 x i64>, ptr %3, i64 %31 |
| %33 = load <8 x i32>, ptr %32, align 32 |
| %34 = getelementptr inbounds <4 x i64>, ptr %1, i64 %31 |
| %35 = load <8 x i32>, ptr %34, align 32 |
| %36 = tail call <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32> %35, <8 x i32> %7, <8 x i32> %33) |
| store <8 x i32> %36, ptr %34, align 32 |
| %37 = add nuw nsw i64 %24, 2 |
| %38 = add i64 %25, 2 |
| %39 = icmp eq i64 %38, %12 |
| br i1 %39, label %13, label %23 |
| } |
| declare <8 x i32> @llvm.x86.avx512.vpdpwssd.256(<8 x i32>, <8 x i32>, <8 x i32>) |
| ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: |
| ; ADL: {{.*}} |
| ; SPR: {{.*}} |