blob: 766b176743d7f35e5fd9e6028f72cb529c626cf2 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2
; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE42
; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2
; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512
define i16 @umulh_i16(i16 %x, i16 %y) nounwind {
; CHECK-LABEL: umulh_i16:
; CHECK: # %bb.0:
; CHECK-NEXT: movzwl %si, %ecx
; CHECK-NEXT: movzwl %di, %eax
; CHECK-NEXT: imull %ecx, %eax
; CHECK-NEXT: shrl $16, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%r = call i16 @llvm.umulh(i16 %x, i16 %y)
ret i16 %r
}
define i32 @umulh_i32(i32 %x, i32 %y) nounwind {
; CHECK-LABEL: umulh_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %esi, %ecx
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: imulq %rcx, %rax
; CHECK-NEXT: shrq $32, %rax
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
; CHECK-NEXT: retq
%r = call i32 @llvm.umulh(i32 %x, i32 %y)
ret i32 %r
}
define i64 @umulh_i64(i64 %x, i64 %y) nounwind {
; SSE-LABEL: umulh_i64:
; SSE: # %bb.0:
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: mulq %rsi
; SSE-NEXT: movq %rdx, %rax
; SSE-NEXT: retq
;
; AVX-LABEL: umulh_i64:
; AVX: # %bb.0:
; AVX-NEXT: movq %rdi, %rdx
; AVX-NEXT: mulxq %rsi, %rax, %rax
; AVX-NEXT: retq
%r = call i64 @llvm.umulh(i64 %x, i64 %y)
ret i64 %r
}
define i96 @umulh_i96(i96 %x, i96 %y) nounwind {
; SSE-LABEL: umulh_i96:
; SSE: # %bb.0:
; SSE-NEXT: movq %rdx, %r8
; SSE-NEXT: movl %ecx, %r10d
; SSE-NEXT: shldq $32, %rdi, %rsi
; SSE-NEXT: shlq $32, %rdi
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: mulq %rdx
; SSE-NEXT: movq %rdx, %r9
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %r8
; SSE-NEXT: movq %rdx, %rcx
; SSE-NEXT: movq %rax, %r8
; SSE-NEXT: addq %r9, %r8
; SSE-NEXT: adcq $0, %rcx
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: mulq %r10
; SSE-NEXT: addq %r8, %rax
; SSE-NEXT: adcq %rdx, %rcx
; SSE-NEXT: setb %dil
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %r10
; SSE-NEXT: movzbl %dil, %esi
; SSE-NEXT: addq %rcx, %rax
; SSE-NEXT: adcq %rsi, %rdx
; SSE-NEXT: retq
;
; AVX2-LABEL: umulh_i96:
; AVX2: # %bb.0:
; AVX2-NEXT: movq %rdi, %rax
; AVX2-NEXT: shlq $32, %rax
; AVX2-NEXT: mulxq %rax, %r8, %r8
; AVX2-NEXT: shldq $32, %rdi, %rsi
; AVX2-NEXT: mulxq %rsi, %rdi, %r9
; AVX2-NEXT: addq %r8, %rdi
; AVX2-NEXT: adcq $0, %r9
; AVX2-NEXT: movl %ecx, %ecx
; AVX2-NEXT: movq %rax, %rdx
; AVX2-NEXT: mulxq %rcx, %rax, %r8
; AVX2-NEXT: addq %rdi, %rax
; AVX2-NEXT: adcq %r9, %r8
; AVX2-NEXT: setb %dil
; AVX2-NEXT: movq %rsi, %rdx
; AVX2-NEXT: mulxq %rcx, %rax, %rdx
; AVX2-NEXT: movzbl %dil, %ecx
; AVX2-NEXT: addq %r8, %rax
; AVX2-NEXT: adcq %rcx, %rdx
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_i96:
; AVX512: # %bb.0:
; AVX512-NEXT: shldq $32, %rdi, %rsi
; AVX512-NEXT: shlq $32, %rdi
; AVX512-NEXT: mulxq %rdi, %rax, %rax
; AVX512-NEXT: movl %ecx, %ecx
; AVX512-NEXT: mulxq %rsi, %r8, %r9
; AVX512-NEXT: addq %rax, %r8
; AVX512-NEXT: adcq $0, %r9
; AVX512-NEXT: movq %rdi, %rdx
; AVX512-NEXT: mulxq %rcx, %rax, %rdi
; AVX512-NEXT: addq %r8, %rax
; AVX512-NEXT: adcq %r9, %rdi
; AVX512-NEXT: setb %al
; AVX512-NEXT: movzbl %al, %r8d
; AVX512-NEXT: movq %rsi, %rdx
; AVX512-NEXT: mulxq %rcx, %rax, %rdx
; AVX512-NEXT: addq %rdi, %rax
; AVX512-NEXT: adcq %r8, %rdx
; AVX512-NEXT: retq
%r = call i96 @llvm.umulh(i96 %x, i96 %y)
ret i96 %r
}
define i128 @umulh_i128(i128 %x, i128 %y) nounwind {
; SSE-LABEL: umulh_i128:
; SSE: # %bb.0:
; SSE-NEXT: movq %rdx, %r8
; SSE-NEXT: movq %rdi, %r9
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: mulq %rdx
; SSE-NEXT: movq %rdx, %r10
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %r8
; SSE-NEXT: movq %rdx, %rdi
; SSE-NEXT: movq %rax, %r8
; SSE-NEXT: addq %r10, %r8
; SSE-NEXT: adcq $0, %rdi
; SSE-NEXT: movq %r9, %rax
; SSE-NEXT: mulq %rcx
; SSE-NEXT: addq %r8, %rax
; SSE-NEXT: adcq %rdx, %rdi
; SSE-NEXT: setb %r8b
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %rcx
; SSE-NEXT: movzbl %r8b, %ecx
; SSE-NEXT: addq %rdi, %rax
; SSE-NEXT: adcq %rcx, %rdx
; SSE-NEXT: retq
;
; AVX2-LABEL: umulh_i128:
; AVX2: # %bb.0:
; AVX2-NEXT: mulxq %rdi, %rax, %rax
; AVX2-NEXT: mulxq %rsi, %r8, %r9
; AVX2-NEXT: addq %rax, %r8
; AVX2-NEXT: adcq $0, %r9
; AVX2-NEXT: movq %rdi, %rdx
; AVX2-NEXT: mulxq %rcx, %rax, %rdi
; AVX2-NEXT: addq %r8, %rax
; AVX2-NEXT: adcq %r9, %rdi
; AVX2-NEXT: setb %r8b
; AVX2-NEXT: movq %rsi, %rdx
; AVX2-NEXT: mulxq %rcx, %rax, %rdx
; AVX2-NEXT: movzbl %r8b, %ecx
; AVX2-NEXT: addq %rdi, %rax
; AVX2-NEXT: adcq %rcx, %rdx
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_i128:
; AVX512: # %bb.0:
; AVX512-NEXT: mulxq %rdi, %rax, %rax
; AVX512-NEXT: mulxq %rsi, %r8, %r9
; AVX512-NEXT: addq %rax, %r8
; AVX512-NEXT: adcq $0, %r9
; AVX512-NEXT: movq %rdi, %rdx
; AVX512-NEXT: mulxq %rcx, %rax, %rdi
; AVX512-NEXT: addq %r8, %rax
; AVX512-NEXT: adcq %r9, %rdi
; AVX512-NEXT: setb %al
; AVX512-NEXT: movzbl %al, %r8d
; AVX512-NEXT: movq %rsi, %rdx
; AVX512-NEXT: mulxq %rcx, %rax, %rdx
; AVX512-NEXT: addq %rdi, %rax
; AVX512-NEXT: adcq %r8, %rdx
; AVX512-NEXT: retq
%r = call i128 @llvm.umulh(i128 %x, i128 %y)
ret i128 %r
}
define <8 x i8> @umulh_v8i8(<8 x i8> %x, <8 x i8> %y) nounwind {
; SSE2-LABEL: umulh_v8i8:
; SSE2: # %bb.0:
; SSE2-NEXT: pxor %xmm2, %xmm2
; SSE2-NEXT: movdqa %xmm1, %xmm3
; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm2[8],xmm3[9],xmm2[9],xmm3[10],xmm2[10],xmm3[11],xmm2[11],xmm3[12],xmm2[12],xmm3[13],xmm2[13],xmm3[14],xmm2[14],xmm3[15],xmm2[15]
; SSE2-NEXT: movdqa %xmm0, %xmm4
; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15]
; SSE2-NEXT: pmullw %xmm3, %xmm4
; SSE2-NEXT: psrlw $8, %xmm4
; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7]
; SSE2-NEXT: pmullw %xmm1, %xmm0
; SSE2-NEXT: psrlw $8, %xmm0
; SSE2-NEXT: packuswb %xmm4, %xmm0
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v8i8:
; SSE42: # %bb.0:
; SSE42-NEXT: pxor %xmm3, %xmm3
; SSE42-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
; SSE42-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm3[8],xmm1[9],xmm3[9],xmm1[10],xmm3[10],xmm1[11],xmm3[11],xmm1[12],xmm3[12],xmm1[13],xmm3[13],xmm1[14],xmm3[14],xmm1[15],xmm3[15]
; SSE42-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
; SSE42-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15]
; SSE42-NEXT: pmullw %xmm1, %xmm0
; SSE42-NEXT: psrlw $8, %xmm0
; SSE42-NEXT: pmullw %xmm4, %xmm2
; SSE42-NEXT: psrlw $8, %xmm2
; SSE42-NEXT: packuswb %xmm0, %xmm2
; SSE42-NEXT: movdqa %xmm2, %xmm0
; SSE42-NEXT: retq
;
; AVX2-LABEL: umulh_v8i8:
; AVX2: # %bb.0:
; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero
; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero
; AVX2-NEXT: vpmullw %ymm1, %ymm0, %ymm0
; AVX2-NEXT: vpsrlw $8, %ymm0, %ymm0
; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1
; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v8i8:
; AVX512: # %bb.0:
; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero
; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero
; AVX512-NEXT: vpmullw %ymm1, %ymm0, %ymm0
; AVX512-NEXT: vpsrlw $8, %ymm0, %ymm0
; AVX512-NEXT: vpmovwb %ymm0, %xmm0
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%r = call <8 x i8> @llvm.umulh(<8 x i8> %x, <8 x i8> %y)
ret <8 x i8> %r
}
define <4 x i16> @umulh_v4i16(<4 x i16> %x, <4 x i16> %y) nounwind {
; SSE-LABEL: umulh_v4i16:
; SSE: # %bb.0:
; SSE-NEXT: pmulhuw %xmm1, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: umulh_v4i16:
; AVX: # %bb.0:
; AVX-NEXT: vpmulhuw %xmm1, %xmm0, %xmm0
; AVX-NEXT: retq
%r = call <4 x i16> @llvm.umulh(<4 x i16> %x, <4 x i16> %y)
ret <4 x i16> %r
}
define <2 x i32> @umulh_v2i32(<2 x i32> %x, <2 x i32> %y) nounwind {
; SSE2-LABEL: umulh_v2i32:
; SSE2: # %bb.0:
; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm1, %xmm0
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,3,2,3]
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm2, %xmm1
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,3,2,3]
; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v2i32:
; SSE42: # %bb.0:
; SSE42-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; SSE42-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; SSE42-NEXT: pmuludq %xmm2, %xmm3
; SSE42-NEXT: pmuludq %xmm1, %xmm0
; SSE42-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; SSE42-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7]
; SSE42-NEXT: retq
;
; AVX2-LABEL: umulh_v2i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; AVX2-NEXT: vpshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; AVX2-NEXT: vpmuludq %xmm2, %xmm3, %xmm2
; AVX2-NEXT: vpmuludq %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3]
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v2i32:
; AVX512: # %bb.0:
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm2
; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm1
; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [1,5,3,7]
; AVX512-NEXT: vpermi2d %xmm1, %xmm2, %xmm0
; AVX512-NEXT: retq
%r = call <2 x i32> @llvm.umulh(<2 x i32> %x, <2 x i32> %y)
ret <2 x i32> %r
}
define <1 x i64> @umulh_v1i64(<1 x i64> %x, <1 x i64> %y) nounwind {
; SSE-LABEL: umulh_v1i64:
; SSE: # %bb.0:
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: mulq %rsi
; SSE-NEXT: movq %rdx, %rax
; SSE-NEXT: retq
;
; AVX-LABEL: umulh_v1i64:
; AVX: # %bb.0:
; AVX-NEXT: movq %rdi, %rdx
; AVX-NEXT: mulxq %rsi, %rax, %rax
; AVX-NEXT: retq
%r = call <1 x i64> @llvm.umulh(<1 x i64> %x, <1 x i64> %y)
ret <1 x i64> %r
}
define <16 x i8> @umulh_v16i8(<16 x i8> %x, <16 x i8> %y) nounwind {
; SSE2-LABEL: umulh_v16i8:
; SSE2: # %bb.0:
; SSE2-NEXT: pxor %xmm2, %xmm2
; SSE2-NEXT: movdqa %xmm1, %xmm3
; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm2[8],xmm3[9],xmm2[9],xmm3[10],xmm2[10],xmm3[11],xmm2[11],xmm3[12],xmm2[12],xmm3[13],xmm2[13],xmm3[14],xmm2[14],xmm3[15],xmm2[15]
; SSE2-NEXT: movdqa %xmm0, %xmm4
; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15]
; SSE2-NEXT: pmullw %xmm3, %xmm4
; SSE2-NEXT: psrlw $8, %xmm4
; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7]
; SSE2-NEXT: pmullw %xmm1, %xmm0
; SSE2-NEXT: psrlw $8, %xmm0
; SSE2-NEXT: packuswb %xmm4, %xmm0
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v16i8:
; SSE42: # %bb.0:
; SSE42-NEXT: pxor %xmm3, %xmm3
; SSE42-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
; SSE42-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm3[8],xmm1[9],xmm3[9],xmm1[10],xmm3[10],xmm1[11],xmm3[11],xmm1[12],xmm3[12],xmm1[13],xmm3[13],xmm1[14],xmm3[14],xmm1[15],xmm3[15]
; SSE42-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
; SSE42-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15]
; SSE42-NEXT: pmullw %xmm1, %xmm0
; SSE42-NEXT: psrlw $8, %xmm0
; SSE42-NEXT: pmullw %xmm4, %xmm2
; SSE42-NEXT: psrlw $8, %xmm2
; SSE42-NEXT: packuswb %xmm0, %xmm2
; SSE42-NEXT: movdqa %xmm2, %xmm0
; SSE42-NEXT: retq
;
; AVX2-LABEL: umulh_v16i8:
; AVX2: # %bb.0:
; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero
; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero
; AVX2-NEXT: vpmullw %ymm1, %ymm0, %ymm0
; AVX2-NEXT: vpsrlw $8, %ymm0, %ymm0
; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1
; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v16i8:
; AVX512: # %bb.0:
; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero
; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero
; AVX512-NEXT: vpmullw %ymm1, %ymm0, %ymm0
; AVX512-NEXT: vpsrlw $8, %ymm0, %ymm0
; AVX512-NEXT: vpmovwb %ymm0, %xmm0
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%r = call <16 x i8> @llvm.umulh(<16 x i8> %x, <16 x i8> %y)
ret <16 x i8> %r
}
define <8 x i16> @umulh_v8i16(<8 x i16> %x, <8 x i16> %y) nounwind {
; SSE-LABEL: umulh_v8i16:
; SSE: # %bb.0:
; SSE-NEXT: pmulhuw %xmm1, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: umulh_v8i16:
; AVX: # %bb.0:
; AVX-NEXT: vpmulhuw %xmm1, %xmm0, %xmm0
; AVX-NEXT: retq
%r = call <8 x i16> @llvm.umulh(<8 x i16> %x, <8 x i16> %y)
ret <8 x i16> %r
}
define <4 x i32> @umulh_v4i32(<4 x i32> %x, <4 x i32> %y) nounwind {
; SSE2-LABEL: umulh_v4i32:
; SSE2: # %bb.0:
; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm1, %xmm0
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,3,2,3]
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm2, %xmm1
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,3,2,3]
; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v4i32:
; SSE42: # %bb.0:
; SSE42-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; SSE42-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; SSE42-NEXT: pmuludq %xmm2, %xmm3
; SSE42-NEXT: pmuludq %xmm1, %xmm0
; SSE42-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; SSE42-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7]
; SSE42-NEXT: retq
;
; AVX2-LABEL: umulh_v4i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; AVX2-NEXT: vpshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; AVX2-NEXT: vpmuludq %xmm2, %xmm3, %xmm2
; AVX2-NEXT: vpmuludq %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3]
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v4i32:
; AVX512: # %bb.0:
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm2
; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm1
; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [1,5,3,7]
; AVX512-NEXT: vpermi2d %xmm1, %xmm2, %xmm0
; AVX512-NEXT: retq
%r = call <4 x i32> @llvm.umulh(<4 x i32> %x, <4 x i32> %y)
ret <4 x i32> %r
}
define <2 x i64> @umulh_v2i64(<2 x i64> %x, <2 x i64> %y) nounwind {
; SSE2-LABEL: umulh_v2i64:
; SSE2: # %bb.0:
; SSE2-NEXT: movq %xmm0, %rax
; SSE2-NEXT: movq %xmm1, %rcx
; SSE2-NEXT: mulq %rcx
; SSE2-NEXT: movq %rdx, %xmm2
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3]
; SSE2-NEXT: movq %xmm0, %rax
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
; SSE2-NEXT: movq %xmm0, %rcx
; SSE2-NEXT: mulq %rcx
; SSE2-NEXT: movq %rdx, %xmm0
; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0]
; SSE2-NEXT: movdqa %xmm2, %xmm0
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v2i64:
; SSE42: # %bb.0:
; SSE42-NEXT: pextrq $1, %xmm0, %rax
; SSE42-NEXT: pextrq $1, %xmm1, %rcx
; SSE42-NEXT: mulq %rcx
; SSE42-NEXT: movq %rdx, %xmm2
; SSE42-NEXT: movq %xmm0, %rax
; SSE42-NEXT: movq %xmm1, %rcx
; SSE42-NEXT: mulq %rcx
; SSE42-NEXT: movq %rdx, %xmm0
; SSE42-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
; SSE42-NEXT: retq
;
; AVX-LABEL: umulh_v2i64:
; AVX: # %bb.0:
; AVX-NEXT: vpextrq $1, %xmm0, %rdx
; AVX-NEXT: vpextrq $1, %xmm1, %rax
; AVX-NEXT: mulxq %rax, %rax, %rax
; AVX-NEXT: vmovq %rax, %xmm2
; AVX-NEXT: vmovq %xmm0, %rdx
; AVX-NEXT: vmovq %xmm1, %rax
; AVX-NEXT: mulxq %rax, %rax, %rax
; AVX-NEXT: vmovq %rax, %xmm0
; AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
; AVX-NEXT: retq
%r = call <2 x i64> @llvm.umulh(<2 x i64> %x, <2 x i64> %y)
ret <2 x i64> %r
}
define <3 x i32> @umulh_v3i32(<3 x i32> %x, <3 x i32> %y) nounwind {
; SSE2-LABEL: umulh_v3i32:
; SSE2: # %bb.0:
; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm1, %xmm0
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,3,2,3]
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; SSE2-NEXT: pmuludq %xmm2, %xmm1
; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,3,2,3]
; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v3i32:
; SSE42: # %bb.0:
; SSE42-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; SSE42-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; SSE42-NEXT: pmuludq %xmm2, %xmm3
; SSE42-NEXT: pmuludq %xmm1, %xmm0
; SSE42-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; SSE42-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7]
; SSE42-NEXT: retq
;
; AVX2-LABEL: umulh_v3i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3]
; AVX2-NEXT: vpshufd {{.*#+}} xmm3 = xmm0[1,1,3,3]
; AVX2-NEXT: vpmuludq %xmm2, %xmm3, %xmm2
; AVX2-NEXT: vpmuludq %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3]
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v3i32:
; AVX512: # %bb.0:
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm2
; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3]
; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512-NEXT: vpmuludq %xmm1, %xmm0, %xmm1
; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [1,5,3,7]
; AVX512-NEXT: vpermi2d %xmm1, %xmm2, %xmm0
; AVX512-NEXT: retq
%r = call <3 x i32> @llvm.umulh(<3 x i32> %x, <3 x i32> %y)
ret <3 x i32> %r
}
define <2 x i48> @umulh_v2i48(<2 x i48> %x, <2 x i48> %y) nounwind {
; SSE2-LABEL: umulh_v2i48:
; SSE2: # %bb.0:
; SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; SSE2-NEXT: psllq $16, %xmm0
; SSE2-NEXT: movq %xmm0, %rax
; SSE2-NEXT: movq %xmm1, %rcx
; SSE2-NEXT: mulq %rcx
; SSE2-NEXT: movq %rdx, %xmm2
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3]
; SSE2-NEXT: movq %xmm0, %rax
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
; SSE2-NEXT: movq %xmm0, %rcx
; SSE2-NEXT: mulq %rcx
; SSE2-NEXT: movq %rdx, %xmm0
; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0]
; SSE2-NEXT: movdqa %xmm2, %xmm0
; SSE2-NEXT: retq
;
; SSE42-LABEL: umulh_v2i48:
; SSE42: # %bb.0:
; SSE42-NEXT: pxor %xmm2, %xmm2
; SSE42-NEXT: pblendw {{.*#+}} xmm2 = xmm1[0,1,2],xmm2[3],xmm1[4,5,6],xmm2[7]
; SSE42-NEXT: pextrq $1, %xmm2, %rcx
; SSE42-NEXT: psllq $16, %xmm0
; SSE42-NEXT: pextrq $1, %xmm0, %rax
; SSE42-NEXT: mulq %rcx
; SSE42-NEXT: movq %rdx, %xmm1
; SSE42-NEXT: movq %xmm2, %rcx
; SSE42-NEXT: movq %xmm0, %rax
; SSE42-NEXT: mulq %rcx
; SSE42-NEXT: movq %rdx, %xmm0
; SSE42-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; SSE42-NEXT: retq
;
; AVX-LABEL: umulh_v2i48:
; AVX: # %bb.0:
; AVX-NEXT: vpxor %xmm2, %xmm2, %xmm2
; AVX-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[3],xmm1[4,5,6],xmm2[7]
; AVX-NEXT: vpextrq $1, %xmm1, %rax
; AVX-NEXT: vpsllq $16, %xmm0, %xmm0
; AVX-NEXT: vpextrq $1, %xmm0, %rdx
; AVX-NEXT: mulxq %rax, %rax, %rax
; AVX-NEXT: vmovq %rax, %xmm2
; AVX-NEXT: vmovq %xmm1, %rax
; AVX-NEXT: vmovq %xmm0, %rdx
; AVX-NEXT: mulxq %rax, %rax, %rax
; AVX-NEXT: vmovq %rax, %xmm0
; AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
; AVX-NEXT: retq
%r = call <2 x i48> @llvm.umulh(<2 x i48> %x, <2 x i48> %y)
ret <2 x i48> %r
}
define <2 x i128> @umulh_v2i128(<2 x i128> %x, <2 x i128> %y) nounwind {
; SSE-LABEL: umulh_v2i128:
; SSE: # %bb.0:
; SSE-NEXT: pushq %r15
; SSE-NEXT: pushq %r14
; SSE-NEXT: pushq %r12
; SSE-NEXT: pushq %rbx
; SSE-NEXT: movq %rdx, %r10
; SSE-NEXT: movq {{[0-9]+}}(%rsp), %r15
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %r9
; SSE-NEXT: movq %rdx, %r11
; SSE-NEXT: movq %r10, %rax
; SSE-NEXT: mulq %r9
; SSE-NEXT: movq %rdx, %r9
; SSE-NEXT: movq %rax, %rbx
; SSE-NEXT: addq %r11, %rbx
; SSE-NEXT: adcq $0, %r9
; SSE-NEXT: movq {{[0-9]+}}(%rsp), %r12
; SSE-NEXT: movq %rsi, %rax
; SSE-NEXT: mulq %r12
; SSE-NEXT: movq %rdx, %r11
; SSE-NEXT: movq {{[0-9]+}}(%rsp), %r14
; SSE-NEXT: addq %rbx, %rax
; SSE-NEXT: adcq %r9, %r11
; SSE-NEXT: setb %al
; SSE-NEXT: movzbl %al, %ebx
; SSE-NEXT: movq %r10, %rax
; SSE-NEXT: mulq %r12
; SSE-NEXT: movq %rdx, %rsi
; SSE-NEXT: movq %rax, %r9
; SSE-NEXT: addq %r11, %r9
; SSE-NEXT: adcq %rbx, %rsi
; SSE-NEXT: movq %rcx, %rax
; SSE-NEXT: mulq %r15
; SSE-NEXT: movq %rdx, %r10
; SSE-NEXT: movq %r8, %rax
; SSE-NEXT: mulq %r15
; SSE-NEXT: movq %rdx, %r11
; SSE-NEXT: movq %rax, %rbx
; SSE-NEXT: addq %r10, %rbx
; SSE-NEXT: adcq $0, %r11
; SSE-NEXT: movq %rcx, %rax
; SSE-NEXT: mulq %r14
; SSE-NEXT: movq %rdx, %rcx
; SSE-NEXT: addq %rbx, %rax
; SSE-NEXT: adcq %r11, %rcx
; SSE-NEXT: setb %al
; SSE-NEXT: movzbl %al, %r10d
; SSE-NEXT: movq %r8, %rax
; SSE-NEXT: mulq %r14
; SSE-NEXT: addq %rcx, %rax
; SSE-NEXT: adcq %r10, %rdx
; SSE-NEXT: movq %rax, 16(%rdi)
; SSE-NEXT: movq %r9, (%rdi)
; SSE-NEXT: movq %rdx, 24(%rdi)
; SSE-NEXT: movq %rsi, 8(%rdi)
; SSE-NEXT: movq %rdi, %rax
; SSE-NEXT: popq %rbx
; SSE-NEXT: popq %r12
; SSE-NEXT: popq %r14
; SSE-NEXT: popq %r15
; SSE-NEXT: retq
;
; AVX2-LABEL: umulh_v2i128:
; AVX2: # %bb.0:
; AVX2-NEXT: pushq %r14
; AVX2-NEXT: pushq %rbx
; AVX2-NEXT: movq %rdx, %rax
; AVX2-NEXT: movq %rsi, %rdx
; AVX2-NEXT: mulxq %r9, %r10, %r10
; AVX2-NEXT: movq {{[0-9]+}}(%rsp), %r11
; AVX2-NEXT: movq %rax, %rdx
; AVX2-NEXT: mulxq %r9, %r9, %rbx
; AVX2-NEXT: movq {{[0-9]+}}(%rsp), %r14
; AVX2-NEXT: addq %r10, %r9
; AVX2-NEXT: adcq $0, %rbx
; AVX2-NEXT: movq %rsi, %rdx
; AVX2-NEXT: mulxq %r14, %rdx, %r10
; AVX2-NEXT: addq %r9, %rdx
; AVX2-NEXT: adcq %rbx, %r10
; AVX2-NEXT: setb %dl
; AVX2-NEXT: movzbl %dl, %ebx
; AVX2-NEXT: movq %rax, %rdx
; AVX2-NEXT: mulxq %r14, %r9, %rsi
; AVX2-NEXT: addq %r10, %r9
; AVX2-NEXT: adcq %rbx, %rsi
; AVX2-NEXT: movq %rcx, %rdx
; AVX2-NEXT: mulxq %r11, %rax, %rax
; AVX2-NEXT: movq %r8, %rdx
; AVX2-NEXT: mulxq %r11, %r10, %r11
; AVX2-NEXT: addq %rax, %r10
; AVX2-NEXT: adcq $0, %r11
; AVX2-NEXT: movq {{[0-9]+}}(%rsp), %rbx
; AVX2-NEXT: movq %rcx, %rdx
; AVX2-NEXT: mulxq %rbx, %rcx, %r14
; AVX2-NEXT: movq %rdi, %rax
; AVX2-NEXT: addq %r10, %rcx
; AVX2-NEXT: adcq %r11, %r14
; AVX2-NEXT: setb %cl
; AVX2-NEXT: movq %r8, %rdx
; AVX2-NEXT: mulxq %rbx, %rdx, %rdi
; AVX2-NEXT: movzbl %cl, %ecx
; AVX2-NEXT: addq %r14, %rdx
; AVX2-NEXT: adcq %rcx, %rdi
; AVX2-NEXT: movq %rdx, 16(%rax)
; AVX2-NEXT: movq %r9, (%rax)
; AVX2-NEXT: movq %rdi, 24(%rax)
; AVX2-NEXT: movq %rsi, 8(%rax)
; AVX2-NEXT: popq %rbx
; AVX2-NEXT: popq %r14
; AVX2-NEXT: retq
;
; AVX512-LABEL: umulh_v2i128:
; AVX512: # %bb.0:
; AVX512-NEXT: pushq %r15
; AVX512-NEXT: pushq %r14
; AVX512-NEXT: pushq %rbx
; AVX512-NEXT: movq %rdx, %r10
; AVX512-NEXT: movq %rdi, %rax
; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r11
; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rdi
; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rbx
; AVX512-NEXT: movq %rsi, %rdx
; AVX512-NEXT: mulxq %r9, %r14, %r14
; AVX512-NEXT: movq %r10, %rdx
; AVX512-NEXT: mulxq %r9, %r9, %r15
; AVX512-NEXT: addq %r14, %r9
; AVX512-NEXT: adcq $0, %r15
; AVX512-NEXT: movq %rsi, %rdx
; AVX512-NEXT: mulxq %rbx, %rdx, %r14
; AVX512-NEXT: addq %r9, %rdx
; AVX512-NEXT: adcq %r15, %r14
; AVX512-NEXT: setb %dl
; AVX512-NEXT: movzbl %dl, %r9d
; AVX512-NEXT: movq %r10, %rdx
; AVX512-NEXT: mulxq %rbx, %r10, %rsi
; AVX512-NEXT: addq %r14, %r10
; AVX512-NEXT: adcq %r9, %rsi
; AVX512-NEXT: movq %rcx, %rdx
; AVX512-NEXT: mulxq %r11, %r9, %r9
; AVX512-NEXT: movq %r8, %rdx
; AVX512-NEXT: mulxq %r11, %r11, %rbx
; AVX512-NEXT: addq %r9, %r11
; AVX512-NEXT: adcq $0, %rbx
; AVX512-NEXT: movq %rcx, %rdx
; AVX512-NEXT: mulxq %rdi, %rcx, %r9
; AVX512-NEXT: addq %r11, %rcx
; AVX512-NEXT: adcq %rbx, %r9
; AVX512-NEXT: setb %cl
; AVX512-NEXT: movzbl %cl, %ecx
; AVX512-NEXT: movq %r8, %rdx
; AVX512-NEXT: mulxq %rdi, %rdx, %rdi
; AVX512-NEXT: addq %r9, %rdx
; AVX512-NEXT: adcq %rcx, %rdi
; AVX512-NEXT: movq %rdx, 16(%rax)
; AVX512-NEXT: movq %r10, (%rax)
; AVX512-NEXT: movq %rdi, 24(%rax)
; AVX512-NEXT: movq %rsi, 8(%rax)
; AVX512-NEXT: popq %rbx
; AVX512-NEXT: popq %r14
; AVX512-NEXT: popq %r15
; AVX512-NEXT: retq
%r = call <2 x i128> @llvm.umulh(<2 x i128> %x, <2 x i128> %y)
ret <2 x i128> %r
}