blob: c85b0091de487d0cddc751965e0dbaba4c4a9961 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+experimental-p,+m,+zbb \
; RUN: -verify-machineinstrs < %s | \
; RUN: FileCheck --check-prefixes=CHECK,RV32 %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \
; RUN: -verify-machineinstrs < %s | \
; RUN: FileCheck --check-prefixes=CHECK,RV64 %s
; Test basic add/sub operations for v2i16
define <2 x i16> @test_padd_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_padd_h:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.h a0, a0, a1
; CHECK-NEXT: ret
%res = add <2 x i16> %a, %b
ret <2 x i16> %res
}
define <2 x i16> @test_psub_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psub_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psub.h a0, a0, a1
; CHECK-NEXT: ret
%res = sub <2 x i16> %a, %b
ret <2 x i16> %res
}
; Test basic add/sub operations for v4i8
define <4 x i8> @test_padd_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_padd_b:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.b a0, a0, a1
; CHECK-NEXT: ret
%res = add <4 x i8> %a, %b
ret <4 x i8> %res
}
define <4 x i8> @test_psub_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_psub_b:
; CHECK: # %bb.0:
; CHECK-NEXT: psub.b a0, a0, a1
; CHECK-NEXT: ret
%res = sub <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test bitwise operations for v2i16 (use scalar instructions)
define <2 x i16> @test_and_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_and_h:
; CHECK: # %bb.0:
; CHECK-NEXT: and a0, a0, a1
; CHECK-NEXT: ret
%res = and <2 x i16> %a, %b
ret <2 x i16> %res
}
define <2 x i16> @test_or_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_or_h:
; CHECK: # %bb.0:
; CHECK-NEXT: or a0, a0, a1
; CHECK-NEXT: ret
%res = or <2 x i16> %a, %b
ret <2 x i16> %res
}
define <2 x i16> @test_xor_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_xor_h:
; CHECK: # %bb.0:
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: ret
%res = xor <2 x i16> %a, %b
ret <2 x i16> %res
}
define <2 x i16> @test_andn_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_andn_h:
; CHECK: # %bb.0:
; CHECK-NEXT: andn a0, a0, a1
; CHECK-NEXT: ret
%not = xor <2 x i16> %b, splat (i16 -1)
%res = and <2 x i16> %a, %not
ret <2 x i16> %res
}
define <2 x i16> @test_orn_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_orn_h:
; CHECK: # %bb.0:
; CHECK-NEXT: orn a0, a0, a1
; CHECK-NEXT: ret
%not = xor <2 x i16> %b, splat (i16 -1)
%res = or <2 x i16> %a, %not
ret <2 x i16> %res
}
; FIXME: A bitcast is getting in the way on RV64.
define <2 x i16> @test_xnor_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_xnor_h:
; CHECK: # %bb.0:
; CHECK-NEXT: xnor a0, a1, a0
; CHECK-NEXT: ret
%not = xor <2 x i16> %b, splat (i16 -1)
%res = xor <2 x i16> %a, %not
ret <2 x i16> %res
}
; Test bitwise operations for v4i8 (use scalar instructions)
define <4 x i8> @test_and_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_and_b:
; CHECK: # %bb.0:
; CHECK-NEXT: and a0, a0, a1
; CHECK-NEXT: ret
%res = and <4 x i8> %a, %b
ret <4 x i8> %res
}
define <4 x i8> @test_or_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_or_b:
; CHECK: # %bb.0:
; CHECK-NEXT: or a0, a0, a1
; CHECK-NEXT: ret
%res = or <4 x i8> %a, %b
ret <4 x i8> %res
}
define <4 x i8> @test_xor_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_xor_b:
; CHECK: # %bb.0:
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: ret
%res = xor <4 x i8> %a, %b
ret <4 x i8> %res
}
define <4 x i8> @test_andn_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_andn_b:
; CHECK: # %bb.0:
; CHECK-NEXT: andn a0, a0, a1
; CHECK-NEXT: ret
%not = xor <4 x i8> %b, splat (i8 -1)
%res = and <4 x i8> %a, %not
ret <4 x i8> %res
}
define <4 x i8> @test_orn_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_orn_b:
; CHECK: # %bb.0:
; CHECK-NEXT: orn a0, a0, a1
; CHECK-NEXT: ret
%not = xor <4 x i8> %b, splat (i8 -1)
%res = or <4 x i8> %a, %not
ret <4 x i8> %res
}
; FIXME: A bitcast is getting in the way on RV64.
define <4 x i8> @test_xnor_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_xnor_b:
; CHECK: # %bb.0:
; CHECK-NEXT: xnor a0, a1, a0
; CHECK-NEXT: ret
%not = xor <4 x i8> %b, splat (i8 -1)
%res = xor <4 x i8> %a, %not
ret <4 x i8> %res
}
define <2 x i16> @test_not_h(<2 x i16> %a) {
; CHECK-LABEL: test_not_h:
; CHECK: # %bb.0:
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%res = xor <2 x i16> %a, splat(i16 -1)
ret <2 x i16> %res
}
define <4 x i8> @test_not_b(<4 x i8> %a) {
; CHECK-LABEL: test_not_b:
; CHECK: # %bb.0:
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%res = xor <4 x i8> %a, splat(i8 -1)
ret <4 x i8> %res
}
; Test saturating add operations for v2i16
define <2 x i16> @test_psadd_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psadd_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psadd.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_psaddu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psaddu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psaddu.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
; Test saturating sub operations for v2i16
define <2 x i16> @test_pssub_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pssub_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pssub.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pssubu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pssubu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pssubu.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
; Test shift-add operations for v2i16
define <2 x i16> @test_psh1add_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psh1add_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psh1add.h a0, a0, a1
; CHECK-NEXT: ret
%shl = shl <2 x i16> %a, splat (i16 1)
%res = add <2 x i16> %shl, %b
ret <2 x i16> %res
}
define <2 x i16> @test_pssh1sadd_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pssh1sadd_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pssh1sadd.h a0, a0, a1
; CHECK-NEXT: ret
%shl = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> splat (i16 1))
%res = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %shl, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pssh1sadd_h_addself(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pssh1sadd_h_addself:
; CHECK: # %bb.0:
; CHECK-NEXT: pssh1sadd.h a0, a0, a1
; CHECK-NEXT: ret
%shl = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %a, <2 x i16> %a)
%res = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %shl, <2 x i16> %b)
ret <2 x i16> %res
}
; Test saturating add operations for v4i8
define <4 x i8> @test_psadd_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_psadd_b:
; CHECK: # %bb.0:
; CHECK-NEXT: psadd.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <4 x i8> @test_psaddu_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_psaddu_b:
; CHECK: # %bb.0:
; CHECK-NEXT: psaddu.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
; Test saturating sub operations for v4i8
define <4 x i8> @test_pssub_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pssub_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pssub.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <4 x i8> @test_pssubu_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pssubu_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pssubu.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
; Test averaging floor signed operations for v2i16
define <2 x i16> @test_paadd_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_paadd_h:
; CHECK: # %bb.0:
; CHECK-NEXT: paadd.h a0, a0, a1
; CHECK-NEXT: ret
%ext.a = sext <2 x i16> %a to <2 x i32>
%ext.b = sext <2 x i16> %b to <2 x i32>
%add = add nsw <2 x i32> %ext.a, %ext.b
%shift = ashr <2 x i32> %add, <i32 1, i32 1>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test averaging floor unsigned operations for v2i16
define <2 x i16> @test_paaddu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_paaddu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: paaddu.h a0, a0, a1
; CHECK-NEXT: ret
%and = and <2 x i16> %a, %b
%xor = xor <2 x i16> %a, %b
%shift = lshr <2 x i16> %xor, <i16 1, i16 1>
%res = add <2 x i16> %and, %shift
ret <2 x i16> %res
}
; Test averaging floor signed operations for v4i8
define <4 x i8> @test_paadd_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_paadd_b:
; CHECK: # %bb.0:
; CHECK-NEXT: paadd.b a0, a0, a1
; CHECK-NEXT: ret
%ext.a = sext <4 x i8> %a to <4 x i16>
%ext.b = sext <4 x i8> %b to <4 x i16>
%add = add nsw <4 x i16> %ext.a, %ext.b
%shift = ashr <4 x i16> %add, <i16 1, i16 1, i16 1, i16 1>
%res = trunc <4 x i16> %shift to <4 x i8>
ret <4 x i8> %res
}
; Test averaging floor unsigned operations for v4i8
define <4 x i8> @test_paaddu_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_paaddu_b:
; CHECK: # %bb.0:
; CHECK-NEXT: paaddu.b a0, a0, a1
; CHECK-NEXT: ret
%and = and <4 x i8> %a, %b
%xor = xor <4 x i8> %a, %b
%shift = lshr <4 x i8> %xor, <i8 1, i8 1, i8 1, i8 1>
%res = add <4 x i8> %and, %shift
ret <4 x i8> %res
}
define <2 x i16> @test_pabs_h(<2 x i16> %a) {
; CHECK-LABEL: test_pabs_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pabs.h a0, a0
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.abs.v2i16(<2 x i16> %a, i1 0)
ret <2 x i16> %res
}
define <4 x i8> @test_pabs_b(<4 x i8> %a) {
; CHECK-LABEL: test_pabs_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pabs.b a0, a0
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %a, i1 0)
ret <4 x i8> %res
}
; Test absolute difference signed for v2i16
define <2 x i16> @test_pdif_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pdif_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pabd.h a0, a0, a1
; CHECK-NEXT: ret
%min = call <2 x i16> @llvm.smin.v2i16(<2 x i16> %a, <2 x i16> %b)
%max = call <2 x i16> @llvm.smax.v2i16(<2 x i16> %a, <2 x i16> %b)
%res = sub <2 x i16> %max, %min
ret <2 x i16> %res
}
; Test absolute difference unsigned for v2i16
define <2 x i16> @test_pdifu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pdifu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pabdu.h a0, a0, a1
; CHECK-NEXT: ret
%min = call <2 x i16> @llvm.umin.v2i16(<2 x i16> %a, <2 x i16> %b)
%max = call <2 x i16> @llvm.umax.v2i16(<2 x i16> %a, <2 x i16> %b)
%res = sub <2 x i16> %max, %min
ret <2 x i16> %res
}
; Test absolute difference signed for v4i8
define <4 x i8> @test_pdif_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pdif_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pabd.b a0, a0, a1
; CHECK-NEXT: ret
%min = call <4 x i8> @llvm.smin.v4i8(<4 x i8> %a, <4 x i8> %b)
%max = call <4 x i8> @llvm.smax.v4i8(<4 x i8> %a, <4 x i8> %b)
%res = sub <4 x i8> %max, %min
ret <4 x i8> %res
}
; Test absolute difference unsigned for v4i8
define <4 x i8> @test_pdifu_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pdifu_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pabdu.b a0, a0, a1
; CHECK-NEXT: ret
%min = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %a, <4 x i8> %b)
%max = call <4 x i8> @llvm.umax.v4i8(<4 x i8> %a, <4 x i8> %b)
%res = sub <4 x i8> %max, %min
ret <4 x i8> %res
}
; Test averaging floor subtraction signed for v2i16
; pasub pattern: (a - b) arithmetic shift right 1
define <2 x i16> @test_pasub_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pasub_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pasub.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <2 x i16> %a to <2 x i32>
%b_ext = sext <2 x i16> %b to <2 x i32>
%sub = sub <2 x i32> %a_ext, %b_ext
%res = ashr <2 x i32> %sub, <i32 1, i32 1>
%res_trunc = trunc <2 x i32> %res to <2 x i16>
ret <2 x i16> %res_trunc
}
; Test averaging floor subtraction unsigned for v2i16
; pasubu pattern: (a - b) logical shift right 1
define <2 x i16> @test_pasubu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pasubu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pasubu.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = zext <2 x i16> %a to <2 x i32>
%b_ext = zext <2 x i16> %b to <2 x i32>
%sub = sub <2 x i32> %a_ext, %b_ext
%res = lshr <2 x i32> %sub, <i32 1, i32 1>
%res_trunc = trunc <2 x i32> %res to <2 x i16>
ret <2 x i16> %res_trunc
}
; Test averaging floor subtraction signed for v4i8
define <4 x i8> @test_pasub_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pasub_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pasub.b a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <4 x i8> %a to <4 x i16>
%b_ext = sext <4 x i8> %b to <4 x i16>
%sub = sub <4 x i16> %a_ext, %b_ext
%res = ashr <4 x i16> %sub, <i16 1, i16 1, i16 1, i16 1>
%res_trunc = trunc <4 x i16> %res to <4 x i8>
ret <4 x i8> %res_trunc
}
; Test averaging floor subtraction unsigned for v4i8
define <4 x i8> @test_pasubu_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pasubu_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pasubu.b a0, a0, a1
; CHECK-NEXT: ret
%a_ext = zext <4 x i8> %a to <4 x i16>
%b_ext = zext <4 x i8> %b to <4 x i16>
%sub = sub <4 x i16> %a_ext, %b_ext
%res = lshr <4 x i16> %sub, <i16 1, i16 1, i16 1, i16 1>
%res_trunc = trunc <4 x i16> %res to <4 x i8>
ret <4 x i8> %res_trunc
}
; Test PLI (pack load immediate) for v2i16
define <2 x i16> @test_pli_h() {
; CHECK-LABEL: test_pli_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.h a0, 42
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 42)
}
define <2 x i16> @test_pli_h_negative() {
; CHECK-LABEL: test_pli_h_negative:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.h a0, -5
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 -5)
}
; Test PLI for v4i8 with unsigned immediate
define <4 x i8> @test_pli_b() {
; CHECK-LABEL: test_pli_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.b a0, 32
; CHECK-NEXT: ret
ret <4 x i8> splat (i8 32)
}
define <2 x i16> @test_pli_b_v2i16() {
; CHECK-LABEL: test_pli_b_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.b a0, 32
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 u0x2020)
}
define <4 x i8> @test_pli_b_negative() {
; CHECK-LABEL: test_pli_b_negative:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.b a0, -2
; CHECK-NEXT: ret
ret <4 x i8> splat (i8 -2)
}
define <2 x i16> @test_pli_b_negative_v2i16() {
; CHECK-LABEL: test_pli_b_negative_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.b a0, -2
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 u0xfefe)
}
define <2 x i16> @test_plui_h() {
; CHECK-LABEL: test_plui_h:
; CHECK: # %bb.0:
; CHECK-NEXT: plui.h a0, 218
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 u0x3680)
}
define <2 x i16> @test_plui_h_negative() {
; CHECK-LABEL: test_plui_h_negative:
; CHECK: # %bb.0:
; CHECK-NEXT: plui.h a0, -295
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 u0xb640)
}
define <4 x i8> @test_allones_v4i8() {
; CHECK-LABEL: test_allones_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: li a0, -1
; CHECK-NEXT: ret
ret <4 x i8> splat (i8 -1)
}
define <2 x i16> @test_allones_v2i16() {
; CHECK-LABEL: test_allones_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: li a0, -1
; CHECK-NEXT: ret
ret <2 x i16> splat (i16 -1)
}
define i16 @test_extract_vector_16(<2 x i16> %a) {
; CHECK-LABEL: test_extract_vector_16:
; CHECK: # %bb.0:
; CHECK-NEXT: ret
%extracted = extractelement <2 x i16> %a, i32 0
ret i16 %extracted
}
define i16 @test_extract_vector_16_elem1(<2 x i16> %a) {
; CHECK-LABEL: test_extract_vector_16_elem1:
; CHECK: # %bb.0:
; CHECK-NEXT: srli a0, a0, 16
; CHECK-NEXT: ret
%extracted = extractelement <2 x i16> %a, i32 1
ret i16 %extracted
}
define i8 @test_extract_vector_8(<4 x i8> %a) {
; CHECK-LABEL: test_extract_vector_8:
; CHECK: # %bb.0:
; CHECK-NEXT: ret
%extracted = extractelement <4 x i8> %a, i32 0
ret i8 %extracted
}
define i8 @test_extract_vector_8_elem1(<4 x i8> %a) {
; CHECK-LABEL: test_extract_vector_8_elem1:
; CHECK: # %bb.0:
; CHECK-NEXT: srli a0, a0, 8
; CHECK-NEXT: ret
%extracted = extractelement <4 x i8> %a, i32 1
ret i8 %extracted
}
define <2 x i16> @test_insert_vector_16(<2 x i16> %a, i16 %val) {
; RV32-LABEL: test_insert_vector_16:
; RV32: # %bb.0:
; RV32-NEXT: srli a0, a0, 16
; RV32-NEXT: pack a0, a1, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_insert_vector_16:
; RV64: # %bb.0:
; RV64-NEXT: srli a0, a0, 16
; RV64-NEXT: ppaire.h a0, a1, a0
; RV64-NEXT: ret
%res = insertelement <2 x i16> %a, i16 %val, i32 0
ret <2 x i16> %res
}
define <2 x i16> @test_insert_vector_16_elem1(<2 x i16> %a, i16 %val) {
; RV32-LABEL: test_insert_vector_16_elem1:
; RV32: # %bb.0:
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_insert_vector_16_elem1:
; RV64: # %bb.0:
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = insertelement <2 x i16> %a, i16 %val, i32 1
ret <2 x i16> %res
}
define <4 x i8> @test_insert_vector_8(<4 x i8> %a, i8 %val) {
; RV32-LABEL: test_insert_vector_8:
; RV32: # %bb.0:
; RV32-NEXT: li a2, 255
; RV32-NEXT: mvm a0, a1, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_insert_vector_8:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a0, 8
; RV64-NEXT: srli a3, a0, 24
; RV64-NEXT: srli a0, a0, 16
; RV64-NEXT: ppaire.b a0, a0, a3
; RV64-NEXT: ppaire.b a1, a1, a2
; RV64-NEXT: ppaire.h a0, a1, a0
; RV64-NEXT: ret
%res = insertelement <4 x i8> %a, i8 %val, i32 0
ret <4 x i8> %res
}
define <4 x i8> @test_insert_vector_8_elem2(<4 x i8> %a, i8 %val) {
; RV32-LABEL: test_insert_vector_8_elem2:
; RV32: # %bb.0:
; RV32-NEXT: slli a1, a1, 16
; RV32-NEXT: lui a2, 4080
; RV32-NEXT: mvm a0, a1, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_insert_vector_8_elem2:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a0, 8
; RV64-NEXT: srli a3, a0, 24
; RV64-NEXT: ppaire.b a1, a1, a3
; RV64-NEXT: ppaire.b a0, a0, a2
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = insertelement <4 x i8> %a, i8 %val, i32 2
ret <4 x i8> %res
}
; Test for splat
define <4 x i8> @test_non_const_splat_i8(i8 %elt) {
; CHECK-LABEL: test_non_const_splat_i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pmv.bs a0, a0
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %elt, i32 0
%splat = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
ret <4 x i8> %splat
}
define <2 x i16> @test_non_const_splat_i16(i16 %elt) {
; CHECK-LABEL: test_non_const_splat_i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pmv.hs a0, a0
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %elt, i32 0
%splat = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
ret <2 x i16> %splat
}
; Test add(vec, splat(scalar)) pattern
define <4 x i8> @test_padd_bs_splat_lhs(<4 x i8> %a, i8 %b) {
; CHECK-LABEL: test_padd_bs_splat_lhs:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.bs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %b, i32 0
%splat = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = add <4 x i8> %splat, %a
ret <4 x i8> %res
}
define <4 x i8> @test_padd_bs_splat_rhs(<4 x i8> %a, i8 %b) {
; CHECK-LABEL: test_padd_bs_splat_rhs:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.bs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %b, i32 0
%splat = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = add <4 x i8> %a, %splat
ret <4 x i8> %res
}
define <2 x i16> @test_padd_hs_splat_lhs(<2 x i16> %a, i16 %b) {
; CHECK-LABEL: test_padd_hs_splat_lhs:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %b, i32 0
%splat = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = add <2 x i16> %splat, %a
ret <2 x i16> %res
}
define <2 x i16> @test_padd_hs_splat_rhs(<2 x i16> %a, i16 %b) {
; CHECK-LABEL: test_padd_hs_splat_rhs:
; CHECK: # %bb.0:
; CHECK-NEXT: padd.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %b, i32 0
%splat = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = add <2 x i16> %a, %splat
ret <2 x i16> %res
}
define <4 x i8> @test_build_vector_i8(i8 %a, i8 %c, i8 %b, i8 %d) {
; RV32-LABEL: test_build_vector_i8:
; RV32: # %bb.0:
; RV32-NEXT: ppaire.db a0, a0, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_build_vector_i8:
; RV64: # %bb.0:
; RV64-NEXT: ppaire.b a1, a1, a3
; RV64-NEXT: ppaire.b a0, a0, a2
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%v0 = insertelement <4 x i8> poison, i8 %a, i32 0
%v1 = insertelement <4 x i8> %v0, i8 %b, i32 1
%v2 = insertelement <4 x i8> %v1, i8 %c, i32 2
%v3 = insertelement <4 x i8> %v2, i8 %d, i32 3
ret <4 x i8> %v3
}
define <2 x i16> @test_build_vector_i16(i16 %a, i16 %b) {
; RV32-LABEL: test_build_vector_i16:
; RV32: # %bb.0:
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_build_vector_i16:
; RV64: # %bb.0:
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%v0 = insertelement <2 x i16> poison, i16 %a, i32 0
%v1 = insertelement <2 x i16> %v0, i16 %b, i32 1
ret <2 x i16> %v1
}
; Test logical shift left immediate for v2i16
define <2 x i16> @test_pslli_h(<2 x i16> %a) {
; CHECK-LABEL: test_pslli_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pslli.h a0, a0, 2
; CHECK-NEXT: ret
%res = shl <2 x i16> %a, splat(i16 2)
ret <2 x i16> %res
}
; Test logical shift left immediate for v4i8
define <4 x i8> @test_pslli_b(<4 x i8> %a) {
; CHECK-LABEL: test_pslli_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pslli.b a0, a0, 2
; CHECK-NEXT: ret
%res = shl <4 x i8> %a, splat(i8 2)
ret <4 x i8> %res
}
; Test saturating shift left arithmetic with splat immediate shift amount for v2i16
define <2 x i16> @test_psslai_h(<2 x i16> %a) {
; CHECK-LABEL: test_psslai_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psslai.h a0, a0, 2
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> splat(i16 2))
ret <2 x i16> %res
}
; Test saturating shift left arithmetic with splat immediate shift amount for v4i8
define <4 x i8> @test_psslai_b(<4 x i8> %a) {
; CHECK-LABEL: test_psslai_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pli.b a1, -128
; CHECK-NEXT: pmsltz.b a2, a0
; CHECK-NEXT: pslli.b a3, a0, 2
; CHECK-NEXT: pli.b a4, 127
; CHECK-NEXT: psrai.b a5, a3, 2
; CHECK-NEXT: merge a2, a4, a1
; CHECK-NEXT: pmseq.b a0, a0, a5
; CHECK-NEXT: merge a0, a2, a3
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.sshl.sat.v4i8(<4 x i8> %a, <4 x i8> splat(i8 2))
ret <4 x i8> %res
}
; Test saturating shift left arithmetic with splat shift amount for v2i16
define <2 x i16> @test_pssla_hs(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_pssla_hs:
; CHECK: # %bb.0:
; CHECK-NEXT: pssha.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %shamt, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
; Test saturating shift left arithmetic with non-splat shift amount for v2i16
define <2 x i16> @test_pssla_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_pssla_h:
; RV32: # %bb.0:
; RV32-NEXT: sll a2, a0, a1
; RV32-NEXT: srli a3, a1, 16
; RV32-NEXT: srli a4, a0, 16
; RV32-NEXT: sll a4, a4, a3
; RV32-NEXT: sext.h a5, a2
; RV32-NEXT: pack a2, a2, a4
; RV32-NEXT: sext.h a4, a4
; RV32-NEXT: sra a1, a5, a1
; RV32-NEXT: sra a3, a4, a3
; RV32-NEXT: pack a1, a1, a3
; RV32-NEXT: lui a3, 8
; RV32-NEXT: pmsltz.h a4, a0
; RV32-NEXT: addi a3, a3, -1
; RV32-NEXT: pmv.hs a3, a3
; RV32-NEXT: plui.h a5, -512
; RV32-NEXT: pmseq.h a0, a0, a1
; RV32-NEXT: merge a4, a3, a5
; RV32-NEXT: merge a0, a4, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_pssla_h:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 48
; RV64-NEXT: srli a3, a0, 48
; RV64-NEXT: srli a4, a1, 32
; RV64-NEXT: srli a5, a0, 32
; RV64-NEXT: sll a3, a3, a2
; RV64-NEXT: sll a5, a5, a4
; RV64-NEXT: srli a6, a1, 16
; RV64-NEXT: srli a7, a0, 16
; RV64-NEXT: sll t0, a0, a1
; RV64-NEXT: sll a7, a7, a6
; RV64-NEXT: ppaire.h t1, a5, a3
; RV64-NEXT: ppaire.h t2, t0, a7
; RV64-NEXT: pack t1, t2, t1
; RV64-NEXT: sext.h a3, a3
; RV64-NEXT: sext.h a5, a5
; RV64-NEXT: sra a2, a3, a2
; RV64-NEXT: sra a3, a5, a4
; RV64-NEXT: sext.h a4, t0
; RV64-NEXT: sext.h a5, a7
; RV64-NEXT: sra a1, a4, a1
; RV64-NEXT: sra a4, a5, a6
; RV64-NEXT: ppaire.h a2, a3, a2
; RV64-NEXT: ppaire.h a1, a1, a4
; RV64-NEXT: pack a1, a1, a2
; RV64-NEXT: lui a2, 8
; RV64-NEXT: pmsltz.h a3, a0
; RV64-NEXT: addi a2, a2, -1
; RV64-NEXT: pmv.hs a2, a2
; RV64-NEXT: plui.h a4, -512
; RV64-NEXT: pmseq.h a0, a0, a1
; RV64-NEXT: merge a3, a2, a4
; RV64-NEXT: merge a0, a3, t1
; RV64-NEXT: ret
%res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
; Test logical shift right immediate
define <2 x i16> @test_psrli_h(<2 x i16> %a) {
; CHECK-LABEL: test_psrli_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psrli.h a0, a0, 2
; CHECK-NEXT: ret
%res = lshr <2 x i16> %a, splat(i16 2)
ret <2 x i16> %res
}
define <4 x i8> @test_psrli_b(<4 x i8> %a) {
; CHECK-LABEL: test_psrli_b:
; CHECK: # %bb.0:
; CHECK-NEXT: psrli.b a0, a0, 2
; CHECK-NEXT: ret
%res = lshr <4 x i8> %a, splat(i8 2)
ret <4 x i8> %res
}
; Test arithmetic shift right immediate
define <2 x i16> @test_psrai_h(<2 x i16> %a) {
; CHECK-LABEL: test_psrai_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psrai.h a0, a0, 2
; CHECK-NEXT: ret
%res = ashr <2 x i16> %a, splat(i16 2)
ret <2 x i16> %res
}
define <4 x i8> @test_psrai_b(<4 x i8> %a) {
; CHECK-LABEL: test_psrai_b:
; CHECK: # %bb.0:
; CHECK-NEXT: psrai.b a0, a0, 2
; CHECK-NEXT: ret
%res = ashr <4 x i8> %a, splat(i8 2)
ret <4 x i8> %res
}
; Test logical shift left(scalar shamt)
define <2 x i16> @test_psll_hs(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psll_hs:
; CHECK: # %bb.0:
; CHECK-NEXT: psll.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %shamt, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = shl <2 x i16> %a, %b
ret <2 x i16> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <2 x i16> @test_psll_hs_mask(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psll_hs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 15
; CHECK-NEXT: psll.hs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i16 %shamt, 15
%insert = insertelement <2 x i16> poison, i16 %masked, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = shl <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psll_bs(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psll_bs:
; CHECK: # %bb.0:
; CHECK-NEXT: psll.bs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %shamt, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = shl <4 x i8> %a, %b
ret <4 x i8> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <4 x i8> @test_psll_bs_mask(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psll_bs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 7
; CHECK-NEXT: psll.bs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i8 %shamt, 7
%insert = insertelement <4 x i8> poison, i8 %masked, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = shl <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test logical shift left(vector shamt)
define <2 x i16> @test_psll_hs_vec_shamt(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_psll_hs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 16
; RV32-NEXT: srli a3, a0, 16
; RV32-NEXT: sll a0, a0, a1
; RV32-NEXT: sll a1, a3, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psll_hs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 16
; RV64-NEXT: srli a3, a0, 16
; RV64-NEXT: sll a0, a0, a1
; RV64-NEXT: sll a1, a3, a2
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = shl <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psll_bs_vec_shamt(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_psll_bs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 24
; RV32-NEXT: srli a3, a0, 24
; RV32-NEXT: srli a4, a1, 8
; RV32-NEXT: sll a3, a3, a2
; RV32-NEXT: srli a2, a0, 8
; RV32-NEXT: sll a6, a0, a1
; RV32-NEXT: srli a1, a1, 16
; RV32-NEXT: srli a0, a0, 16
; RV32-NEXT: sll a2, a2, a4
; RV32-NEXT: sll a7, a0, a1
; RV32-NEXT: ppaire.db a0, a6, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psll_bs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 24
; RV64-NEXT: srli a3, a0, 24
; RV64-NEXT: srli a4, a1, 16
; RV64-NEXT: srli a5, a0, 16
; RV64-NEXT: sll a2, a3, a2
; RV64-NEXT: sll a3, a5, a4
; RV64-NEXT: srli a4, a1, 8
; RV64-NEXT: srli a5, a0, 8
; RV64-NEXT: sll a0, a0, a1
; RV64-NEXT: sll a1, a5, a4
; RV64-NEXT: ppaire.b a2, a3, a2
; RV64-NEXT: ppaire.b a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = shl <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test logical shift right(scalar shamt)
define <2 x i16> @test_psrl_hs(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psrl_hs:
; CHECK: # %bb.0:
; CHECK-NEXT: psrl.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %shamt, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = lshr <2 x i16> %a, %b
ret <2 x i16> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <2 x i16> @test_psrl_hs_mask(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psrl_hs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 15
; CHECK-NEXT: psrl.hs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i16 %shamt, 15
%insert = insertelement <2 x i16> poison, i16 %masked, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = lshr <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psrl_bs(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psrl_bs:
; CHECK: # %bb.0:
; CHECK-NEXT: psrl.bs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %shamt, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = lshr <4 x i8> %a, %b
ret <4 x i8> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <4 x i8> @test_psrl_bs_mask(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psrl_bs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 7
; CHECK-NEXT: psrl.bs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i8 %shamt, 7
%insert = insertelement <4 x i8> poison, i8 %masked, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = lshr <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test arithmetic shift right(scalar shamt)
define <2 x i16> @test_psra_hs(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psra_hs:
; CHECK: # %bb.0:
; CHECK-NEXT: psra.hs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <2 x i16> poison, i16 %shamt, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = ashr <2 x i16> %a, %b
ret <2 x i16> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <2 x i16> @test_psra_hs_mask(<2 x i16> %a, i16 %shamt) {
; CHECK-LABEL: test_psra_hs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 15
; CHECK-NEXT: psra.hs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i16 %shamt, 15
%insert = insertelement <2 x i16> poison, i16 %masked, i32 0
%b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer
%res = ashr <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psra_bs(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psra_bs:
; CHECK: # %bb.0:
; CHECK-NEXT: psra.bs a0, a0, a1
; CHECK-NEXT: ret
%insert = insertelement <4 x i8> poison, i8 %shamt, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = ashr <4 x i8> %a, %b
ret <4 x i8> %res
}
; We can't remove the andi, the hardware instruction always reads 5 bits.
define <4 x i8> @test_psra_bs_mask(<4 x i8> %a, i8 %shamt) {
; CHECK-LABEL: test_psra_bs_mask:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a1, a1, 7
; CHECK-NEXT: psra.bs a0, a0, a1
; CHECK-NEXT: ret
%masked = and i8 %shamt, 7
%insert = insertelement <4 x i8> poison, i8 %masked, i32 0
%b = shufflevector <4 x i8> %insert, <4 x i8> poison, <4 x i32> zeroinitializer
%res = ashr <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test logical shift right(vector shamt)
define <2 x i16> @test_psrl_hs_vec_shamt(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_psrl_hs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 16
; RV32-NEXT: srli a3, a0, 16
; RV32-NEXT: zext.h a0, a0
; RV32-NEXT: srl a2, a3, a2
; RV32-NEXT: srl a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_psrl_hs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 16
; RV64-NEXT: srliw a3, a0, 16
; RV64-NEXT: zext.h a0, a0
; RV64-NEXT: srl a2, a3, a2
; RV64-NEXT: srl a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = lshr <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psrl_bs_vec_shamt(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_psrl_bs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 24
; RV32-NEXT: srli a3, a0, 24
; RV32-NEXT: srli a4, a1, 8
; RV32-NEXT: srl a3, a3, a2
; RV32-NEXT: slli a2, a0, 16
; RV32-NEXT: srli a2, a2, 24
; RV32-NEXT: zext.b a5, a0
; RV32-NEXT: srl a6, a5, a1
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srli a1, a1, 16
; RV32-NEXT: srli a0, a0, 24
; RV32-NEXT: srl a2, a2, a4
; RV32-NEXT: srl a7, a0, a1
; RV32-NEXT: ppaire.db a0, a6, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psrl_bs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 24
; RV64-NEXT: srliw a3, a0, 24
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srli a5, a1, 16
; RV64-NEXT: srli a4, a4, 56
; RV64-NEXT: srl a2, a3, a2
; RV64-NEXT: srl a3, a4, a5
; RV64-NEXT: zext.b a4, a0
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srli a5, a1, 8
; RV64-NEXT: srli a0, a0, 56
; RV64-NEXT: srl a1, a4, a1
; RV64-NEXT: srl a0, a0, a5
; RV64-NEXT: ppaire.b a2, a3, a2
; RV64-NEXT: ppaire.b a0, a1, a0
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = lshr <4 x i8> %a, %b
ret <4 x i8> %res
}
; Test arithmetic shift right(vector shamt)
define <2 x i16> @test_psra_hs_vec_shamt(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_psra_hs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 16
; RV32-NEXT: srai a3, a0, 16
; RV32-NEXT: sext.h a0, a0
; RV32-NEXT: sra a2, a3, a2
; RV32-NEXT: sra a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_psra_hs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: sext.h a2, a0
; RV64-NEXT: slli a0, a0, 32
; RV64-NEXT: srli a3, a1, 16
; RV64-NEXT: srai a0, a0, 48
; RV64-NEXT: sra a1, a2, a1
; RV64-NEXT: sra a0, a0, a3
; RV64-NEXT: ppaire.h a0, a1, a0
; RV64-NEXT: ret
%res = ashr <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psra_bs_vec_shamt(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_psra_bs_vec_shamt:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 24
; RV32-NEXT: srai a3, a0, 24
; RV32-NEXT: srli a4, a1, 8
; RV32-NEXT: sra a3, a3, a2
; RV32-NEXT: slli a2, a0, 16
; RV32-NEXT: srai a2, a2, 24
; RV32-NEXT: sext.b a5, a0
; RV32-NEXT: sra a6, a5, a1
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srli a1, a1, 16
; RV32-NEXT: srai a0, a0, 24
; RV32-NEXT: sra a2, a2, a4
; RV32-NEXT: sra a7, a0, a1
; RV32-NEXT: ppaire.db a0, a6, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psra_bs_vec_shamt:
; RV64: # %bb.0:
; RV64-NEXT: srli a2, a1, 24
; RV64-NEXT: slli a3, a0, 32
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srai a3, a3, 56
; RV64-NEXT: srli a5, a1, 16
; RV64-NEXT: srai a4, a4, 56
; RV64-NEXT: sra a2, a3, a2
; RV64-NEXT: sra a3, a4, a5
; RV64-NEXT: sext.b a4, a0
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srli a5, a1, 8
; RV64-NEXT: srai a0, a0, 56
; RV64-NEXT: sra a1, a4, a1
; RV64-NEXT: sra a0, a0, a5
; RV64-NEXT: ppaire.b a2, a3, a2
; RV64-NEXT: ppaire.b a0, a1, a0
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = ashr <4 x i8> %a, %b
ret <4 x i8> %res
}
; Packed saturating and rounding shifts
define <2 x i16> @test_pssha_s_i16x2(<2 x i16> %a, i32 %shamt) {
; CHECK-LABEL: test_pssha_s_i16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: pssha.hs a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pssha.v2i16.i32(<2 x i16> %a, i32 %shamt)
ret <2 x i16> %res
}
define <2 x i16> @test_psshar_s_i16x2(<2 x i16> %a, i32 %shamt) {
; CHECK-LABEL: test_psshar_s_i16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: psshar.hs a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psshar.v2i16.i32(<2 x i16> %a, i32 %shamt)
ret <2 x i16> %res
}
define <2 x i16> @test_psshl_s_u16x2(<2 x i16> %a, i32 %shamt) {
; CHECK-LABEL: test_psshl_s_u16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: psshl.hs a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psshl.v2i16.i32(<2 x i16> %a, i32 %shamt)
ret <2 x i16> %res
}
define <2 x i16> @test_psshlr_s_u16x2(<2 x i16> %a, i32 %shamt) {
; CHECK-LABEL: test_psshlr_s_u16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: psshlr.hs a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psshlr.v2i16.i32(<2 x i16> %a, i32 %shamt)
ret <2 x i16> %res
}
; Test packed multiply high signed for v4i8
define <4 x i8> @test_pmulh_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pmulh_b:
; RV32: # %bb.0:
; RV32-NEXT: pwmul.b a0, a0, a1
; RV32-NEXT: pncvth.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmulh_b:
; RV64: # %bb.0:
; RV64-NEXT: pmul.h.b11 a2, a0, a1
; RV64-NEXT: pmul.h.b00 a0, a0, a1
; RV64-NEXT: ppairo.b a0, a0, a2
; RV64-NEXT: ret
%a_ext = sext <4 x i8> %a to <4 x i16>
%b_ext = sext <4 x i8> %b to <4 x i16>
%mul = mul <4 x i16> %a_ext, %b_ext
%shift = lshr <4 x i16> %mul, splat (i16 8)
%res = trunc <4 x i16> %shift to <4 x i8>
ret <4 x i8> %res
}
; Test packed multiply high unsigned for v4i8
define <4 x i8> @test_pmulhu_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pmulhu_b:
; RV32: # %bb.0:
; RV32-NEXT: pwmulu.b a0, a0, a1
; RV32-NEXT: pncvth.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmulhu_b:
; RV64: # %bb.0:
; RV64-NEXT: pmulu.h.b11 a2, a0, a1
; RV64-NEXT: pmulu.h.b00 a0, a0, a1
; RV64-NEXT: ppairo.b a0, a0, a2
; RV64-NEXT: ret
%a_ext = zext <4 x i8> %a to <4 x i16>
%b_ext = zext <4 x i8> %b to <4 x i16>
%mul = mul <4 x i16> %a_ext, %b_ext
%shift = lshr <4 x i16> %mul, splat (i16 8)
%res = trunc <4 x i16> %shift to <4 x i8>
ret <4 x i8> %res
}
; Test packed multiply high signed-unsigned for v4i8
define <4 x i8> @test_pmulhsu_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pmulhsu_b:
; RV32: # %bb.0:
; RV32-NEXT: pwcvt.b a2, a0
; RV32-NEXT: pwcvtu.b a0, a1
; RV32-NEXT: pwmul.h a4, a3, a1
; RV32-NEXT: pncvt.h a1, a4
; RV32-NEXT: pwmul.h a2, a2, a0
; RV32-NEXT: pncvt.h a0, a2
; RV32-NEXT: pncvth.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmulhsu_b:
; RV64: # %bb.0:
; RV64-NEXT: pwcvtu.wb a0, a0
; RV64-NEXT: psext.h.b a0, a0
; RV64-NEXT: pwcvtu.wb a1, a1
; RV64-NEXT: pmul.w.h11 a2, a0, a1
; RV64-NEXT: pmul.w.h00 a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: psrli.h a0, a0, 8
; RV64-NEXT: pncvt.wb a0, a0
; RV64-NEXT: ret
%a_ext = sext <4 x i8> %a to <4 x i16>
%b_ext = zext <4 x i8> %b to <4 x i16>
%mul = mul <4 x i16> %a_ext, %b_ext
%shift = lshr <4 x i16> %mul, splat (i16 8)
%res = trunc <4 x i16> %shift to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_pmulhsu_b_commuted(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pmulhsu_b_commuted:
; RV32: # %bb.0:
; RV32-NEXT: pwcvtu.b a2, a0
; RV32-NEXT: pwcvt.b a0, a1
; RV32-NEXT: pwmul.h a4, a3, a1
; RV32-NEXT: pncvt.h a1, a4
; RV32-NEXT: pwmul.h a2, a2, a0
; RV32-NEXT: pncvt.h a0, a2
; RV32-NEXT: pncvth.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmulhsu_b_commuted:
; RV64: # %bb.0:
; RV64-NEXT: pwcvtu.wb a1, a1
; RV64-NEXT: pwcvtu.wb a0, a0
; RV64-NEXT: psext.h.b a1, a1
; RV64-NEXT: pmul.w.h11 a2, a0, a1
; RV64-NEXT: pmul.w.h00 a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: psrli.h a0, a0, 8
; RV64-NEXT: pncvt.wb a0, a0
; RV64-NEXT: ret
%a_ext = zext <4 x i8> %a to <4 x i16>
%b_ext = sext <4 x i8> %b to <4 x i16>
%mul = mul <4 x i16> %a_ext, %b_ext
%shift = lshr <4 x i16> %mul, splat (i16 8)
%res = trunc <4 x i16> %shift to <4 x i8>
ret <4 x i8> %res
}
; Test packed multiply high signed for v2i16
define <2 x i16> @test_pmulh_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulh_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulh.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <2 x i16> %a to <2 x i32>
%b_ext = sext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%shift = lshr <2 x i32> %mul, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply high unsigned for v2i16
define <2 x i16> @test_pmulhu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhu.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = zext <2 x i16> %a to <2 x i32>
%b_ext = zext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%shift = lshr <2 x i32> %mul, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply high signed-unsigned for v2i16
define <2 x i16> @test_pmulhsu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhsu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhsu.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <2 x i16> %a to <2 x i32>
%b_ext = zext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%shift = lshr <2 x i32> %mul, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_pmulhsu_h_commuted(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhsu_h_commuted:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhsu.h a0, a1, a0
; CHECK-NEXT: ret
%a_ext = zext <2 x i16> %a to <2 x i32>
%b_ext = sext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%shift = lshr <2 x i32> %mul, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply high rounding signed for v2i16
define <2 x i16> @test_pmulhr_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhr_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhr.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <2 x i16> %a to <2 x i32>
%b_ext = sext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%add = add <2 x i32> %mul, <i32 32768, i32 32768>
%shift = lshr <2 x i32> %add, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply high rounding unsigned for v2i16
define <2 x i16> @test_pmulhru_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhru_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhru.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = zext <2 x i16> %a to <2 x i32>
%b_ext = zext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%add = add <2 x i32> %mul, <i32 32768, i32 32768>
%shift = lshr <2 x i32> %add, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply high rounding signed-unsigned for v2i16
define <2 x i16> @test_pmulhrsu_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhrsu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhrsu.h a0, a0, a1
; CHECK-NEXT: ret
%a_ext = sext <2 x i16> %a to <2 x i32>
%b_ext = zext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%add = add <2 x i32> %mul, <i32 32768, i32 32768>
%shift = lshr <2 x i32> %add, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_pmulhrsu_h_commuted(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulhrsu_h_commuted:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulhrsu.h a0, a1, a0
; CHECK-NEXT: ret
%a_ext = zext <2 x i16> %a to <2 x i32>
%b_ext = sext <2 x i16> %b to <2 x i32>
%mul = mul <2 x i32> %a_ext, %b_ext
%add = add <2 x i32> %mul, <i32 32768, i32 32768>
%shift = lshr <2 x i32> %add, <i32 16, i32 16>
%res = trunc <2 x i32> %shift to <2 x i16>
ret <2 x i16> %res
}
; Test packed multiply low for v2i16
define <2 x i16> @test_pmul_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_pmul_h:
; RV32: # %bb.0:
; RV32-NEXT: pwmul.h a0, a0, a1
; RV32-NEXT: pncvt.h a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmul_h:
; RV64: # %bb.0:
; RV64-NEXT: pmul.w.h11 a2, a0, a1
; RV64-NEXT: pmul.w.h00 a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = mul <2 x i16> %a, %b
ret <2 x i16> %res
}
; Test packed multiply low for v4i8
define <4 x i8> @test_pmul_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pmul_b:
; RV32: # %bb.0:
; RV32-NEXT: pwmul.b a0, a0, a1
; RV32-NEXT: pncvt.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_pmul_b:
; RV64: # %bb.0:
; RV64-NEXT: pmul.h.b11 a2, a0, a1
; RV64-NEXT: pmul.h.b00 a0, a0, a1
; RV64-NEXT: ppaire.b a0, a0, a2
; RV64-NEXT: ret
%res = mul <4 x i8> %a, %b
ret <4 x i8> %res
}
; Division and remainder tests
define <2 x i16> @test_psdiv_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_psdiv_h:
; RV32: # %bb.0:
; RV32-NEXT: srai a2, a1, 16
; RV32-NEXT: srai a3, a0, 16
; RV32-NEXT: div a2, a3, a2
; RV32-NEXT: sext.h a1, a1
; RV32-NEXT: sext.h a0, a0
; RV32-NEXT: div a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_psdiv_h:
; RV64: # %bb.0:
; RV64-NEXT: sext.h a2, a1
; RV64-NEXT: sext.h a3, a0
; RV64-NEXT: divw a2, a3, a2
; RV64-NEXT: slli a1, a1, 32
; RV64-NEXT: slli a0, a0, 32
; RV64-NEXT: srai a1, a1, 48
; RV64-NEXT: srai a0, a0, 48
; RV64-NEXT: divw a0, a0, a1
; RV64-NEXT: ppaire.h a0, a2, a0
; RV64-NEXT: ret
%res = sdiv <2 x i16> %a, %b
ret <2 x i16> %res
}
define <2 x i16> @test_psdiv_mulhsu_h(<2 x i16> %a) {
; CHECK-LABEL: test_psdiv_mulhsu_h:
; CHECK: # %bb.0:
; CHECK-NEXT: lui a1, 1048569
; CHECK-NEXT: addi a1, a1, -1911
; CHECK-NEXT: pmv.hs a1, a1
; CHECK-NEXT: pmulhsu.h a0, a0, a1
; CHECK-NEXT: psrai.h a0, a0, 3
; CHECK-NEXT: psrli.h a1, a0, 15
; CHECK-NEXT: padd.h a0, a0, a1
; CHECK-NEXT: ret
%res = sdiv <2 x i16> %a, splat (i16 15)
ret <2 x i16> %res
}
define <4 x i8> @test_psdiv_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_psdiv_b:
; RV32: # %bb.0:
; RV32-NEXT: srai a2, a1, 24
; RV32-NEXT: srai a3, a0, 24
; RV32-NEXT: div a3, a3, a2
; RV32-NEXT: slli a2, a1, 16
; RV32-NEXT: slli a4, a0, 16
; RV32-NEXT: srai a2, a2, 24
; RV32-NEXT: srai a4, a4, 24
; RV32-NEXT: div a2, a4, a2
; RV32-NEXT: sext.b a4, a1
; RV32-NEXT: sext.b a5, a0
; RV32-NEXT: div a4, a5, a4
; RV32-NEXT: slli a1, a1, 8
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srai a1, a1, 24
; RV32-NEXT: srai a0, a0, 24
; RV32-NEXT: div a5, a0, a1
; RV32-NEXT: ppaire.db a0, a4, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psdiv_b:
; RV64: # %bb.0:
; RV64-NEXT: slli a2, a1, 32
; RV64-NEXT: slli a3, a0, 32
; RV64-NEXT: srai a2, a2, 56
; RV64-NEXT: srai a3, a3, 56
; RV64-NEXT: divw a2, a3, a2
; RV64-NEXT: slli a3, a1, 40
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srai a3, a3, 56
; RV64-NEXT: srai a4, a4, 56
; RV64-NEXT: divw a3, a4, a3
; RV64-NEXT: sext.b a4, a1
; RV64-NEXT: sext.b a5, a0
; RV64-NEXT: divw a4, a5, a4
; RV64-NEXT: slli a1, a1, 48
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srai a1, a1, 56
; RV64-NEXT: srai a0, a0, 56
; RV64-NEXT: divw a0, a0, a1
; RV64-NEXT: ppaire.b a1, a3, a2
; RV64-NEXT: ppaire.b a0, a4, a0
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = sdiv <4 x i8> %a, %b
ret <4 x i8> %res
}
define <2 x i16> @test_pudiv_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_pudiv_h:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 16
; RV32-NEXT: srli a3, a0, 16
; RV32-NEXT: divu a2, a3, a2
; RV32-NEXT: zext.h a1, a1
; RV32-NEXT: zext.h a0, a0
; RV32-NEXT: divu a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_pudiv_h:
; RV64: # %bb.0:
; RV64-NEXT: srliw a2, a1, 16
; RV64-NEXT: srliw a3, a0, 16
; RV64-NEXT: divuw a2, a3, a2
; RV64-NEXT: zext.h a1, a1
; RV64-NEXT: zext.h a0, a0
; RV64-NEXT: divuw a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = udiv <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psdiv_mulhsu_b(<4 x i8> %a) {
; RV32-LABEL: test_psdiv_mulhsu_b:
; RV32: # %bb.0:
; RV32-NEXT: pli.b a1, -119
; RV32-NEXT: pwmulsu.b a0, a0, a1
; RV32-NEXT: pnsrai.b a0, a0, 11
; RV32-NEXT: psrli.b a1, a0, 7
; RV32-NEXT: padd.b a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psdiv_mulhsu_b:
; RV64: # %bb.0:
; RV64-NEXT: pli.b a1, -119
; RV64-NEXT: pmulsu.h.b11 a2, a0, a1
; RV64-NEXT: pmulsu.h.b00 a0, a0, a1
; RV64-NEXT: ppairo.b a0, a0, a2
; RV64-NEXT: psrai.b a0, a0, 3
; RV64-NEXT: psrli.b a1, a0, 7
; RV64-NEXT: padd.b a0, a0, a1
; RV64-NEXT: ret
%res = sdiv <4 x i8> %a, splat (i8 15)
ret <4 x i8> %res
}
define <4 x i8> @test_pudiv_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pudiv_b:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 24
; RV32-NEXT: srli a3, a0, 24
; RV32-NEXT: divu a3, a3, a2
; RV32-NEXT: slli a2, a1, 16
; RV32-NEXT: slli a4, a0, 16
; RV32-NEXT: srli a2, a2, 24
; RV32-NEXT: srli a4, a4, 24
; RV32-NEXT: divu a2, a4, a2
; RV32-NEXT: zext.b a4, a1
; RV32-NEXT: zext.b a5, a0
; RV32-NEXT: divu a4, a5, a4
; RV32-NEXT: slli a1, a1, 8
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srli a1, a1, 24
; RV32-NEXT: srli a0, a0, 24
; RV32-NEXT: divu a5, a0, a1
; RV32-NEXT: ppaire.db a0, a4, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_pudiv_b:
; RV64: # %bb.0:
; RV64-NEXT: srliw a2, a1, 24
; RV64-NEXT: srliw a3, a0, 24
; RV64-NEXT: divuw a2, a3, a2
; RV64-NEXT: slli a3, a1, 40
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srli a3, a3, 56
; RV64-NEXT: srli a4, a4, 56
; RV64-NEXT: divuw a3, a4, a3
; RV64-NEXT: zext.b a4, a1
; RV64-NEXT: zext.b a5, a0
; RV64-NEXT: divuw a4, a5, a4
; RV64-NEXT: slli a1, a1, 48
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srli a1, a1, 56
; RV64-NEXT: srli a0, a0, 56
; RV64-NEXT: divuw a0, a0, a1
; RV64-NEXT: ppaire.b a1, a3, a2
; RV64-NEXT: ppaire.b a0, a4, a0
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = udiv <4 x i8> %a, %b
ret <4 x i8> %res
}
define <4 x i8> @test_pudiv_mulhu_b(<4 x i8> %a) {
; RV32-LABEL: test_pudiv_mulhu_b:
; RV32: # %bb.0:
; RV32-NEXT: pli.b a1, -85
; RV32-NEXT: pwmulu.b a0, a0, a1
; RV32-NEXT: pnsrli.b a0, a0, 9
; RV32-NEXT: ret
;
; RV64-LABEL: test_pudiv_mulhu_b:
; RV64: # %bb.0:
; RV64-NEXT: pli.b a1, -85
; RV64-NEXT: pmulu.h.b11 a2, a0, a1
; RV64-NEXT: pmulu.h.b00 a0, a0, a1
; RV64-NEXT: ppairo.b a0, a0, a2
; RV64-NEXT: psrli.b a0, a0, 1
; RV64-NEXT: ret
%res = udiv <4 x i8> %a, splat (i8 3)
ret <4 x i8> %res
}
define <2 x i16> @test_psrem_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_psrem_h:
; RV32: # %bb.0:
; RV32-NEXT: srai a2, a1, 16
; RV32-NEXT: srai a3, a0, 16
; RV32-NEXT: rem a2, a3, a2
; RV32-NEXT: sext.h a1, a1
; RV32-NEXT: sext.h a0, a0
; RV32-NEXT: rem a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_psrem_h:
; RV64: # %bb.0:
; RV64-NEXT: sext.h a2, a1
; RV64-NEXT: sext.h a3, a0
; RV64-NEXT: remw a2, a3, a2
; RV64-NEXT: slli a1, a1, 32
; RV64-NEXT: slli a0, a0, 32
; RV64-NEXT: srai a1, a1, 48
; RV64-NEXT: srai a0, a0, 48
; RV64-NEXT: remw a0, a0, a1
; RV64-NEXT: ppaire.h a0, a2, a0
; RV64-NEXT: ret
%res = srem <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_psrem_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_psrem_b:
; RV32: # %bb.0:
; RV32-NEXT: srai a2, a1, 24
; RV32-NEXT: srai a3, a0, 24
; RV32-NEXT: rem a3, a3, a2
; RV32-NEXT: slli a2, a1, 16
; RV32-NEXT: slli a4, a0, 16
; RV32-NEXT: srai a2, a2, 24
; RV32-NEXT: srai a4, a4, 24
; RV32-NEXT: rem a2, a4, a2
; RV32-NEXT: sext.b a4, a1
; RV32-NEXT: sext.b a5, a0
; RV32-NEXT: rem a4, a5, a4
; RV32-NEXT: slli a1, a1, 8
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srai a1, a1, 24
; RV32-NEXT: srai a0, a0, 24
; RV32-NEXT: rem a5, a0, a1
; RV32-NEXT: ppaire.db a0, a4, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_psrem_b:
; RV64: # %bb.0:
; RV64-NEXT: slli a2, a1, 32
; RV64-NEXT: slli a3, a0, 32
; RV64-NEXT: srai a2, a2, 56
; RV64-NEXT: srai a3, a3, 56
; RV64-NEXT: remw a2, a3, a2
; RV64-NEXT: slli a3, a1, 40
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srai a3, a3, 56
; RV64-NEXT: srai a4, a4, 56
; RV64-NEXT: remw a3, a4, a3
; RV64-NEXT: sext.b a4, a1
; RV64-NEXT: sext.b a5, a0
; RV64-NEXT: remw a4, a5, a4
; RV64-NEXT: slli a1, a1, 48
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srai a1, a1, 56
; RV64-NEXT: srai a0, a0, 56
; RV64-NEXT: remw a0, a0, a1
; RV64-NEXT: ppaire.b a1, a3, a2
; RV64-NEXT: ppaire.b a0, a4, a0
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = srem <4 x i8> %a, %b
ret <4 x i8> %res
}
define <2 x i16> @test_purem_h(<2 x i16> %a, <2 x i16> %b) {
; RV32-LABEL: test_purem_h:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 16
; RV32-NEXT: srli a3, a0, 16
; RV32-NEXT: remu a2, a3, a2
; RV32-NEXT: zext.h a1, a1
; RV32-NEXT: zext.h a0, a0
; RV32-NEXT: remu a0, a0, a1
; RV32-NEXT: pack a0, a0, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_purem_h:
; RV64: # %bb.0:
; RV64-NEXT: srliw a2, a1, 16
; RV64-NEXT: srliw a3, a0, 16
; RV64-NEXT: remuw a2, a3, a2
; RV64-NEXT: zext.h a1, a1
; RV64-NEXT: zext.h a0, a0
; RV64-NEXT: remuw a0, a0, a1
; RV64-NEXT: ppaire.h a0, a0, a2
; RV64-NEXT: ret
%res = urem <2 x i16> %a, %b
ret <2 x i16> %res
}
define <4 x i8> @test_purem_b(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_purem_b:
; RV32: # %bb.0:
; RV32-NEXT: srli a2, a1, 24
; RV32-NEXT: srli a3, a0, 24
; RV32-NEXT: remu a3, a3, a2
; RV32-NEXT: slli a2, a1, 16
; RV32-NEXT: slli a4, a0, 16
; RV32-NEXT: srli a2, a2, 24
; RV32-NEXT: srli a4, a4, 24
; RV32-NEXT: remu a2, a4, a2
; RV32-NEXT: zext.b a4, a1
; RV32-NEXT: zext.b a5, a0
; RV32-NEXT: remu a4, a5, a4
; RV32-NEXT: slli a1, a1, 8
; RV32-NEXT: slli a0, a0, 8
; RV32-NEXT: srli a1, a1, 24
; RV32-NEXT: srli a0, a0, 24
; RV32-NEXT: remu a5, a0, a1
; RV32-NEXT: ppaire.db a0, a4, a2
; RV32-NEXT: pack a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_purem_b:
; RV64: # %bb.0:
; RV64-NEXT: srliw a2, a1, 24
; RV64-NEXT: srliw a3, a0, 24
; RV64-NEXT: remuw a2, a3, a2
; RV64-NEXT: slli a3, a1, 40
; RV64-NEXT: slli a4, a0, 40
; RV64-NEXT: srli a3, a3, 56
; RV64-NEXT: srli a4, a4, 56
; RV64-NEXT: remuw a3, a4, a3
; RV64-NEXT: zext.b a4, a1
; RV64-NEXT: zext.b a5, a0
; RV64-NEXT: remuw a4, a5, a4
; RV64-NEXT: slli a1, a1, 48
; RV64-NEXT: slli a0, a0, 48
; RV64-NEXT: srli a1, a1, 56
; RV64-NEXT: srli a0, a0, 56
; RV64-NEXT: remuw a0, a0, a1
; RV64-NEXT: ppaire.b a1, a3, a2
; RV64-NEXT: ppaire.b a0, a4, a0
; RV64-NEXT: ppaire.h a0, a0, a1
; RV64-NEXT: ret
%res = urem <4 x i8> %a, %b
ret <4 x i8> %res
}
; Comparison operations for v2i16
define <2 x i16> @test_eq_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_eq_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmseq.h a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp eq <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_ne_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_ne_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmseq.h a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp ne <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_nez_h(<2 x i16> %a) {
; CHECK-LABEL: test_nez_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsnez.h a0, a0
; CHECK-NEXT: ret
%cmp = icmp ne <2 x i16> %a, splat (i16 0)
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_slt_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_slt_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.h a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp slt <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_sle_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_sle_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.h a0, a1, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sle <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_sgt_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_sgt_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.h a0, a1, a0
; CHECK-NEXT: ret
%cmp = icmp sgt <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_sge_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_sge_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.h a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sge <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_sgez_h(<2 x i16> %a) {
; CHECK-LABEL: test_sgez_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltz.h a0, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sgt <2 x i16> %a, splat (i16 -1);
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_ult_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_ult_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.h a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp ult <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_ule_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_ule_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.h a0, a1, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp ule <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_ugt_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_ugt_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.h a0, a1, a0
; CHECK-NEXT: ret
%cmp = icmp ugt <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
define <2 x i16> @test_uge_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_uge_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.h a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp uge <2 x i16> %a, %b
%res = sext <2 x i1> %cmp to <2 x i16>
ret <2 x i16> %res
}
; Comparison operations for v4i8
define <4 x i8> @test_eq_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_eq_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmseq.b a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp eq <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_ne_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ne_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmseq.b a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp ne <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_nez_b(<4 x i8> %a) {
; CHECK-LABEL: test_nez_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsnez.b a0, a0
; CHECK-NEXT: ret
%cmp = icmp ne <4 x i8> %a, splat (i8 0)
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_slt_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_slt_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.b a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp slt <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_sle_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_sle_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.b a0, a1, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sle <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_sgt_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_sgt_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.b a0, a1, a0
; CHECK-NEXT: ret
%cmp = icmp sgt <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_sge_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_sge_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.b a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sge <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_sgez_b(<4 x i8> %a) {
; CHECK-LABEL: test_sgez_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltz.b a0, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp sgt <4 x i8> %a, splat (i8 -1)
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_ult_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ult_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.b a0, a0, a1
; CHECK-NEXT: ret
%cmp = icmp ult <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_ule_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ule_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.b a0, a1, a0
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp ule <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_ugt_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ugt_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.b a0, a1, a0
; CHECK-NEXT: ret
%cmp = icmp ugt <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
define <4 x i8> @test_uge_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_uge_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmsltu.b a0, a0, a1
; CHECK-NEXT: not a0, a0
; CHECK-NEXT: ret
%cmp = icmp uge <4 x i8> %a, %b
%res = sext <4 x i1> %cmp to <4 x i8>
ret <4 x i8> %res
}
; Test 8/16-bit [s|u]min/[s|u]max
define <2 x i16> @test_smin_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_smin_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmin.h a0, a0, a1
; CHECK-NEXT: ret
%min = call <2 x i16> @llvm.smin.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %min
}
define <2 x i16> @test_umin_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_umin_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pminu.h a0, a0, a1
; CHECK-NEXT: ret
%min = call <2 x i16> @llvm.umin.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %min
}
define <4 x i8> @test_smin_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_smin_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmin.b a0, a0, a1
; CHECK-NEXT: ret
%min = call <4 x i8> @llvm.smin.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %min
}
define <4 x i8> @test_umin_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_umin_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pminu.b a0, a0, a1
; CHECK-NEXT: ret
%min = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %min
}
define <2 x i16> @test_smax_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_smax_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmax.h a0, a0, a1
; CHECK-NEXT: ret
%max = call <2 x i16> @llvm.smax.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %max
}
define <2 x i16> @test_umax_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_umax_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pmaxu.h a0, a0, a1
; CHECK-NEXT: ret
%max = call <2 x i16> @llvm.umax.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %max
}
define <4 x i8> @test_smax_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_smax_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmax.b a0, a0, a1
; CHECK-NEXT: ret
%max = call <4 x i8> @llvm.smax.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %max
}
define <4 x i8> @test_umax_b(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_umax_b:
; CHECK: # %bb.0:
; CHECK-NEXT: pmaxu.b a0, a0, a1
; CHECK-NEXT: ret
%max = call <4 x i8> @llvm.umax.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %max
}
; Test select operations
define <2 x i16> @test_select_v2i16(i1 %cond, <2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_select_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a3, a0, 1
; CHECK-NEXT: mv a0, a1
; CHECK-NEXT: bnez a3, .LBB158_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: mv a0, a2
; CHECK-NEXT: .LBB158_2:
; CHECK-NEXT: ret
%res = select i1 %cond, <2 x i16> %a, <2 x i16> %b
ret <2 x i16> %res
}
define <4 x i8> @test_select_v4i8(i1 %cond, <4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_select_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a3, a0, 1
; CHECK-NEXT: mv a0, a1
; CHECK-NEXT: bnez a3, .LBB159_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: mv a0, a2
; CHECK-NEXT: .LBB159_2:
; CHECK-NEXT: ret
%res = select i1 %cond, <4 x i8> %a, <4 x i8> %b
ret <4 x i8> %res
}
; Test vselect operations
define <2 x i16> @test_vselect_v2i16(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c) {
; CHECK-LABEL: test_vselect_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pmslt.h a0, a1, a0
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%mask = icmp sgt <2 x i16> %a, %b
%res = select <2 x i1> %mask, <2 x i16> %c, <2 x i16> %b
ret <2 x i16> %res
}
define <4 x i8> @test_vselect_v4i8(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c) {
; CHECK-LABEL: test_vselect_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pmseq.b a0, a0, a1
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%mask = icmp eq <4 x i8> %a, %b
%res = select <4 x i1> %mask, <4 x i8> %c, <4 x i8> %b
ret <4 x i8> %res
}
define <4 x i8> @test_ppaire_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ppaire_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: ppaire.b a0, a0, a1
; CHECK-NEXT: ret
%res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
ret <4 x i8> %res
}
define <4 x i8> @test_ppaireo_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ppaireo_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: ppaireo.b a0, a0, a1
; CHECK-NEXT: ret
%res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
ret <4 x i8> %res
}
define <4 x i8> @test_ppairoe_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ppairoe_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: ppairoe.b a0, a0, a1
; CHECK-NEXT: ret
%res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> <i32 1, i32 4, i32 3, i32 6>
ret <4 x i8> %res
}
define <4 x i8> @test_ppairo_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_ppairo_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: ppairo.b a0, a0, a1
; CHECK-NEXT: ret
%res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
ret <4 x i8> %res
}
define <2 x i16> @test_bswap_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_bswap_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: ppairoe.b a0, a0, a0
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> %a)
ret <2 x i16> %res
}
define <4 x i8> @test_bitreverse_v4i8(<4 x i8> %a) {
; CHECK-LABEL: test_bitreverse_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: rev a0, a0
; CHECK-NEXT: rev8 a0, a0
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.bitreverse.v4i8(<4 x i8> %a)
ret <4 x i8> %res
}
define <2 x i16> @test_bitreverse_v2i16(<2 x i16> %a) {
; RV32-LABEL: test_bitreverse_v2i16:
; RV32: # %bb.0:
; RV32-NEXT: rev a0, a0
; RV32-NEXT: ppairoe.h a0, a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_bitreverse_v2i16:
; RV64: # %bb.0:
; RV64-NEXT: rev a0, a0
; RV64-NEXT: rev16 a0, a0
; RV64-NEXT: ret
%res = call <2 x i16> @llvm.bitreverse.v2i16(<2 x i16> %a)
ret <2 x i16> %res
}
define <4 x i8> @test_paadd_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_paadd_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: paadd.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.paadd.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <4 x i8> @test_paaddu_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_paaddu_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: paaddu.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.paaddu.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <4 x i8> @test_pasub_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pasub_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pasub.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pasub.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <4 x i8> @test_pasubu_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pasubu_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pasubu.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pasubu.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <2 x i16> @test_paadd_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_paadd_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: paadd.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.paadd.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_paaddu_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_paaddu_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: paaddu.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.paaddu.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pasub_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pasub_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pasub.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pasub.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pasubu_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pasubu_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pasubu.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pasubu.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <4 x i8> @test_pabd_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pabd_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pabd.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pabd.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <2 x i16> @test_pabd_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pabd_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pabd.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pabd.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <4 x i8> @test_pabdu_v4i8(<4 x i8> %a, <4 x i8> %b) {
; CHECK-LABEL: test_pabdu_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: pabdu.b a0, a0, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pabdu.v4i8(<4 x i8> %a, <4 x i8> %b)
ret <4 x i8> %res
}
define <2 x i16> @test_pabdu_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pabdu_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pabdu.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pabdu.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pas_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pas_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pas.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pas.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_psa_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psa_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psa.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psa.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_psas_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_psas_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: psas.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psas.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pssa_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pssa_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pssa.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pssa.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_paas_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_paas_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: paas.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.paas.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pasa_x_h(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pasa_x_h:
; CHECK: # %bb.0:
; CHECK-NEXT: pasa.hx a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pasa.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
; Packed reduction sum
define i32 @test_predsum_i8x4_i32(<4 x i8> %a, i32 %b) {
; RV32-LABEL: test_predsum_i8x4_i32:
; RV32: # %bb.0:
; RV32-NEXT: predsum.bs a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_predsum_i8x4_i32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a0, a0
; RV64-NEXT: predsum.bs a0, a0, a1
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.predsum.i32.v4i8(<4 x i8> %a, i32 %b)
ret i32 %res
}
define i32 @test_predsumu_u8x4_u32(<4 x i8> %a, i32 %b) {
; RV32-LABEL: test_predsumu_u8x4_u32:
; RV32: # %bb.0:
; RV32-NEXT: predsumu.bs a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_predsumu_u8x4_u32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a0, a0
; RV64-NEXT: predsumu.bs a0, a0, a1
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.predsumu.i32.v4i8(<4 x i8> %a, i32 %b)
ret i32 %res
}
define i32 @test_predsum_i16x2_i32(<2 x i16> %a, i32 %b) {
; RV32-LABEL: test_predsum_i16x2_i32:
; RV32: # %bb.0:
; RV32-NEXT: predsum.hs a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_predsum_i16x2_i32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a0, a0
; RV64-NEXT: predsum.hs a0, a0, a1
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.predsum.i32.v2i16(<2 x i16> %a, i32 %b)
ret i32 %res
}
define i32 @test_predsumu_u16x2_u32(<2 x i16> %a, i32 %b) {
; RV32-LABEL: test_predsumu_u16x2_u32:
; RV32: # %bb.0:
; RV32-NEXT: predsumu.hs a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_predsumu_u16x2_u32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a0, a0
; RV64-NEXT: predsumu.hs a0, a0, a1
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.predsumu.i32.v2i16(<2 x i16> %a, i32 %b)
ret i32 %res
}
; Packed Merge
define <4 x i8> @test_pmerge_merge_u8x4(<4 x i8> %rd, <4 x i8> %rs1, <4 x i8> %rs2) {
; CHECK-LABEL: test_pmerge_merge_u8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <4 x i8> @test_pmerge_mvm_u8x4(<4 x i8> %rs1, <4 x i8> %rd, <4 x i8> %rs2) {
; CHECK-LABEL: test_pmerge_mvm_u8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: mvm a0, a2, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <4 x i8> @test_pmerge_mvmn_u8x4(<4 x i8> %rs2, <4 x i8> %rs1, <4 x i8> %rd) {
; CHECK-LABEL: test_pmerge_mvmn_u8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: mvmn a0, a1, a2
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <4 x i8> @test_pmerge_merge_i8x4(<4 x i8> %rd, <4 x i8> %rs1, <4 x i8> %rs2) {
; CHECK-LABEL: test_pmerge_merge_i8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <4 x i8> @test_pmerge_mvm_i8x4(<4 x i8> %rs1, <4 x i8> %rd, <4 x i8> %rs2) {
; CHECK-LABEL: test_pmerge_mvm_i8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: mvm a0, a2, a1
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <4 x i8> @test_pmerge_mvmn_i8x4(<4 x i8> %rs2, <4 x i8> %rs1, <4 x i8> %rd) {
; CHECK-LABEL: test_pmerge_mvmn_i8x4:
; CHECK: # %bb.0:
; CHECK-NEXT: mvmn a0, a1, a2
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.pmerge.v4i8(<4 x i8> %rs1, <4 x i8> %rs2, <4 x i8> %rd)
ret <4 x i8> %res
}
define <2 x i16> @test_pmerge_merge_u16x2(<2 x i16> %rd, <2 x i16> %rs1, <2 x i16> %rs2) {
; CHECK-LABEL: test_pmerge_merge_u16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
define <2 x i16> @test_pmerge_mvm_u16x2(<2 x i16> %rs1, <2 x i16> %rd, <2 x i16> %rs2) {
; CHECK-LABEL: test_pmerge_mvm_u16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: mvm a0, a2, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
define <2 x i16> @test_pmerge_mvmn_u16x2(<2 x i16> %rs2, <2 x i16> %rs1, <2 x i16> %rd) {
; CHECK-LABEL: test_pmerge_mvmn_u16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: mvmn a0, a1, a2
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
define <2 x i16> @test_pmerge_merge_i16x2(<2 x i16> %rd, <2 x i16> %rs1, <2 x i16> %rs2) {
; CHECK-LABEL: test_pmerge_merge_i16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: merge a0, a1, a2
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
define <2 x i16> @test_pmerge_mvm_i16x2(<2 x i16> %rs1, <2 x i16> %rd, <2 x i16> %rs2) {
; CHECK-LABEL: test_pmerge_mvm_i16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: mvm a0, a2, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
define <2 x i16> @test_pmerge_mvmn_i16x2(<2 x i16> %rs2, <2 x i16> %rs1, <2 x i16> %rd) {
; CHECK-LABEL: test_pmerge_mvmn_i16x2:
; CHECK: # %bb.0:
; CHECK-NEXT: mvmn a0, a1, a2
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmerge.v2i16(<2 x i16> %rs1, <2 x i16> %rs2, <2 x i16> %rd)
ret <2 x i16> %res
}
; Packed sign and zero extend
define <2 x i16> @test_psext_b_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_psext_b_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: psext.h.b a0, a0
; CHECK-NEXT: ret
%shl = shl <2 x i16> %a, splat (i16 8)
%res = ashr <2 x i16> %shl, splat (i16 8)
ret <2 x i16> %res
}
define <2 x i16> @test_pzext_b_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_pzext_b_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pzext.h.b a0, a0
; CHECK-NEXT: ret
%res = and <2 x i16> %a, splat (i16 255)
ret <2 x i16> %res
}
define <2 x i16> @test_riscv_psext_b_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_riscv_psext_b_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: psext.h.b a0, a0
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psext.b.v2i16(<2 x i16> %a)
ret <2 x i16> %res
}
define <2 x i16> @test_riscv_pzext_b_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_riscv_pzext_b_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pzext.h.b a0, a0
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pzext.b.v2i16(<2 x i16> %a)
ret <2 x i16> %res
}
; Packed absolute difference sum
define i32 @test_pabdsumu_u8x4_u32(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pabdsumu_u8x4_u32:
; RV32: # %bb.0:
; RV32-NEXT: pabdsumu.b a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: test_pabdsumu_u8x4_u32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a1, a1
; RV64-NEXT: zext.w a0, a0
; RV64-NEXT: pabdsumu.b a0, a0, a1
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.pabdsumu.i32.v4i8(<4 x i8> %a, <4 x i8> %b)
ret i32 %res
}
define i32 @test_pabdsumau_u8x4_u32(i32 %rd, <4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pabdsumau_u8x4_u32:
; RV32: # %bb.0:
; RV32-NEXT: pabdsumau.b a0, a1, a2
; RV32-NEXT: ret
;
; RV64-LABEL: test_pabdsumau_u8x4_u32:
; RV64: # %bb.0:
; RV64-NEXT: zext.w a2, a2
; RV64-NEXT: zext.w a1, a1
; RV64-NEXT: pabdsumau.b a0, a1, a2
; RV64-NEXT: ret
%res = call i32 @llvm.riscv.pabdsumau.i32.v4i8(i32 %rd, <4 x i8> %a, <4 x i8> %b)
ret i32 %res
}
; Packed Saturating Absolute Value
define <4 x i8> @test_psabs_v4i8(<4 x i8> %a) {
; CHECK-LABEL: test_psabs_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: psabs.b a0, a0
; CHECK-NEXT: ret
%res = call <4 x i8> @llvm.riscv.psabs.v4i8(<4 x i8> %a)
ret <4 x i8> %res
}
define <2 x i16> @test_psabs_v2i16(<2 x i16> %a) {
; CHECK-LABEL: test_psabs_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: psabs.h a0, a0
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.psabs.v2i16(<2 x i16> %a)
ret <2 x i16> %res
}
define <4 x i8> @test_undef_v4i8() {
; CHECK-LABEL: test_undef_v4i8:
; CHECK: # %bb.0:
; CHECK-NEXT: ret
ret <4 x i8> undef
}
define <2 x i16> @test_undef_v2i16() {
; CHECK-LABEL: test_undef_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: ret
ret <2 x i16> undef
}
define <2 x i16> @test_pmulq_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulq_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulq.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmulq.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}
define <2 x i16> @test_pmulqr_v2i16(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: test_pmulqr_v2i16:
; CHECK: # %bb.0:
; CHECK-NEXT: pmulqr.h a0, a0, a1
; CHECK-NEXT: ret
%res = call <2 x i16> @llvm.riscv.pmulqr.v2i16(<2 x i16> %a, <2 x i16> %b)
ret <2 x i16> %res
}