| ; 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,CHECK-RV32 %s |
| ; RUN: llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \ |
| ; RUN: -verify-machineinstrs < %s | \ |
| ; RUN: FileCheck --check-prefixes=CHECK,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 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 |
| } |
| |
| ; 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 |
| %res = add <2 x i16> <i16 42, i16 42>, <i16 0, i16 0> |
| ret <2 x i16> %res |
| } |
| |
| 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 |
| %res = add <2 x i16> <i16 -5, i16 -5>, <i16 0, i16 0> |
| ret <2 x i16> %res |
| } |
| |
| ; 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 |
| %res = add <4 x i8> <i8 32, i8 32, i8 32, i8 32>, <i8 0, i8 0, i8 0, i8 0> |
| ret <4 x i8> %res |
| } |
| |
| 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 |
| %res = add <4 x i8> <i8 -2, i8 -2, i8 -2, i8 -2>, <i8 0, i8 0, i8 0, i8 0> |
| ret <4 x i8> %res |
| } |
| |
| 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) { |
| ; CHECK-RV32-LABEL: test_insert_vector_16: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: pack a0, a1, a0 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_insert_vector_16: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a1, a0 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_insert_vector_16_elem1: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_insert_vector_16_elem1: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_insert_vector_8: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: li a2, 255 |
| ; CHECK-RV32-NEXT: mvm a0, a1, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_insert_vector_8: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a0, 8 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a0, a3 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a1, a2 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a1, a0 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_insert_vector_8_elem2: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: slli a1, a1, 16 |
| ; CHECK-RV32-NEXT: lui a2, 4080 |
| ; CHECK-RV32-NEXT: mvm a0, a1, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_insert_vector_8_elem2: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a0, 8 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a1, a3 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a0, a2 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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: padd.bs a0, zero, 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: padd.hs a0, zero, 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 |
| } |
| |
| define <4 x i8> @test_build_vector_i8(i8 %a, i8 %c, i8 %b, i8 %d) { |
| ; CHECK-RV32-LABEL: test_build_vector_i8: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: ppaire.db a0, a0, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_build_vector_i8: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: ppaire.b a1, a1, a3 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a0, a2 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_build_vector_i16: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_build_vector_i16: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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 arithmetic saturation shift left immediate 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 arithmetic saturation shift left immediate for v4i8 |
| define <4 x i8> @test_psslai_b(<4 x i8> %a) { |
| ; CHECK-LABEL: test_psslai_b: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: pmslt.b a1, a0, zero |
| ; CHECK-NEXT: li a2, 128 |
| ; CHECK-NEXT: pli.b a3, 127 |
| ; CHECK-NEXT: padd.bs a2, zero, a2 |
| ; CHECK-NEXT: merge a1, a3, a2 |
| ; CHECK-NEXT: pslli.b a2, a0, 2 |
| ; CHECK-NEXT: psrai.b a3, a2, 2 |
| ; CHECK-NEXT: pmseq.b a0, a0, a3 |
| ; CHECK-NEXT: merge a0, a1, a2 |
| ; 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 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 |
| } |
| |
| 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 |
| } |
| |
| ; Test logical shift left(vector shamt) |
| define <2 x i16> @test_psll_hs_vec_shamt(<2 x i16> %a, <2 x i16> %b) { |
| ; CHECK-RV32-LABEL: test_psll_hs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: sll a2, a0, a1 |
| ; CHECK-RV32-NEXT: srli a1, a1, 16 |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: sll a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a2, a0 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psll_hs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: sll a2, a0, a1 |
| ; CHECK-RV64-NEXT: srli a1, a1, 16 |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: sll a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a2, a0 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psll_bs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 24 |
| ; CHECK-RV32-NEXT: srli a3, a0, 24 |
| ; CHECK-RV32-NEXT: srli a4, a1, 8 |
| ; CHECK-RV32-NEXT: srli a5, a0, 8 |
| ; CHECK-RV32-NEXT: sll a3, a3, a2 |
| ; CHECK-RV32-NEXT: sll a2, a5, a4 |
| ; CHECK-RV32-NEXT: sll a4, a0, a1 |
| ; CHECK-RV32-NEXT: srli a1, a1, 16 |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: sll a5, a0, a1 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psll_bs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 24 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: srli a4, a1, 16 |
| ; CHECK-RV64-NEXT: sll a2, a3, a2 |
| ; CHECK-RV64-NEXT: srli a3, a0, 16 |
| ; CHECK-RV64-NEXT: sll a3, a3, a4 |
| ; CHECK-RV64-NEXT: sll a4, a0, a1 |
| ; CHECK-RV64-NEXT: srli a1, a1, 8 |
| ; CHECK-RV64-NEXT: srli a0, a0, 8 |
| ; CHECK-RV64-NEXT: sll a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a3, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a4, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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 |
| } |
| |
| 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 |
| } |
| |
| ; 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 |
| } |
| |
| 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 |
| } |
| |
| ; Test logical shift right(vector shamt) |
| define <2 x i16> @test_psrl_hs_vec_shamt(<2 x i16> %a, <2 x i16> %b) { |
| ; CHECK-RV32-LABEL: test_psrl_hs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 16 |
| ; CHECK-RV32-NEXT: srli a3, a0, 16 |
| ; CHECK-RV32-NEXT: zext.h a0, a0 |
| ; CHECK-RV32-NEXT: srl a2, a3, a2 |
| ; CHECK-RV32-NEXT: srl a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psrl_hs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 16 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 16 |
| ; CHECK-RV64-NEXT: zext.h a0, a0 |
| ; CHECK-RV64-NEXT: srl a2, a3, a2 |
| ; CHECK-RV64-NEXT: srl a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a2 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psrl_bs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 24 |
| ; CHECK-RV32-NEXT: srli a3, a0, 24 |
| ; CHECK-RV32-NEXT: srli a4, a1, 8 |
| ; CHECK-RV32-NEXT: slli a5, a0, 16 |
| ; CHECK-RV32-NEXT: srl a3, a3, a2 |
| ; CHECK-RV32-NEXT: srli a5, a5, 24 |
| ; CHECK-RV32-NEXT: srl a2, a5, a4 |
| ; CHECK-RV32-NEXT: zext.b a4, a0 |
| ; CHECK-RV32-NEXT: srli a5, a1, 16 |
| ; CHECK-RV32-NEXT: slli a0, a0, 8 |
| ; CHECK-RV32-NEXT: srl a4, a4, a1 |
| ; CHECK-RV32-NEXT: srli a0, a0, 24 |
| ; CHECK-RV32-NEXT: srl a5, a0, a5 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psrl_bs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 24 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 24 |
| ; CHECK-RV64-NEXT: srli a4, a1, 16 |
| ; CHECK-RV64-NEXT: srl a2, a3, a2 |
| ; CHECK-RV64-NEXT: slli a3, a0, 40 |
| ; CHECK-RV64-NEXT: srli a3, a3, 56 |
| ; CHECK-RV64-NEXT: srl a3, a3, a4 |
| ; CHECK-RV64-NEXT: zext.b a4, a0 |
| ; CHECK-RV64-NEXT: srl a4, a4, a1 |
| ; CHECK-RV64-NEXT: srli a1, a1, 8 |
| ; CHECK-RV64-NEXT: slli a0, a0, 48 |
| ; CHECK-RV64-NEXT: srli a0, a0, 56 |
| ; CHECK-RV64-NEXT: srl a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a3, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a4, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psra_hs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 16 |
| ; CHECK-RV32-NEXT: srai a3, a0, 16 |
| ; CHECK-RV32-NEXT: sext.h a0, a0 |
| ; CHECK-RV32-NEXT: sra a2, a3, a2 |
| ; CHECK-RV32-NEXT: sra a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psra_hs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: sext.h a2, a0 |
| ; CHECK-RV64-NEXT: sra a2, a2, a1 |
| ; CHECK-RV64-NEXT: srli a1, a1, 16 |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: sext.h a0, a0 |
| ; CHECK-RV64-NEXT: sra a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a2, a0 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psra_bs_vec_shamt: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 24 |
| ; CHECK-RV32-NEXT: srai a3, a0, 24 |
| ; CHECK-RV32-NEXT: srli a4, a1, 8 |
| ; CHECK-RV32-NEXT: srli a5, a0, 8 |
| ; CHECK-RV32-NEXT: sra a3, a3, a2 |
| ; CHECK-RV32-NEXT: sext.b a2, a5 |
| ; CHECK-RV32-NEXT: sra a2, a2, a4 |
| ; CHECK-RV32-NEXT: sext.b a4, a0 |
| ; CHECK-RV32-NEXT: srli a5, a1, 16 |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: sra a4, a4, a1 |
| ; CHECK-RV32-NEXT: sext.b a0, a0 |
| ; CHECK-RV32-NEXT: sra a5, a0, a5 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psra_bs_vec_shamt: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 24 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: srli a4, a1, 16 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: sra a2, a3, a2 |
| ; CHECK-RV64-NEXT: srli a3, a0, 16 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: sra a3, a3, a4 |
| ; CHECK-RV64-NEXT: sext.b a4, a0 |
| ; CHECK-RV64-NEXT: sra a4, a4, a1 |
| ; CHECK-RV64-NEXT: srli a1, a1, 8 |
| ; CHECK-RV64-NEXT: srli a0, a0, 8 |
| ; CHECK-RV64-NEXT: sext.b a0, a0 |
| ; CHECK-RV64-NEXT: sra a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a3, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a4, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-RV64-NEXT: ret |
| %res = ashr <4 x i8> %a, %b |
| 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) { |
| ; CHECK-RV32-LABEL: test_pmul_h: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: pwmul.h a0, a0, a1 |
| ; CHECK-RV32-NEXT: pnsrli.h a0, a0, 0 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_pmul_h: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: pmul.w.h11 a2, a0, a1 |
| ; CHECK-RV64-NEXT: pmul.w.h00 a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a2 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_pmul_b: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: pwmul.b a0, a0, a1 |
| ; CHECK-RV32-NEXT: pnsrli.b a0, a0, 0 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_pmul_b: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: pmul.h.b11 a2, a0, a1 |
| ; CHECK-RV64-NEXT: pmul.h.b00 a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a0, a2 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psdiv_h: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srai a2, a1, 16 |
| ; CHECK-RV32-NEXT: srai a3, a0, 16 |
| ; CHECK-RV32-NEXT: sext.h a1, a1 |
| ; CHECK-RV32-NEXT: sext.h a0, a0 |
| ; CHECK-RV32-NEXT: div a2, a3, a2 |
| ; CHECK-RV32-NEXT: div a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psdiv_h: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: sext.h a2, a1 |
| ; CHECK-RV64-NEXT: sext.h a3, a0 |
| ; CHECK-RV64-NEXT: srli a1, a1, 16 |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: divw a2, a3, a2 |
| ; CHECK-RV64-NEXT: sext.h a1, a1 |
| ; CHECK-RV64-NEXT: sext.h a0, a0 |
| ; CHECK-RV64-NEXT: divw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a2, a0 |
| ; CHECK-RV64-NEXT: ret |
| %res = sdiv <2 x i16> %a, %b |
| ret <2 x i16> %res |
| } |
| |
| define <4 x i8> @test_psdiv_b(<4 x i8> %a, <4 x i8> %b) { |
| ; CHECK-RV32-LABEL: test_psdiv_b: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srai a2, a1, 24 |
| ; CHECK-RV32-NEXT: srai a3, a0, 24 |
| ; CHECK-RV32-NEXT: srli a4, a1, 8 |
| ; CHECK-RV32-NEXT: srli a5, a0, 8 |
| ; CHECK-RV32-NEXT: div a3, a3, a2 |
| ; CHECK-RV32-NEXT: sext.b a2, a4 |
| ; CHECK-RV32-NEXT: sext.b a4, a5 |
| ; CHECK-RV32-NEXT: div a2, a4, a2 |
| ; CHECK-RV32-NEXT: sext.b a4, a1 |
| ; CHECK-RV32-NEXT: sext.b a5, a0 |
| ; CHECK-RV32-NEXT: srli a1, a1, 16 |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: div a4, a5, a4 |
| ; CHECK-RV32-NEXT: sext.b a1, a1 |
| ; CHECK-RV32-NEXT: sext.b a0, a0 |
| ; CHECK-RV32-NEXT: div a5, a0, a1 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psdiv_b: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 24 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: sext.b a4, a1 |
| ; CHECK-RV64-NEXT: sext.b a5, a0 |
| ; CHECK-RV64-NEXT: divw a4, a5, a4 |
| ; CHECK-RV64-NEXT: srli a5, a1, 16 |
| ; CHECK-RV64-NEXT: sext.b a2, a2 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: divw a2, a3, a2 |
| ; CHECK-RV64-NEXT: srli a3, a0, 16 |
| ; CHECK-RV64-NEXT: sext.b a5, a5 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: divw a3, a3, a5 |
| ; CHECK-RV64-NEXT: srli a1, a1, 8 |
| ; CHECK-RV64-NEXT: srli a0, a0, 8 |
| ; CHECK-RV64-NEXT: sext.b a1, a1 |
| ; CHECK-RV64-NEXT: sext.b a0, a0 |
| ; CHECK-RV64-NEXT: divw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a3, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a4, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_pudiv_h: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 16 |
| ; CHECK-RV32-NEXT: srli a3, a0, 16 |
| ; CHECK-RV32-NEXT: zext.h a1, a1 |
| ; CHECK-RV32-NEXT: zext.h a0, a0 |
| ; CHECK-RV32-NEXT: divu a2, a3, a2 |
| ; CHECK-RV32-NEXT: divu a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_pudiv_h: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srliw a2, a1, 16 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 16 |
| ; CHECK-RV64-NEXT: zext.h a1, a1 |
| ; CHECK-RV64-NEXT: zext.h a0, a0 |
| ; CHECK-RV64-NEXT: divuw a2, a3, a2 |
| ; CHECK-RV64-NEXT: divuw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a2 |
| ; CHECK-RV64-NEXT: ret |
| %res = udiv <2 x i16> %a, %b |
| ret <2 x i16> %res |
| } |
| |
| define <4 x i8> @test_pudiv_b(<4 x i8> %a, <4 x i8> %b) { |
| ; CHECK-RV32-LABEL: test_pudiv_b: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 24 |
| ; CHECK-RV32-NEXT: srli a3, a0, 24 |
| ; CHECK-RV32-NEXT: slli a4, a1, 16 |
| ; CHECK-RV32-NEXT: slli a5, a0, 16 |
| ; CHECK-RV32-NEXT: divu a3, a3, a2 |
| ; CHECK-RV32-NEXT: srli a4, a4, 24 |
| ; CHECK-RV32-NEXT: srli a5, a5, 24 |
| ; CHECK-RV32-NEXT: divu a2, a5, a4 |
| ; CHECK-RV32-NEXT: zext.b a4, a1 |
| ; CHECK-RV32-NEXT: zext.b a5, a0 |
| ; CHECK-RV32-NEXT: slli a1, a1, 8 |
| ; CHECK-RV32-NEXT: slli a0, a0, 8 |
| ; CHECK-RV32-NEXT: divu a4, a5, a4 |
| ; CHECK-RV32-NEXT: srli a1, a1, 24 |
| ; CHECK-RV32-NEXT: srli a0, a0, 24 |
| ; CHECK-RV32-NEXT: divu a5, a0, a1 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_pudiv_b: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srliw a2, a1, 24 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 24 |
| ; CHECK-RV64-NEXT: slli a4, a1, 40 |
| ; CHECK-RV64-NEXT: zext.b a5, a1 |
| ; CHECK-RV64-NEXT: divuw a2, a3, a2 |
| ; CHECK-RV64-NEXT: zext.b a3, a0 |
| ; CHECK-RV64-NEXT: divuw a3, a3, a5 |
| ; CHECK-RV64-NEXT: slli a5, a0, 40 |
| ; CHECK-RV64-NEXT: srli a4, a4, 56 |
| ; CHECK-RV64-NEXT: srli a5, a5, 56 |
| ; CHECK-RV64-NEXT: divuw a4, a5, a4 |
| ; CHECK-RV64-NEXT: slli a1, a1, 48 |
| ; CHECK-RV64-NEXT: slli a0, a0, 48 |
| ; CHECK-RV64-NEXT: srli a1, a1, 56 |
| ; CHECK-RV64-NEXT: srli a0, a0, 56 |
| ; CHECK-RV64-NEXT: divuw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a4, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a3, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-RV64-NEXT: ret |
| %res = udiv <4 x i8> %a, %b |
| ret <4 x i8> %res |
| } |
| |
| define <2 x i16> @test_psrem_h(<2 x i16> %a, <2 x i16> %b) { |
| ; CHECK-RV32-LABEL: test_psrem_h: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srai a2, a1, 16 |
| ; CHECK-RV32-NEXT: srai a3, a0, 16 |
| ; CHECK-RV32-NEXT: sext.h a1, a1 |
| ; CHECK-RV32-NEXT: sext.h a0, a0 |
| ; CHECK-RV32-NEXT: rem a2, a3, a2 |
| ; CHECK-RV32-NEXT: rem a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psrem_h: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: sext.h a2, a1 |
| ; CHECK-RV64-NEXT: sext.h a3, a0 |
| ; CHECK-RV64-NEXT: srli a1, a1, 16 |
| ; CHECK-RV64-NEXT: srli a0, a0, 16 |
| ; CHECK-RV64-NEXT: remw a2, a3, a2 |
| ; CHECK-RV64-NEXT: sext.h a1, a1 |
| ; CHECK-RV64-NEXT: sext.h a0, a0 |
| ; CHECK-RV64-NEXT: remw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a2, a0 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_psrem_b: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srai a2, a1, 24 |
| ; CHECK-RV32-NEXT: srai a3, a0, 24 |
| ; CHECK-RV32-NEXT: srli a4, a1, 8 |
| ; CHECK-RV32-NEXT: srli a5, a0, 8 |
| ; CHECK-RV32-NEXT: rem a3, a3, a2 |
| ; CHECK-RV32-NEXT: sext.b a2, a4 |
| ; CHECK-RV32-NEXT: sext.b a4, a5 |
| ; CHECK-RV32-NEXT: rem a2, a4, a2 |
| ; CHECK-RV32-NEXT: sext.b a4, a1 |
| ; CHECK-RV32-NEXT: sext.b a5, a0 |
| ; CHECK-RV32-NEXT: srli a1, a1, 16 |
| ; CHECK-RV32-NEXT: srli a0, a0, 16 |
| ; CHECK-RV32-NEXT: rem a4, a5, a4 |
| ; CHECK-RV32-NEXT: sext.b a1, a1 |
| ; CHECK-RV32-NEXT: sext.b a0, a0 |
| ; CHECK-RV32-NEXT: rem a5, a0, a1 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_psrem_b: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srli a2, a1, 24 |
| ; CHECK-RV64-NEXT: srli a3, a0, 24 |
| ; CHECK-RV64-NEXT: sext.b a4, a1 |
| ; CHECK-RV64-NEXT: sext.b a5, a0 |
| ; CHECK-RV64-NEXT: remw a4, a5, a4 |
| ; CHECK-RV64-NEXT: srli a5, a1, 16 |
| ; CHECK-RV64-NEXT: sext.b a2, a2 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: remw a2, a3, a2 |
| ; CHECK-RV64-NEXT: srli a3, a0, 16 |
| ; CHECK-RV64-NEXT: sext.b a5, a5 |
| ; CHECK-RV64-NEXT: sext.b a3, a3 |
| ; CHECK-RV64-NEXT: remw a3, a3, a5 |
| ; CHECK-RV64-NEXT: srli a1, a1, 8 |
| ; CHECK-RV64-NEXT: srli a0, a0, 8 |
| ; CHECK-RV64-NEXT: sext.b a1, a1 |
| ; CHECK-RV64-NEXT: sext.b a0, a0 |
| ; CHECK-RV64-NEXT: remw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a3, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a4, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_purem_h: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 16 |
| ; CHECK-RV32-NEXT: srli a3, a0, 16 |
| ; CHECK-RV32-NEXT: zext.h a1, a1 |
| ; CHECK-RV32-NEXT: zext.h a0, a0 |
| ; CHECK-RV32-NEXT: remu a2, a3, a2 |
| ; CHECK-RV32-NEXT: remu a0, a0, a1 |
| ; CHECK-RV32-NEXT: pack a0, a0, a2 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_purem_h: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srliw a2, a1, 16 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 16 |
| ; CHECK-RV64-NEXT: zext.h a1, a1 |
| ; CHECK-RV64-NEXT: zext.h a0, a0 |
| ; CHECK-RV64-NEXT: remuw a2, a3, a2 |
| ; CHECK-RV64-NEXT: remuw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a2 |
| ; CHECK-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) { |
| ; CHECK-RV32-LABEL: test_purem_b: |
| ; CHECK-RV32: # %bb.0: |
| ; CHECK-RV32-NEXT: srli a2, a1, 24 |
| ; CHECK-RV32-NEXT: srli a3, a0, 24 |
| ; CHECK-RV32-NEXT: slli a4, a1, 16 |
| ; CHECK-RV32-NEXT: slli a5, a0, 16 |
| ; CHECK-RV32-NEXT: remu a3, a3, a2 |
| ; CHECK-RV32-NEXT: srli a4, a4, 24 |
| ; CHECK-RV32-NEXT: srli a5, a5, 24 |
| ; CHECK-RV32-NEXT: remu a2, a5, a4 |
| ; CHECK-RV32-NEXT: zext.b a4, a1 |
| ; CHECK-RV32-NEXT: zext.b a5, a0 |
| ; CHECK-RV32-NEXT: slli a1, a1, 8 |
| ; CHECK-RV32-NEXT: slli a0, a0, 8 |
| ; CHECK-RV32-NEXT: remu a4, a5, a4 |
| ; CHECK-RV32-NEXT: srli a1, a1, 24 |
| ; CHECK-RV32-NEXT: srli a0, a0, 24 |
| ; CHECK-RV32-NEXT: remu a5, a0, a1 |
| ; CHECK-RV32-NEXT: ppaire.db a0, a4, a2 |
| ; CHECK-RV32-NEXT: pack a0, a0, a1 |
| ; CHECK-RV32-NEXT: ret |
| ; |
| ; CHECK-RV64-LABEL: test_purem_b: |
| ; CHECK-RV64: # %bb.0: |
| ; CHECK-RV64-NEXT: srliw a2, a1, 24 |
| ; CHECK-RV64-NEXT: srliw a3, a0, 24 |
| ; CHECK-RV64-NEXT: slli a4, a1, 40 |
| ; CHECK-RV64-NEXT: zext.b a5, a1 |
| ; CHECK-RV64-NEXT: remuw a2, a3, a2 |
| ; CHECK-RV64-NEXT: zext.b a3, a0 |
| ; CHECK-RV64-NEXT: remuw a3, a3, a5 |
| ; CHECK-RV64-NEXT: slli a5, a0, 40 |
| ; CHECK-RV64-NEXT: srli a4, a4, 56 |
| ; CHECK-RV64-NEXT: srli a5, a5, 56 |
| ; CHECK-RV64-NEXT: remuw a4, a5, a4 |
| ; CHECK-RV64-NEXT: slli a1, a1, 48 |
| ; CHECK-RV64-NEXT: slli a0, a0, 48 |
| ; CHECK-RV64-NEXT: srli a1, a1, 56 |
| ; CHECK-RV64-NEXT: srli a0, a0, 56 |
| ; CHECK-RV64-NEXT: remuw a0, a0, a1 |
| ; CHECK-RV64-NEXT: ppaire.b a1, a4, a2 |
| ; CHECK-RV64-NEXT: ppaire.b a0, a3, a0 |
| ; CHECK-RV64-NEXT: ppaire.h a0, a0, a1 |
| ; CHECK-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_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_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_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_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, .LBB120_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: mv a0, a2 |
| ; CHECK-NEXT: .LBB120_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, .LBB121_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: mv a0, a2 |
| ; CHECK-NEXT: .LBB121_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 |
| } |