| ; 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 %s --check-prefixes=CHECK,RV32 |
| ; RUN: llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \ |
| ; RUN: -verify-machineinstrs < %s | \ |
| ; RUN: FileCheck %s --check-prefixes=CHECK,RV64 |
| |
| ; Test basic add/sub operations for v4i16 |
| define <4 x i16> @test_padd_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_padd_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = add <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psub_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psub_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psub.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psub_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psub.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sub <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| ; Test basic add/sub operations for v8i8 |
| define <8 x i8> @test_padd_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_padd_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = add <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_psub_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_psub_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psub.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psub_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psub.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sub <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| ; Test bitwise operations for v4i16 (use scalar instructions) |
| define <4 x i16> @test_and_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_and_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: and a1, a1, a3 |
| ; RV32-NEXT: and a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_and_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: and a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = and <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_or_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_or_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: or a1, a1, a3 |
| ; RV32-NEXT: or a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_or_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: or a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = or <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_xor_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_xor_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xor a1, a1, a3 |
| ; RV32-NEXT: xor a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xor_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xor a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = xor <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_andn_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_andn_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andn a1, a1, a3 |
| ; RV32-NEXT: andn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_andn_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <4 x i16> %b, splat (i16 -1) |
| %res = and <4 x i16> %a, %not |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_orn_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_orn_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: orn a1, a1, a3 |
| ; RV32-NEXT: orn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_orn_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: orn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <4 x i16> %b, splat (i16 -1) |
| %res = or <4 x i16> %a, %not |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_xnor_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_xnor_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xnor a1, a3, a1 |
| ; RV32-NEXT: xnor a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xnor_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xnor a0, a1, a0 |
| ; RV64-NEXT: ret |
| %not = xor <4 x i16> %b, splat (i16 -1) |
| %res = xor <4 x i16> %a, %not |
| ret <4 x i16> %res |
| } |
| |
| ; Test bitwise operations for v8i8 (use scalar instructions) |
| define <8 x i8> @test_and_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_and_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: and a1, a1, a3 |
| ; RV32-NEXT: and a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_and_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: and a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = and <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_or_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_or_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: or a1, a1, a3 |
| ; RV32-NEXT: or a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_or_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: or a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = or <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_xor_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_xor_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xor a1, a1, a3 |
| ; RV32-NEXT: xor a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xor_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xor a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = xor <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_andn_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_andn_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andn a1, a1, a3 |
| ; RV32-NEXT: andn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_andn_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <8 x i8> %b, splat (i8 -1) |
| %res = and <8 x i8> %a, %not |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_orn_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_orn_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: orn a1, a1, a3 |
| ; RV32-NEXT: orn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_orn_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: orn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <8 x i8> %b, splat (i8 -1) |
| %res = or <8 x i8> %a, %not |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_xnor_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_xnor_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xnor a1, a3, a1 |
| ; RV32-NEXT: xnor a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xnor_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xnor a0, a1, a0 |
| ; RV64-NEXT: ret |
| %not = xor <8 x i8> %b, splat (i8 -1) |
| %res = xor <8 x i8> %a, %not |
| ret <8 x i8> %res |
| } |
| |
| ; Test bitwise operations for v2i32 (use scalar instructions) |
| define <2 x i32> @test_and_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_and_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: and a1, a1, a3 |
| ; RV32-NEXT: and a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_and_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: and a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = and <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_or_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_or_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: or a1, a1, a3 |
| ; RV32-NEXT: or a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_or_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: or a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = or <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_xor_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_xor_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xor a1, a1, a3 |
| ; RV32-NEXT: xor a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xor_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xor a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = xor <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_andn_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_andn_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andn a1, a1, a3 |
| ; RV32-NEXT: andn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_andn_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <2 x i32> %b, splat (i32 -1) |
| %res = and <2 x i32> %a, %not |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_orn_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_orn_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: orn a1, a1, a3 |
| ; RV32-NEXT: orn a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_orn_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: orn a0, a0, a1 |
| ; RV64-NEXT: ret |
| %not = xor <2 x i32> %b, splat (i32 -1) |
| %res = or <2 x i32> %a, %not |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_xnor_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_xnor_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: xnor a1, a3, a1 |
| ; RV32-NEXT: xnor a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_xnor_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: xnor a0, a1, a0 |
| ; RV64-NEXT: ret |
| %not = xor <2 x i32> %b, splat (i32 -1) |
| %res = xor <2 x i32> %a, %not |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_not_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_not_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_not_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %res = xor <4 x i16> %a, splat(i16 -1) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_not_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_not_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_not_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %res = xor <8 x i8> %a, splat(i8 -1) |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_not_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_not_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_not_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %res = xor <2 x i32> %a, splat(i32 -1) |
| ret <2 x i32> %res |
| } |
| |
| ; Test saturating add operations for v4i16 |
| define <4 x i16> @test_psadd_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psadd_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psadd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psadd_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psadd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psaddu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psaddu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psaddu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psaddu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psaddu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| ; Test saturating sub operations for v4i16 |
| define <4 x i16> @test_pssub_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssub_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssub.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssub_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssub.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pssubu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssubu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssubu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssubu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssubu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| ; Test shift-add operations for v4i16 |
| define <4 x i16> @test_psh1add_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psh1add_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psh1add.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psh1add_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psh1add.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = shl <4 x i16> %a, splat (i16 1) |
| %res = add <4 x i16> %shl, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pssh1sadd_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssh1sadd_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssh1sadd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssh1sadd_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssh1sadd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = call <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> splat (i16 1)) |
| %res = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %shl, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pssh1sadd_h_addself(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssh1sadd_h_addself: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssh1sadd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssh1sadd_h_addself: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssh1sadd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %a, <4 x i16> %a) |
| %res = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %shl, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| ; Test saturating add operations for v8i8 |
| define <8 x i8> @test_psadd_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_psadd_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psadd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psadd_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psadd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_psaddu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_psaddu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psaddu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psaddu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psaddu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| ; Test saturating sub operations for v8i8 |
| define <8 x i8> @test_pssub_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pssub_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssub.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssub_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssub.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pssubu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pssubu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssubu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssubu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssubu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| ; Test averaging floor signed operations for v4i16 |
| ; avgfloors pattern: (a + b) arithmetic shift right 1 |
| define <4 x i16> @test_paadd_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_paadd_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %ext.a = sext <4 x i16> %a to <4 x i32> |
| %ext.b = sext <4 x i16> %b to <4 x i32> |
| %add = add nsw <4 x i32> %ext.a, %ext.b |
| %shift = ashr <4 x i32> %add, <i32 1, i32 1, i32 1, i32 1> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| ; Test averaging floor unsigned operations for v4i16 |
| ; avgflooru pattern: (a & b) + ((a ^ b) >> 1) |
| define <4 x i16> @test_paaddu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_paaddu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %and = and <4 x i16> %a, %b |
| %xor = xor <4 x i16> %a, %b |
| %shift = lshr <4 x i16> %xor, <i16 1, i16 1, i16 1, i16 1> |
| %res = add <4 x i16> %and, %shift |
| ret <4 x i16> %res |
| } |
| |
| ; Test averaging floor signed operations for v8i8 |
| define <8 x i8> @test_paadd_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_paadd_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %ext.a = sext <8 x i8> %a to <8 x i16> |
| %ext.b = sext <8 x i8> %b to <8 x i16> |
| %add = add nsw <8 x i16> %ext.a, %ext.b |
| %shift = ashr <8 x i16> %add, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> |
| %res = trunc <8 x i16> %shift to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| ; Test averaging floor unsigned operations for v8i8 |
| define <8 x i8> @test_paaddu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_paaddu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %and = and <8 x i8> %a, %b |
| %xor = xor <8 x i8> %a, %b |
| %shift = lshr <8 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> |
| %res = add <8 x i8> %and, %shift |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_pabs_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_pabs_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pneg.dw a2, a0 |
| ; RV32-NEXT: pmax.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabs_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pneg.w a1, a0 |
| ; RV64-NEXT: pmax.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %a, i1 0) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_pabs_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_pabs_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabs.dh a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabs_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabs.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 0) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_pabs_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_pabs_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabs.db a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabs_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabs.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.abs.v8i8(<8 x i8> %a, i1 0) |
| ret <8 x i8> %res |
| } |
| |
| ; Test absolute difference signed for v2i32 |
| ; abds pattern: sub(smax(a,b), smin(a,b)) |
| define <2 x i32> @test_pdif_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pdif_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmin.dw a4, a0, a2 |
| ; RV32-NEXT: pmax.dw a0, a0, a2 |
| ; RV32-NEXT: psub.dw a0, a0, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdif_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmin.w a2, a0, a1 |
| ; RV64-NEXT: pmax.w a0, a0, a1 |
| ; RV64-NEXT: psub.w a0, a0, a2 |
| ; RV64-NEXT: ret |
| %min = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %a, <2 x i32> %b) |
| %max = call <2 x i32> @llvm.smax.v2i32(<2 x i32> %a, <2 x i32> %b) |
| %res = sub <2 x i32> %max, %min |
| ret <2 x i32> %res |
| } |
| |
| ; Test absolute difference unsigned for v2i32 |
| ; abdu pattern: sub(umax(a,b), umin(a,b)) |
| define <2 x i32> @test_pdifu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pdifu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pminu.dw a4, a0, a2 |
| ; RV32-NEXT: pmaxu.dw a0, a0, a2 |
| ; RV32-NEXT: psub.dw a0, a0, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdifu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pminu.w a2, a0, a1 |
| ; RV64-NEXT: pmaxu.w a0, a0, a1 |
| ; RV64-NEXT: psub.w a0, a0, a2 |
| ; RV64-NEXT: ret |
| %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %a, <2 x i32> %b) |
| %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %a, <2 x i32> %b) |
| %res = sub <2 x i32> %max, %min |
| ret <2 x i32> %res |
| } |
| |
| ; Test absolute difference signed for v4i16 |
| ; abds pattern: sub(smax(a,b), smin(a,b)) |
| define <4 x i16> @test_pdif_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pdif_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdif_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <4 x i16> @llvm.smin.v4i16(<4 x i16> %a, <4 x i16> %b) |
| %max = call <4 x i16> @llvm.smax.v4i16(<4 x i16> %a, <4 x i16> %b) |
| %res = sub <4 x i16> %max, %min |
| ret <4 x i16> %res |
| } |
| |
| ; Test absolute difference unsigned for v4i16 |
| ; abdu pattern: sub(umax(a,b), umin(a,b)) |
| define <4 x i16> @test_pdifu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pdifu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdifu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <4 x i16> @llvm.umin.v4i16(<4 x i16> %a, <4 x i16> %b) |
| %max = call <4 x i16> @llvm.umax.v4i16(<4 x i16> %a, <4 x i16> %b) |
| %res = sub <4 x i16> %max, %min |
| ret <4 x i16> %res |
| } |
| |
| ; Test absolute difference signed for v8i8 |
| define <8 x i8> @test_pdif_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pdif_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdif_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <8 x i8> @llvm.smin.v8i8(<8 x i8> %a, <8 x i8> %b) |
| %max = call <8 x i8> @llvm.smax.v8i8(<8 x i8> %a, <8 x i8> %b) |
| %res = sub <8 x i8> %max, %min |
| ret <8 x i8> %res |
| } |
| |
| ; Test absolute difference unsigned for v8i8 |
| define <8 x i8> @test_pdifu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pdifu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pdifu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <8 x i8> @llvm.umin.v8i8(<8 x i8> %a, <8 x i8> %b) |
| %max = call <8 x i8> @llvm.umax.v8i8(<8 x i8> %a, <8 x i8> %b) |
| %res = sub <8 x i8> %max, %min |
| ret <8 x i8> %res |
| } |
| |
| ; Test averaging floor subtraction signed for v4i16 |
| ; pasub pattern: (a - b) arithmetic shift right 1 |
| define <4 x i16> @test_pasub_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pasub_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <4 x i16> %a to <4 x i32> |
| %b_ext = sext <4 x i16> %b to <4 x i32> |
| %sub = sub <4 x i32> %a_ext, %b_ext |
| %res = ashr <4 x i32> %sub, <i32 1, i32 1, i32 1, i32 1> |
| %res_trunc = trunc <4 x i32> %res to <4 x i16> |
| ret <4 x i16> %res_trunc |
| } |
| |
| ; Test averaging floor subtraction unsigned for v4i16 |
| ; pasubu pattern: (a - b) logical shift right 1 |
| define <4 x i16> @test_pasubu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pasubu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <4 x i16> %a to <4 x i32> |
| %b_ext = zext <4 x i16> %b to <4 x i32> |
| %sub = sub <4 x i32> %a_ext, %b_ext |
| %res = lshr <4 x i32> %sub, <i32 1, i32 1, i32 1, i32 1> |
| %res_trunc = trunc <4 x i32> %res to <4 x i16> |
| ret <4 x i16> %res_trunc |
| } |
| |
| ; Test averaging floor subtraction signed for v8i8 |
| define <8 x i8> @test_pasub_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pasub_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <8 x i8> %a to <8 x i16> |
| %b_ext = sext <8 x i8> %b to <8 x i16> |
| %sub = sub <8 x i16> %a_ext, %b_ext |
| %res = ashr <8 x i16> %sub, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> |
| %res_trunc = trunc <8 x i16> %res to <8 x i8> |
| ret <8 x i8> %res_trunc |
| } |
| |
| ; Test averaging floor subtraction unsigned for v8i8 |
| define <8 x i8> @test_pasubu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pasubu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <8 x i8> %a to <8 x i16> |
| %b_ext = zext <8 x i8> %b to <8 x i16> |
| %sub = sub <8 x i16> %a_ext, %b_ext |
| %res = lshr <8 x i16> %sub, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> |
| %res_trunc = trunc <8 x i16> %res to <8 x i8> |
| ret <8 x i8> %res_trunc |
| } |
| |
| ; Test PLI (pack load immediate) for v4i16 |
| define <4 x i16> @test_pli_h() { |
| ; RV32-LABEL: test_pli_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.dh a0, 100 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.h a0, 100 |
| ; RV64-NEXT: ret |
| ret <4 x i16> splat (i16 100) |
| } |
| |
| define <2 x i32> @test_pli_h_v2i32() { |
| ; RV32-LABEL: test_pli_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.dh a0, 100 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.h a0, 100 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0x640064) |
| } |
| |
| ; Test PLI for v8i8 with unsigned immediate |
| define <8 x i8> @test_pli_b() { |
| ; RV32-LABEL: test_pli_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, 64 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.b a0, 64 |
| ; RV64-NEXT: ret |
| ret <8 x i8> splat (i8 64) |
| } |
| |
| define <4 x i16> @test_pli_b_v4i16() { |
| ; RV32-LABEL: test_pli_b_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, 64 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_b_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.b a0, 64 |
| ; RV64-NEXT: ret |
| ret <4 x i16> splat (i16 u0x4040) |
| } |
| |
| define <2 x i32> @test_pli_b_v2i32() { |
| ; RV32-LABEL: test_pli_b_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, 64 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_b_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.b a0, 64 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0x40404040) |
| } |
| |
| ; Test PLI for v2i32 with signed immediate |
| define <2 x i32> @test_pli_w() { |
| ; RV32-LABEL: test_pli_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: li a0, -256 |
| ; RV32-NEXT: li a1, -256 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pli_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.w a0, -256 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 -256) |
| } |
| |
| define <4 x i16> @test_plui_h() { |
| ; RV32-LABEL: test_plui_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: plui.dh a0, 100 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.h a0, 100 |
| ; RV64-NEXT: ret |
| ret <4 x i16> splat (i16 u0x1900) |
| } |
| |
| define <4 x i16> @test_plui_h_negative() { |
| ; RV32-LABEL: test_plui_h_negative: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: plui.dh a0, -412 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_h_negative: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.h a0, -412 |
| ; RV64-NEXT: ret |
| ret <4 x i16> splat (i16 u0x9900) |
| } |
| |
| define <2 x i32> @test_plui_h_v2i32() { |
| ; RV32-LABEL: test_plui_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: plui.dh a0, 100 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.h a0, 100 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0x19001900) |
| } |
| |
| define <2 x i32> @test_plui_h_negative_v2i32() { |
| ; RV32-LABEL: test_plui_h_negative_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: plui.dh a0, -412 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_h_negative_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.h a0, -412 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0x99009900) |
| } |
| |
| define <2 x i32> @test_plui_w() { |
| ; RV32-LABEL: test_plui_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a0, 76800 |
| ; RV32-NEXT: lui a1, 76800 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.w a0, 75 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0x12c00000) |
| } |
| |
| define <2 x i32> @test_plui_w_negative() { |
| ; RV32-LABEL: test_plui_w_negative: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a0, 825344 |
| ; RV32-NEXT: lui a1, 825344 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_plui_w_negative: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: plui.w a0, -218 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 u0xc9800000) |
| } |
| |
| define <8 x i8> @test_allones_v8i8() { |
| ; RV32-LABEL: test_allones_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, -1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_allones_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a0, -1 |
| ; RV64-NEXT: ret |
| ret <8 x i8> splat (i8 -1) |
| } |
| |
| define <4 x i16> @test_allones_v4i16() { |
| ; RV32-LABEL: test_allones_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, -1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_allones_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a0, -1 |
| ; RV64-NEXT: ret |
| ret <4 x i16> splat (i16 -1) |
| } |
| |
| define <2 x i32> @test_allones_v2i32() { |
| ; RV32-LABEL: test_allones_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.db a0, -1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_allones_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a0, -1 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 -1) |
| } |
| |
| define i16 @test_extract_vector_16(<4 x i16> %a) { |
| ; CHECK-LABEL: test_extract_vector_16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| %extracted = extractelement <4 x i16> %a, i32 0 |
| ret i16 %extracted |
| } |
| |
| define i8 @test_extract_vector_8(<8 x i8> %a) { |
| ; CHECK-LABEL: test_extract_vector_8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| %extracted = extractelement <8 x i8> %a, i32 0 |
| ret i8 %extracted |
| } |
| |
| define i32 @test_extract_vector_32(<2 x i32> %a) { |
| ; CHECK-LABEL: test_extract_vector_32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| %extracted = extractelement <2 x i32> %a, i32 0 |
| ret i32 %extracted |
| } |
| |
| define i32 @test_extract_vector_32_elem1(<2 x i32> %a) { |
| ; RV32-LABEL: test_extract_vector_32_elem1: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mv a0, a1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_extract_vector_32_elem1: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a0, a0, 32 |
| ; RV64-NEXT: ret |
| %extracted = extractelement <2 x i32> %a, i32 1 |
| ret i32 %extracted |
| } |
| |
| define <4 x i16> @test_insert_vector_16(<4 x i16> %a, i16 %val) { |
| ; RV32-LABEL: test_insert_vector_16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a0, a0, 16 |
| ; RV32-NEXT: pack a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a2, 16 |
| ; RV64-NEXT: addi a2, a2, -1 |
| ; RV64-NEXT: mvm a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = insertelement <4 x i16> %a, i16 %val, i32 0 |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_insert_vector_16_elem2(<4 x i16> %a, i16 %val) { |
| ; RV32-LABEL: test_insert_vector_16_elem2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a1, a1, 16 |
| ; RV32-NEXT: pack a1, a2, a1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_16_elem2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a2, 65535 |
| ; RV64-NEXT: slli a1, a1, 32 |
| ; RV64-NEXT: slli a2, a2, 20 |
| ; RV64-NEXT: mvm a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = insertelement <4 x i16> %a, i16 %val, i32 2 |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_insert_vector_8(<8 x i8> %a, i8 %val) { |
| ; RV32-LABEL: test_insert_vector_8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: li a3, 255 |
| ; RV32-NEXT: mvm a0, a2, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a2, 255 |
| ; RV64-NEXT: mvm a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = insertelement <8 x i8> %a, i8 %val, i32 0 |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_insert_vector_8_elem3(<8 x i8> %a, i8 %val) { |
| ; RV32-LABEL: test_insert_vector_8_elem3: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: slli a2, a2, 24 |
| ; RV32-NEXT: lui a3, 1044480 |
| ; RV32-NEXT: mvm a0, a2, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_8_elem3: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a2, 255 |
| ; RV64-NEXT: slli a1, a1, 24 |
| ; RV64-NEXT: slli a2, a2, 24 |
| ; RV64-NEXT: mvm a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = insertelement <8 x i8> %a, i8 %val, i32 3 |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_insert_vector_32(<2 x i32> %a, i32 %val) { |
| ; RV32-LABEL: test_insert_vector_32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: addi sp, sp, -16 |
| ; RV32-NEXT: .cfi_def_cfa_offset 16 |
| ; RV32-NEXT: mv a0, a2 |
| ; RV32-NEXT: addi sp, sp, 16 |
| ; RV32-NEXT: .cfi_def_cfa_offset 0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a0, a0, 32 |
| ; RV64-NEXT: pack a0, a1, a0 |
| ; RV64-NEXT: ret |
| %res = insertelement <2 x i32> %a, i32 %val, i32 0 |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_insert_vector_32_elem1(<2 x i32> %a, i32 %val) { |
| ; RV32-LABEL: test_insert_vector_32_elem1: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: addi sp, sp, -16 |
| ; RV32-NEXT: .cfi_def_cfa_offset 16 |
| ; RV32-NEXT: mv a1, a2 |
| ; RV32-NEXT: addi sp, sp, 16 |
| ; RV32-NEXT: .cfi_def_cfa_offset 0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_insert_vector_32_elem1: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = insertelement <2 x i32> %a, i32 %val, i32 1 |
| ret <2 x i32> %res |
| } |
| |
| ; Test basic add/sub operations for v2i32 (RV64 only) |
| define <2 x i32> @test_padd_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_padd_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = add <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psub_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psub_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psub.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psub_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psub.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sub <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test saturating add operations for v2i32 (RV64 only) |
| define <2 x i32> @test_psadd_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psadd_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psadd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psadd_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psadd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psaddu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psaddu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psaddu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psaddu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psaddu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Test saturating sub operations for v2i32 (RV64 only) |
| define <2 x i32> @test_pssub_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssub_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssub.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssub_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssub.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pssubu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssubu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssubu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssubu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssubu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Test shift-add operations for v2i32 |
| define <2 x i32> @test_psh1add_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psh1add_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psh1add.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psh1add_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psh1add.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = shl <2 x i32> %a, splat (i32 1) |
| %res = add <2 x i32> %shl, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pssh1sadd_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssh1sadd_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssh1sadd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssh1sadd_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssh1sadd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> splat (i32 1)) |
| %res = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %shl, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pssh1sadd_w_addself(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssh1sadd_w_addself: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssh1sadd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssh1sadd_w_addself: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssh1sadd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %shl = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %a, <2 x i32> %a) |
| %res = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %shl, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Test averaging floor signed operations for v2i32 (RV64 only) |
| ; avgfloors pattern: (a + b) arithmetic shift right 1 |
| define <2 x i32> @test_paadd_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_paadd_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %ext.a = sext <2 x i32> %a to <2 x i64> |
| %ext.b = sext <2 x i32> %b to <2 x i64> |
| %add = add nsw <2 x i64> %ext.a, %ext.b |
| %shift = ashr <2 x i64> %add, <i64 1, i64 1> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test averaging floor unsigned operations for v2i32 (RV64 only) |
| ; avgflooru pattern: (a & b) + ((a ^ b) >> 1) |
| define <2 x i32> @test_paaddu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_paaddu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %and = and <2 x i32> %a, %b |
| %xor = xor <2 x i32> %a, %b |
| %shift = lshr <2 x i32> %xor, <i32 1, i32 1> |
| %res = add <2 x i32> %and, %shift |
| ret <2 x i32> %res |
| } |
| |
| ; Test averaging floor subtraction signed for v2i32 (RV64 only) |
| ; pasub pattern: (a - b) arithmetic shift right 1 |
| define <2 x i32> @test_pasub_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pasub_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <2 x i32> %a to <2 x i64> |
| %b_ext = sext <2 x i32> %b to <2 x i64> |
| %sub = sub <2 x i64> %a_ext, %b_ext |
| %res = ashr <2 x i64> %sub, <i64 1, i64 1> |
| %res_trunc = trunc <2 x i64> %res to <2 x i32> |
| ret <2 x i32> %res_trunc |
| } |
| |
| ; Test averaging floor subtraction unsigned for v2i32 (RV64 only) |
| ; pasubu pattern: (a - b) logical shift right 1 |
| define <2 x i32> @test_pasubu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pasubu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <2 x i32> %a to <2 x i64> |
| %b_ext = zext <2 x i32> %b to <2 x i64> |
| %sub = sub <2 x i64> %a_ext, %b_ext |
| %res = lshr <2 x i64> %sub, <i64 1, i64 1> |
| %res_trunc = trunc <2 x i64> %res to <2 x i32> |
| ret <2 x i32> %res_trunc |
| } |
| |
| ; Test for splat |
| define <2 x i32> @test_non_const_splat_i32(i32 %elt) { |
| ; RV32-LABEL: test_non_const_splat_i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mv a1, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_non_const_splat_i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmv.ws a0, a0 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %elt, i32 0 |
| %splat = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| ret <2 x i32> %splat |
| } |
| |
| ; Test add(vec, splat(scalar)) pattern |
| define <8 x i8> @test_padd_bs_splat_lhs(<8 x i8> %a, i8 %b) { |
| ; RV32-LABEL: test_padd_bs_splat_lhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_bs_splat_lhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <8 x i8> poison, i8 %b, i32 0 |
| %splat = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = add <8 x i8> %splat, %a |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_padd_bs_splat_rhs(<8 x i8> %a, i8 %b) { |
| ; RV32-LABEL: test_padd_bs_splat_rhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_bs_splat_rhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <8 x i8> poison, i8 %b, i32 0 |
| %splat = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = add <8 x i8> %a, %splat |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_padd_hs_splat_lhs(<4 x i16> %a, i16 %b) { |
| ; RV32-LABEL: test_padd_hs_splat_lhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_hs_splat_lhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %b, i32 0 |
| %splat = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = add <4 x i16> %splat, %a |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_padd_hs_splat_rhs(<4 x i16> %a, i16 %b) { |
| ; RV32-LABEL: test_padd_hs_splat_rhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_hs_splat_rhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %b, i32 0 |
| %splat = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = add <4 x i16> %a, %splat |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_padd_ws_splat_lhs(<2 x i32> %a, i32 %b) { |
| ; RV32-LABEL: test_padd_ws_splat_lhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_ws_splat_lhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %b, i32 0 |
| %splat = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = add <2 x i32> %splat, %a |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_padd_ws_splat_rhs(<2 x i32> %a, i32 %b) { |
| ; RV32-LABEL: test_padd_ws_splat_rhs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: padd.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_padd_ws_splat_rhs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: padd.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %b, i32 0 |
| %splat = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = add <2 x i32> %a, %splat |
| ret <2 x i32> %res |
| } |
| |
| define <8 x i8> @test_build_vector_i8(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g, i8 %h) { |
| ; RV32-LABEL: test_build_vector_i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppaire.b a6, a6, a7 |
| ; RV32-NEXT: ppaire.b a4, a4, a5 |
| ; RV32-NEXT: ppaire.b a2, a2, a3 |
| ; RV32-NEXT: ppaire.b a0, a0, a1 |
| ; RV32-NEXT: pack a1, a4, a6 |
| ; RV32-NEXT: pack a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_build_vector_i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppaire.b a6, a6, a7 |
| ; RV64-NEXT: ppaire.b a4, a4, a5 |
| ; RV64-NEXT: ppaire.b a2, a2, a3 |
| ; RV64-NEXT: ppaire.b a0, a0, a1 |
| ; RV64-NEXT: ppaire.h a1, a4, a6 |
| ; RV64-NEXT: ppaire.h a0, a0, a2 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %v0 = insertelement <8 x i8> poison, i8 %a, i32 0 |
| %v1 = insertelement <8 x i8> %v0, i8 %b, i32 1 |
| %v2 = insertelement <8 x i8> %v1, i8 %c, i32 2 |
| %v3 = insertelement <8 x i8> %v2, i8 %d, i32 3 |
| %v4 = insertelement <8 x i8> %v3, i8 %e, i32 4 |
| %v5 = insertelement <8 x i8> %v4, i8 %f, i32 5 |
| %v6 = insertelement <8 x i8> %v5, i8 %g, i32 6 |
| %v7 = insertelement <8 x i8> %v6, i8 %h, i32 7 |
| ret <8 x i8> %v7 |
| } |
| |
| define <4 x i16> @test_build_vector_i16(i16 %a, i16 %b, i16 %c, i16 %d) { |
| ; RV32-LABEL: test_build_vector_i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pack a2, a2, a3 |
| ; RV32-NEXT: pack a0, a0, a1 |
| ; RV32-NEXT: mv a1, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_build_vector_i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppaire.h a2, a2, a3 |
| ; RV64-NEXT: ppaire.h a0, a0, a1 |
| ; RV64-NEXT: pack a0, a0, a2 |
| ; RV64-NEXT: ret |
| %v0 = insertelement <4 x i16> poison, i16 %a, i32 0 |
| %v1 = insertelement <4 x i16> %v0, i16 %b, i32 1 |
| %v2 = insertelement <4 x i16> %v1, i16 %c, i32 2 |
| %v3 = insertelement <4 x i16> %v2, i16 %d, i32 3 |
| ret <4 x i16> %v3 |
| } |
| |
| define <2 x i32> @test_build_vector_i32(i32 %a, i32 %b) { |
| ; RV32-LABEL: test_build_vector_i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_build_vector_i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %v0 = insertelement <2 x i32> poison, i32 %a, i32 0 |
| %v1 = insertelement <2 x i32> %v0, i32 %b, i32 1 |
| ret <2 x i32> %v1 |
| } |
| |
| ; Test logical shift left immediate for v4i16 |
| define <4 x i16> @test_pslli_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_pslli_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pslli.dh a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pslli_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pslli.h a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = shl <4 x i16> %a, splat(i16 2) |
| ret <4 x i16> %res |
| } |
| |
| ; Test logical shift left immediate for v8i8 |
| define <8 x i8> @test_pslli_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_pslli_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pslli.db a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pslli_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pslli.b a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = shl <8 x i8> %a, splat(i8 2) |
| ret <8 x i8> %res |
| } |
| |
| ; Test logical shift left immediate for v2i32 |
| define <2 x i32> @test_pslli_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_pslli_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pslli.dw a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pslli_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pslli.w a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = shl <2 x i32> %a, splat(i32 2) |
| ret <2 x i32> %res |
| } |
| |
| ; Test logical shift right immediate |
| define <2 x i32> @test_psrli_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_psrli_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrli.dw a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrli_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrli.w a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = lshr <2 x i32> %a, splat(i32 2) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psrli_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_psrli_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrli.dh a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrli_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrli.h a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = lshr <4 x i16> %a, splat(i16 2) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psrli_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_psrli_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrli.db a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrli_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrli.b a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = lshr <8 x i8> %a, splat(i8 2) |
| ret <8 x i8> %res |
| } |
| |
| ; Test arithmetic shift right immediate |
| define <2 x i32> @test_psrai_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_psrai_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrai.dw a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrai_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrai.w a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = ashr <2 x i32> %a, splat(i32 2) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psrai_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_psrai_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrai.dh a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrai_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrai.h a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = ashr <4 x i16> %a, splat(i16 2) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psrai_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_psrai_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrai.db a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrai_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrai.b a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = ashr <8 x i8> %a, splat(i8 2) |
| ret <8 x i8> %res |
| } |
| |
| ; Test saturating shift left arithmetic with splat immediate shift amount for v2i32 |
| define <2 x i32> @test_psslai_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_psslai_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psslai.dw a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psslai_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psslai.w a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> splat(i32 2)) |
| ret <2 x i32> %res |
| } |
| |
| ; Test saturating shift left arithmetic with splat immediate shift amount for v4i16 |
| define <4 x i16> @test_psslai_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_psslai_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psslai.dh a0, a0, 2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psslai_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psslai.h a0, a0, 2 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> splat(i16 2)) |
| ret <4 x i16> %res |
| } |
| |
| ; Test saturating shift left arithmetic with splat immediate shift amount for v8i8 |
| define <8 x i8> @test_psslai_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_psslai_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.b a2, -128 |
| ; RV32-NEXT: pslli.db a4, a0, 2 |
| ; RV32-NEXT: psrai.db a6, a4, 2 |
| ; RV32-NEXT: pmsltz.db t1, a0 |
| ; RV32-NEXT: pli.b a3, 127 |
| ; RV32-NEXT: pmseq.db a0, a0, a6 |
| ; RV32-NEXT: merge t2, a3, a2 |
| ; RV32-NEXT: merge a1, t2, a5 |
| ; RV32-NEXT: merge t1, a3, a2 |
| ; RV32-NEXT: merge a0, t1, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psslai_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.b a1, -128 |
| ; RV64-NEXT: pmsltz.b a2, a0 |
| ; RV64-NEXT: pslli.b a3, a0, 2 |
| ; RV64-NEXT: pli.b a4, 127 |
| ; RV64-NEXT: psrai.b a5, a3, 2 |
| ; RV64-NEXT: merge a2, a4, a1 |
| ; RV64-NEXT: pmseq.b a0, a0, a5 |
| ; RV64-NEXT: merge a0, a2, a3 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.sshl.sat.v8i8(<8 x i8> %a, <8 x i8> splat(i8 2)) |
| ret <8 x i8> %res |
| } |
| |
| ; Test saturating shift left arithmetic with splat shift amount for v4i16 |
| define <4 x i16> @test_pssla_hs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_pssla_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssha.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssla_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssha.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = call <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| ; Test saturating shift left arithmetic with splat shift amount for v2i32 |
| define <2 x i32> @test_pssla_ws(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pssla_ws: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssha.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssla_ws: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssha.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Test saturating shift left arithmetic with non-splat shift amount for v4i16 |
| define <4 x i16> @test_pssla_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssla_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a4, a3, 16 |
| ; RV32-NEXT: sll a5, a1, a3 |
| ; RV32-NEXT: srli a6, a1, 16 |
| ; RV32-NEXT: sext.h a7, a5 |
| ; RV32-NEXT: sll a6, a6, a4 |
| ; RV32-NEXT: sra a3, a7, a3 |
| ; RV32-NEXT: sext.h a7, a6 |
| ; RV32-NEXT: sra a4, a7, a4 |
| ; RV32-NEXT: sll a7, a0, a2 |
| ; RV32-NEXT: srli t0, a2, 16 |
| ; RV32-NEXT: srli t1, a0, 16 |
| ; RV32-NEXT: sext.h t2, a7 |
| ; RV32-NEXT: sll t1, t1, t0 |
| ; RV32-NEXT: sra a2, t2, a2 |
| ; RV32-NEXT: sext.h t2, t1 |
| ; RV32-NEXT: pack a3, a3, a4 |
| ; RV32-NEXT: sra a4, t2, t0 |
| ; RV32-NEXT: pack a2, a2, a4 |
| ; RV32-NEXT: pmseq.dh a2, a0, a2 |
| ; RV32-NEXT: lui a4, 8 |
| ; RV32-NEXT: pmsltz.dh a0, a0 |
| ; RV32-NEXT: addi a4, a4, -1 |
| ; RV32-NEXT: pmv.hs a4, a4 |
| ; RV32-NEXT: plui.h t0, -512 |
| ; RV32-NEXT: pack a5, a5, a6 |
| ; RV32-NEXT: merge a1, a4, t0 |
| ; RV32-NEXT: merge a3, a1, a5 |
| ; RV32-NEXT: pack a1, a7, t1 |
| ; RV32-NEXT: merge a0, a4, t0 |
| ; RV32-NEXT: merge a2, a0, a1 |
| ; RV32-NEXT: mvd a0, 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 <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| ; Test saturating shift left arithmetic with non-splat shift amount for v2i32 |
| define <2 x i32> @test_pssla_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssla_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ssha a1, a1, a3 |
| ; RV32-NEXT: ssha a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssla_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: sllw a2, a0, a1 |
| ; RV64-NEXT: srli a3, a1, 32 |
| ; RV64-NEXT: srli a4, a0, 32 |
| ; RV64-NEXT: sllw a4, a4, a3 |
| ; RV64-NEXT: sraw a1, a2, a1 |
| ; RV64-NEXT: pack a2, a2, a4 |
| ; RV64-NEXT: sraw a3, a4, a3 |
| ; RV64-NEXT: pack a1, a1, a3 |
| ; RV64-NEXT: lui a3, 524288 |
| ; RV64-NEXT: pmsltz.w a4, a0 |
| ; RV64-NEXT: addiw a3, a3, -1 |
| ; RV64-NEXT: pmv.ws a3, a3 |
| ; RV64-NEXT: plui.w a5, -512 |
| ; RV64-NEXT: pmseq.w a0, a0, a1 |
| ; RV64-NEXT: merge a4, a3, a5 |
| ; RV64-NEXT: merge a0, a4, a2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Test logical shift left(scalar shamt) |
| define <4 x i16> @test_psll_hs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psll_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psll.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psll.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = shl <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <4 x i16> @test_psll_hs_mask(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psll_hs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 15 |
| ; RV32-NEXT: psll.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_hs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 15 |
| ; RV64-NEXT: psll.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i16 %shamt, 15 |
| %insert = insertelement <4 x i16> poison, i16 %masked, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = shl <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psll_bs(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psll_bs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psll.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_bs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psll.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <8 x i8> poison, i8 %shamt, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = shl <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <8 x i8> @test_psll_bs_mask(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psll_bs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 7 |
| ; RV32-NEXT: psll.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_bs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 7 |
| ; RV64-NEXT: psll.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i8 %shamt, 7 |
| %insert = insertelement <8 x i8> poison, i8 %masked, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = shl <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_psll_ws(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psll_ws: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psll.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_ws: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psll.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = shl <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psll_ws_mask(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psll_ws_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psll.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_ws_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psll.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i32 %shamt, 31 |
| %insert = insertelement <2 x i32> poison, i32 %masked, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = shl <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test logical shift left(vector shamt) |
| define <2 x i32> @test_psll_ws_vec_shamt(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psll_ws_vec_shamt: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: sll a1, a1, a3 |
| ; RV32-NEXT: sll a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psll_ws_vec_shamt: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a1, 32 |
| ; RV64-NEXT: srli a3, a0, 32 |
| ; RV64-NEXT: sllw a0, a0, a1 |
| ; RV64-NEXT: sllw a1, a3, a2 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = shl <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test logical shift right(scalar shamt) |
| define <4 x i16> @test_psrl_hs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psrl_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrl.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = lshr <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <4 x i16> @test_psrl_hs_mask(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psrl_hs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 15 |
| ; RV32-NEXT: psrl.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_hs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 15 |
| ; RV64-NEXT: psrl.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i16 %shamt, 15 |
| %insert = insertelement <4 x i16> poison, i16 %masked, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = lshr <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psrl_bs(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psrl_bs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrl.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_bs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <8 x i8> poison, i8 %shamt, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = lshr <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <8 x i8> @test_psrl_bs_mask(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psrl_bs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 7 |
| ; RV32-NEXT: psrl.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_bs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 7 |
| ; RV64-NEXT: psrl.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i8 %shamt, 7 |
| %insert = insertelement <8 x i8> poison, i8 %masked, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = lshr <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_psrl_ws(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psrl_ws: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrl.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_ws: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = lshr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psrl_ws_mask(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psrl_ws_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psrl.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_ws_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i32 %shamt, 31 |
| %insert = insertelement <2 x i32> poison, i32 %masked, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = lshr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test arithmetic shift right(scalar shamt) |
| define <4 x i16> @test_psra_hs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psra_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psra.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = ashr <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <4 x i16> @test_psra_hs_mask(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_psra_hs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 15 |
| ; RV32-NEXT: psra.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_hs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 15 |
| ; RV64-NEXT: psra.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i16 %shamt, 15 |
| %insert = insertelement <4 x i16> poison, i16 %masked, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %res = ashr <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psra_bs(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psra_bs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psra.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_bs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <8 x i8> poison, i8 %shamt, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = ashr <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <8 x i8> @test_psra_bs_mask(<8 x i8> %a, i8 %shamt) { |
| ; RV32-LABEL: test_psra_bs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 7 |
| ; RV32-NEXT: psra.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_bs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 7 |
| ; RV64-NEXT: psra.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i8 %shamt, 7 |
| %insert = insertelement <8 x i8> poison, i8 %masked, i32 0 |
| %b = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer |
| %res = ashr <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_psra_ws(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psra_ws: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psra.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_ws: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = ashr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psra_ws_mask(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psra_ws_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psra.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_ws_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %masked = and i32 %shamt, 31 |
| %insert = insertelement <2 x i32> poison, i32 %masked, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %res = ashr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test logical shift right(vector shamt) |
| define <2 x i32> @test_psrl_ws_vec_shamt(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psrl_ws_vec_shamt: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srl a1, a1, a3 |
| ; RV32-NEXT: srl a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrl_ws_vec_shamt: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a1, 32 |
| ; RV64-NEXT: srli a3, a0, 32 |
| ; RV64-NEXT: srlw a0, a0, a1 |
| ; RV64-NEXT: srlw a1, a3, a2 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = lshr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test arithmetic shift right(vector shamt) |
| define <2 x i32> @test_psra_ws_vec_shamt(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psra_ws_vec_shamt: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: sra a1, a1, a3 |
| ; RV32-NEXT: sra a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psra_ws_vec_shamt: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a1, 32 |
| ; RV64-NEXT: srli a3, a0, 32 |
| ; RV64-NEXT: sraw a0, a0, a1 |
| ; RV64-NEXT: sraw a1, a3, a2 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = ashr <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Packed saturating and rounding shifts |
| define <4 x i16> @test_pssha_s_i16x4(<4 x i16> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pssha_s_i16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssha.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssha_s_i16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssha.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pssha.v4i16.i32(<4 x i16> %a, i32 %shamt) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pssha_s_i32x2(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pssha_s_i32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssha.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssha_s_i32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssha.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pssha.v2i32.i32(<2 x i32> %a, i32 %shamt) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psshar_s_i16x4(<4 x i16> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshar_s_i16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshar.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshar_s_i16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshar.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psshar.v4i16.i32(<4 x i16> %a, i32 %shamt) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_psshar_s_i32x2(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshar_s_i32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshar.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshar_s_i32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshar.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psshar.v2i32.i32(<2 x i32> %a, i32 %shamt) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psshl_s_u16x4(<4 x i16> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshl_s_u16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshl.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshl_s_u16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshl.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psshl.v4i16.i32(<4 x i16> %a, i32 %shamt) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_psshl_s_u32x2(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshl_s_u32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshl.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshl_s_u32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshl.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psshl.v2i32.i32(<2 x i32> %a, i32 %shamt) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psshlr_s_u16x4(<4 x i16> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshlr_s_u16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshlr.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshlr_s_u16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshlr.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psshlr.v4i16.i32(<4 x i16> %a, i32 %shamt) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_psshlr_s_u32x2(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_psshlr_s_u32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psshlr.dws a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psshlr_s_u32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psshlr.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psshlr.v2i32.i32(<2 x i32> %a, i32 %shamt) |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high signed |
| define <8 x i8> @test_pmulh_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pmulh_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwmul.b a4, a1, a3 |
| ; RV32-NEXT: pwmul.b a2, a0, a2 |
| ; RV32-NEXT: pncvth.b a1, a4 |
| ; RV32-NEXT: pncvth.b a0, a2 |
| ; 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 <8 x i8> %a to <8 x i16> |
| %b_ext = sext <8 x i8> %b to <8 x i16> |
| %mul = mul <8 x i16> %a_ext, %b_ext |
| %shift = lshr <8 x i16> %mul, splat (i16 8) |
| %res = trunc <8 x i16> %shift to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_pmulh_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulh_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulh.h a1, a1, a3 |
| ; RV32-NEXT: pmulh.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulh_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulh.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <4 x i16> %a to <4 x i32> |
| %b_ext = sext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %shift = lshr <4 x i32> %mul, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulh_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulh_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulh a1, a1, a3 |
| ; RV32-NEXT: mulh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulh_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulh.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <2 x i32> %a to <2 x i64> |
| %b_ext = sext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %shift = lshr <2 x i64> %mul, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high unsigned |
| define <8 x i8> @test_pmulhu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pmulhu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwmulu.b a4, a1, a3 |
| ; RV32-NEXT: pwmulu.b a2, a0, a2 |
| ; RV32-NEXT: pncvth.b a1, a4 |
| ; RV32-NEXT: pncvth.b a0, a2 |
| ; 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 <8 x i8> %a to <8 x i16> |
| %b_ext = zext <8 x i8> %b to <8 x i16> |
| %mul = mul <8 x i16> %a_ext, %b_ext |
| %shift = lshr <8 x i16> %mul, splat (i16 8) |
| %res = trunc <8 x i16> %shift to <8 x i8> |
| ret <8 x i8> %res |
| } |
| define <4 x i16> @test_pmulhu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhu.h a1, a1, a3 |
| ; RV32-NEXT: pmulhu.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <4 x i16> %a to <4 x i32> |
| %b_ext = zext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %shift = lshr <4 x i32> %mul, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulhu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulhu a1, a1, a3 |
| ; RV32-NEXT: mulhu a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <2 x i32> %a to <2 x i64> |
| %b_ext = zext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %shift = lshr <2 x i64> %mul, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high signed-unsigned |
| define <8 x i8> @test_pmulhsu_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pmulhsu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvt.b a4, a0 |
| ; RV32-NEXT: pwcvtu.b a6, a2 |
| ; RV32-NEXT: pwcvt.b a0, a1 |
| ; RV32-NEXT: pwmul.h t1, a5, a7 |
| ; RV32-NEXT: pwcvtu.b a2, a3 |
| ; RV32-NEXT: pncvt.h a5, t1 |
| ; RV32-NEXT: pwmul.h a6, a4, a6 |
| ; RV32-NEXT: pwmul.h t1, a1, a3 |
| ; RV32-NEXT: pncvt.h a1, t1 |
| ; RV32-NEXT: pwmul.h a2, a0, a2 |
| ; RV32-NEXT: pncvt.h a4, a6 |
| ; RV32-NEXT: pncvt.h a0, a2 |
| ; RV32-NEXT: pncvth.b a1, a0 |
| ; RV32-NEXT: pncvth.b a0, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a0, 56 |
| ; RV64-NEXT: srli a3, a0, 48 |
| ; RV64-NEXT: srli a4, a0, 40 |
| ; RV64-NEXT: srli a5, a0, 32 |
| ; RV64-NEXT: ppaire.b a2, a3, a2 |
| ; RV64-NEXT: ppaire.b a3, a5, a4 |
| ; RV64-NEXT: ppaire.h a2, a3, a2 |
| ; RV64-NEXT: pwcvtu.wb a2, a2 |
| ; RV64-NEXT: srli a3, a1, 56 |
| ; RV64-NEXT: srli a4, a1, 48 |
| ; RV64-NEXT: psext.h.b a2, a2 |
| ; RV64-NEXT: ppaire.b a3, a4, a3 |
| ; RV64-NEXT: srli a4, a1, 40 |
| ; RV64-NEXT: srli a5, a1, 32 |
| ; RV64-NEXT: pwcvtu.wb a0, a0 |
| ; RV64-NEXT: ppaire.b a4, a5, a4 |
| ; RV64-NEXT: psext.h.b a0, a0 |
| ; RV64-NEXT: ppaire.h a3, a4, a3 |
| ; RV64-NEXT: pwcvtu.wb a3, a3 |
| ; RV64-NEXT: pwcvtu.wb a1, a1 |
| ; RV64-NEXT: pmul.w.h11 a4, a2, a3 |
| ; RV64-NEXT: pmul.w.h00 a2, a2, a3 |
| ; RV64-NEXT: pmul.w.h11 a3, a0, a1 |
| ; RV64-NEXT: pmul.w.h00 a0, a0, a1 |
| ; RV64-NEXT: ppaire.h a1, a2, a4 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: psrli.h a1, a1, 8 |
| ; RV64-NEXT: psrli.h a0, a0, 8 |
| ; RV64-NEXT: unzip8p a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <8 x i8> %a to <8 x i16> |
| %b_ext = zext <8 x i8> %b to <8 x i16> |
| %mul = mul <8 x i16> %a_ext, %b_ext |
| %shift = lshr <8 x i16> %mul, splat (i16 8) |
| %res = trunc <8 x i16> %shift to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmulhsu_b_commuted(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pmulhsu_b_commuted: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvtu.b a4, a0 |
| ; RV32-NEXT: pwcvt.b a6, a2 |
| ; RV32-NEXT: pwcvtu.b a0, a1 |
| ; RV32-NEXT: pwmul.h t1, a5, a7 |
| ; RV32-NEXT: pwcvt.b a2, a3 |
| ; RV32-NEXT: pncvt.h a5, t1 |
| ; RV32-NEXT: pwmul.h a6, a4, a6 |
| ; RV32-NEXT: pwmul.h t1, a1, a3 |
| ; RV32-NEXT: pncvt.h a1, t1 |
| ; RV32-NEXT: pwmul.h a2, a0, a2 |
| ; RV32-NEXT: pncvt.h a4, a6 |
| ; RV32-NEXT: pncvt.h a0, a2 |
| ; RV32-NEXT: pncvth.b a1, a0 |
| ; RV32-NEXT: pncvth.b a0, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_b_commuted: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a0, 56 |
| ; RV64-NEXT: srli a3, a0, 48 |
| ; RV64-NEXT: srli a4, a0, 40 |
| ; RV64-NEXT: srli a5, a0, 32 |
| ; RV64-NEXT: ppaire.b a2, a3, a2 |
| ; RV64-NEXT: ppaire.b a3, a5, a4 |
| ; RV64-NEXT: srli a4, a1, 56 |
| ; RV64-NEXT: srli a5, a1, 48 |
| ; RV64-NEXT: ppaire.h a2, a3, a2 |
| ; RV64-NEXT: ppaire.b a3, a5, a4 |
| ; RV64-NEXT: srli a4, a1, 40 |
| ; RV64-NEXT: srli a5, a1, 32 |
| ; RV64-NEXT: pwcvtu.wb a2, a2 |
| ; RV64-NEXT: ppaire.b a4, a5, a4 |
| ; RV64-NEXT: pwcvtu.wb a0, a0 |
| ; RV64-NEXT: ppaire.h a3, a4, a3 |
| ; RV64-NEXT: pwcvtu.wb a3, a3 |
| ; RV64-NEXT: pwcvtu.wb a1, a1 |
| ; RV64-NEXT: psext.h.b a3, a3 |
| ; RV64-NEXT: psext.h.b a1, a1 |
| ; RV64-NEXT: pmul.w.h11 a4, a2, a3 |
| ; RV64-NEXT: pmul.w.h00 a2, a2, a3 |
| ; RV64-NEXT: pmul.w.h11 a3, a0, a1 |
| ; RV64-NEXT: pmul.w.h00 a0, a0, a1 |
| ; RV64-NEXT: ppaire.h a1, a2, a4 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: psrli.h a1, a1, 8 |
| ; RV64-NEXT: psrli.h a0, a0, 8 |
| ; RV64-NEXT: unzip8p a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <8 x i8> %a to <8 x i16> |
| %b_ext = sext <8 x i8> %b to <8 x i16> |
| %mul = mul <8 x i16> %a_ext, %b_ext |
| %shift = lshr <8 x i16> %mul, splat (i16 8) |
| %res = trunc <8 x i16> %shift to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_pmulhsu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhsu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhsu.h a1, a1, a3 |
| ; RV32-NEXT: pmulhsu.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhsu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <4 x i16> %a to <4 x i32> |
| %b_ext = zext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %shift = lshr <4 x i32> %mul, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmulhsu_h_commuted(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhsu_h_commuted: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhsu.h a1, a3, a1 |
| ; RV32-NEXT: pmulhsu.h a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_h_commuted: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhsu.h a0, a1, a0 |
| ; RV64-NEXT: ret |
| %a_ext = zext <4 x i16> %a to <4 x i32> |
| %b_ext = sext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %shift = lshr <4 x i32> %mul, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulhsu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhsu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulhsu a1, a1, a3 |
| ; RV32-NEXT: mulhsu a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhsu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <2 x i32> %a to <2 x i64> |
| %b_ext = zext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %shift = lshr <2 x i64> %mul, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmulhsu_w_commuted(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhsu_w_commuted: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulhsu a1, a3, a1 |
| ; RV32-NEXT: mulhsu a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhsu_w_commuted: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhsu.w a0, a1, a0 |
| ; RV64-NEXT: ret |
| %a_ext = zext <2 x i32> %a to <2 x i64> |
| %b_ext = sext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %shift = lshr <2 x i64> %mul, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high rounding signed |
| define <4 x i16> @test_pmulhr_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhr_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhr.h a1, a1, a3 |
| ; RV32-NEXT: pmulhr.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhr_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhr.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <4 x i16> %a to <4 x i32> |
| %b_ext = sext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %add = add <4 x i32> %mul, <i32 32768, i32 32768, i32 32768, i32 32768> |
| %shift = lshr <4 x i32> %add, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulhr_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhr_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: wmul a4, a0, a2 |
| ; RV32-NEXT: wmul a0, a1, a3 |
| ; RV32-NEXT: lui a2, 524288 |
| ; RV32-NEXT: waddau a0, a2, zero |
| ; RV32-NEXT: waddau a4, a2, zero |
| ; RV32-NEXT: mv a0, a5 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhr_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhr.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <2 x i32> %a to <2 x i64> |
| %b_ext = sext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %add = add <2 x i64> %mul, <i64 2147483648, i64 2147483648> |
| %shift = lshr <2 x i64> %add, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high rounding unsigned |
| define <4 x i16> @test_pmulhru_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhru_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhru.h a1, a1, a3 |
| ; RV32-NEXT: pmulhru.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhru_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhru.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <4 x i16> %a to <4 x i32> |
| %b_ext = zext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %add = add <4 x i32> %mul, <i32 32768, i32 32768, i32 32768, i32 32768> |
| %shift = lshr <4 x i32> %add, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulhru_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhru_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: wmulu a4, a0, a2 |
| ; RV32-NEXT: wmulu a0, a1, a3 |
| ; RV32-NEXT: lui a2, 524288 |
| ; RV32-NEXT: waddau a0, a2, zero |
| ; RV32-NEXT: waddau a4, a2, zero |
| ; RV32-NEXT: mv a0, a5 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhru_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhru.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = zext <2 x i32> %a to <2 x i64> |
| %b_ext = zext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %add = add <2 x i64> %mul, <i64 2147483648, i64 2147483648> |
| %shift = lshr <2 x i64> %add, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply high rounding signed-unsigned |
| define <4 x i16> @test_pmulhrsu_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhrsu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhrsu.h a1, a1, a3 |
| ; RV32-NEXT: pmulhrsu.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhrsu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhrsu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <4 x i16> %a to <4 x i32> |
| %b_ext = zext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %add = add <4 x i32> %mul, <i32 32768, i32 32768, i32 32768, i32 32768> |
| %shift = lshr <4 x i32> %add, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmulhrsu_h_commuted(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulhrsu_h_commuted: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulhrsu.h a1, a3, a1 |
| ; RV32-NEXT: pmulhrsu.h a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhrsu_h_commuted: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhrsu.h a0, a1, a0 |
| ; RV64-NEXT: ret |
| %a_ext = zext <4 x i16> %a to <4 x i32> |
| %b_ext = sext <4 x i16> %b to <4 x i32> |
| %mul = mul <4 x i32> %a_ext, %b_ext |
| %add = add <4 x i32> %mul, <i32 32768, i32 32768, i32 32768, i32 32768> |
| %shift = lshr <4 x i32> %add, <i32 16, i32 16, i32 16, i32 16> |
| %res = trunc <4 x i32> %shift to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulhrsu_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhrsu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: wmulsu a4, a0, a2 |
| ; RV32-NEXT: wmulsu a0, a1, a3 |
| ; RV32-NEXT: lui a2, 524288 |
| ; RV32-NEXT: waddau a0, a2, zero |
| ; RV32-NEXT: waddau a4, a2, zero |
| ; RV32-NEXT: mv a0, a5 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhrsu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhrsu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %a_ext = sext <2 x i32> %a to <2 x i64> |
| %b_ext = zext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %add = add <2 x i64> %mul, <i64 2147483648, i64 2147483648> |
| %shift = lshr <2 x i64> %add, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmulhrsu_w_commuted(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulhrsu_w_commuted: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: wmulsu a4, a2, a0 |
| ; RV32-NEXT: wmulsu a0, a3, a1 |
| ; RV32-NEXT: lui a2, 524288 |
| ; RV32-NEXT: waddau a0, a2, zero |
| ; RV32-NEXT: waddau a4, a2, zero |
| ; RV32-NEXT: mv a0, a5 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulhrsu_w_commuted: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulhrsu.w a0, a1, a0 |
| ; RV64-NEXT: ret |
| %a_ext = zext <2 x i32> %a to <2 x i64> |
| %b_ext = sext <2 x i32> %b to <2 x i64> |
| %mul = mul <2 x i64> %a_ext, %b_ext |
| %add = add <2 x i64> %mul, <i64 2147483648, i64 2147483648> |
| %shift = lshr <2 x i64> %add, <i64 32, i64 32> |
| %res = trunc <2 x i64> %shift to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test packed multiply low for v4i16 |
| define <4 x i16> @test_pmul_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmul_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwmul.h a4, a1, a3 |
| ; RV32-NEXT: pwmul.h a2, a0, a2 |
| ; RV32-NEXT: pncvt.h a1, a4 |
| ; RV32-NEXT: pncvt.h a0, a2 |
| ; 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 <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| ; Test packed multiply low for v8i8 |
| define <8 x i8> @test_pmul_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pmul_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwmul.b a4, a1, a3 |
| ; RV32-NEXT: pwmul.b a2, a0, a2 |
| ; RV32-NEXT: pncvt.b a1, a4 |
| ; RV32-NEXT: pncvt.b a0, a2 |
| ; 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 <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| ; Test packed multiply low for v2i32 |
| define <2 x i32> @test_pmul_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmul_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mul a1, a1, a3 |
| ; RV32-NEXT: mul a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmul_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mul.w11 a2, a0, a1 |
| ; RV64-NEXT: mul.w00 a0, a0, a1 |
| ; RV64-NEXT: pack a0, a0, a2 |
| ; RV64-NEXT: ret |
| %res = mul <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Division and remainder tests |
| define <4 x i16> @test_psdiv_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psdiv_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srai a4, a3, 16 |
| ; RV32-NEXT: srai a5, a1, 16 |
| ; RV32-NEXT: div a4, a5, a4 |
| ; RV32-NEXT: sext.h a3, a3 |
| ; RV32-NEXT: sext.h a1, a1 |
| ; RV32-NEXT: div a1, a1, a3 |
| ; RV32-NEXT: srai a3, a2, 16 |
| ; RV32-NEXT: srai a5, a0, 16 |
| ; RV32-NEXT: div a3, a5, a3 |
| ; RV32-NEXT: sext.h a2, a2 |
| ; RV32-NEXT: sext.h a0, a0 |
| ; RV32-NEXT: div a0, a0, a2 |
| ; RV32-NEXT: pack a1, a1, a4 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srai a2, a1, 48 |
| ; RV64-NEXT: srai a3, a0, 48 |
| ; RV64-NEXT: divw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 16 |
| ; RV64-NEXT: slli a4, a0, 16 |
| ; RV64-NEXT: srai a3, a3, 48 |
| ; RV64-NEXT: srai a4, a4, 48 |
| ; RV64-NEXT: divw a3, a4, a3 |
| ; RV64-NEXT: sext.h a4, a1 |
| ; RV64-NEXT: sext.h a5, a0 |
| ; RV64-NEXT: divw a4, a5, a4 |
| ; 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 a1, a3, a2 |
| ; RV64-NEXT: ppaire.h a0, a4, a0 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psdiv_mulhs_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_psdiv_mulhs_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a2, 5 |
| ; RV32-NEXT: addi a2, a2, 1366 |
| ; RV32-NEXT: pmv.hs a2, a2 |
| ; RV32-NEXT: pmulh.h a1, a1, a2 |
| ; RV32-NEXT: pmulh.h a0, a0, a2 |
| ; RV32-NEXT: psrli.dh a2, a0, 15 |
| ; RV32-NEXT: padd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_mulhs_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a1, 5 |
| ; RV64-NEXT: addi a1, a1, 1366 |
| ; RV64-NEXT: pmv.hs a1, a1 |
| ; RV64-NEXT: pmulh.h a0, a0, a1 |
| ; RV64-NEXT: psrli.h a1, a0, 15 |
| ; RV64-NEXT: padd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <4 x i16> %a, splat (i16 3) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psdiv_mulhsu_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_psdiv_mulhsu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a2, 1048569 |
| ; RV32-NEXT: addi a2, a2, -1911 |
| ; RV32-NEXT: pmv.hs a2, a2 |
| ; RV32-NEXT: pmulhsu.h a1, a1, a2 |
| ; RV32-NEXT: pmulhsu.h a0, a0, a2 |
| ; RV32-NEXT: psrai.dh a0, a0, 3 |
| ; RV32-NEXT: psrli.dh a2, a0, 15 |
| ; RV32-NEXT: padd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_mulhsu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a1, 1048569 |
| ; RV64-NEXT: addi a1, a1, -1911 |
| ; RV64-NEXT: pmv.hs a1, a1 |
| ; RV64-NEXT: pmulhsu.h a0, a0, a1 |
| ; RV64-NEXT: psrai.h a0, a0, 3 |
| ; RV64-NEXT: psrli.h a1, a0, 15 |
| ; RV64-NEXT: padd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <4 x i16> %a, splat (i16 15) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psdiv_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_psdiv_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srai a4, a3, 24 |
| ; RV32-NEXT: srai a5, a1, 24 |
| ; RV32-NEXT: div a4, a5, a4 |
| ; RV32-NEXT: slli a5, a3, 8 |
| ; RV32-NEXT: slli a6, a1, 8 |
| ; RV32-NEXT: srai a5, a5, 24 |
| ; RV32-NEXT: srai a6, a6, 24 |
| ; RV32-NEXT: div a5, a6, a5 |
| ; RV32-NEXT: sext.b a6, a3 |
| ; RV32-NEXT: sext.b a7, a1 |
| ; RV32-NEXT: div a6, a7, a6 |
| ; RV32-NEXT: slli a3, a3, 16 |
| ; RV32-NEXT: slli a1, a1, 16 |
| ; RV32-NEXT: srai a3, a3, 24 |
| ; RV32-NEXT: srai a1, a1, 24 |
| ; RV32-NEXT: div a1, a1, a3 |
| ; RV32-NEXT: srai a3, a2, 24 |
| ; RV32-NEXT: srai a7, a0, 24 |
| ; RV32-NEXT: div a3, a7, a3 |
| ; RV32-NEXT: slli a7, a2, 8 |
| ; RV32-NEXT: slli t0, a0, 8 |
| ; RV32-NEXT: srai a7, a7, 24 |
| ; RV32-NEXT: srai t0, t0, 24 |
| ; RV32-NEXT: div a7, t0, a7 |
| ; RV32-NEXT: sext.b t0, a2 |
| ; RV32-NEXT: sext.b t1, a0 |
| ; RV32-NEXT: div t0, t1, t0 |
| ; RV32-NEXT: slli a2, a2, 16 |
| ; RV32-NEXT: slli a0, a0, 16 |
| ; RV32-NEXT: srai a2, a2, 24 |
| ; RV32-NEXT: srai a0, a0, 24 |
| ; RV32-NEXT: div a0, a0, a2 |
| ; RV32-NEXT: ppaire.b a2, a5, a4 |
| ; RV32-NEXT: ppaire.b a1, a6, a1 |
| ; RV32-NEXT: ppaire.b a3, a7, a3 |
| ; RV32-NEXT: ppaire.b a0, t0, a0 |
| ; RV32-NEXT: pack a1, a1, a2 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srai a2, a1, 56 |
| ; RV64-NEXT: srai a3, a0, 56 |
| ; RV64-NEXT: divw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 8 |
| ; RV64-NEXT: slli a4, a0, 8 |
| ; RV64-NEXT: srai a3, a3, 56 |
| ; RV64-NEXT: srai a4, a4, 56 |
| ; RV64-NEXT: divw a3, a4, a3 |
| ; RV64-NEXT: slli a4, a1, 16 |
| ; RV64-NEXT: slli a5, a0, 16 |
| ; RV64-NEXT: srai a4, a4, 56 |
| ; RV64-NEXT: srai a5, a5, 56 |
| ; RV64-NEXT: divw a4, a5, a4 |
| ; RV64-NEXT: slli a5, a1, 24 |
| ; RV64-NEXT: slli a6, a0, 24 |
| ; RV64-NEXT: srai a5, a5, 56 |
| ; RV64-NEXT: srai a6, a6, 56 |
| ; RV64-NEXT: divw a5, a6, a5 |
| ; RV64-NEXT: slli a6, a1, 32 |
| ; RV64-NEXT: slli a7, a0, 32 |
| ; RV64-NEXT: srai a6, a6, 56 |
| ; RV64-NEXT: srai a7, a7, 56 |
| ; RV64-NEXT: divw a6, a7, a6 |
| ; RV64-NEXT: slli a7, a1, 40 |
| ; RV64-NEXT: slli t0, a0, 40 |
| ; RV64-NEXT: srai a7, a7, 56 |
| ; RV64-NEXT: srai t0, t0, 56 |
| ; RV64-NEXT: divw a7, t0, a7 |
| ; RV64-NEXT: sext.b t0, a1 |
| ; RV64-NEXT: sext.b t1, a0 |
| ; RV64-NEXT: divw t0, t1, t0 |
| ; 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 a2, a5, a4 |
| ; RV64-NEXT: ppaire.b a3, a7, a6 |
| ; RV64-NEXT: ppaire.b a0, t0, a0 |
| ; RV64-NEXT: ppaire.h a1, a2, a1 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_psdiv_mulhs_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_psdiv_mulhs_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.b a2, 86 |
| ; RV32-NEXT: pwmul.b a4, a1, a2 |
| ; RV32-NEXT: pncvth.b a1, a4 |
| ; RV32-NEXT: pwmul.b a2, a0, a2 |
| ; RV32-NEXT: pncvth.b a0, a2 |
| ; RV32-NEXT: psrli.db a2, a0, 7 |
| ; RV32-NEXT: padd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_mulhs_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pli.b a1, 86 |
| ; 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: psrli.b a1, a0, 7 |
| ; RV64-NEXT: padd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <8 x i8> %a, splat (i8 3) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_psdiv_mulhsu_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_psdiv_mulhsu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.b a2, -119 |
| ; RV32-NEXT: pwmulsu.b a4, a1, a2 |
| ; RV32-NEXT: pnsrai.b a1, a4, 11 |
| ; RV32-NEXT: pwmulsu.b a2, a0, a2 |
| ; RV32-NEXT: pnsrai.b a0, a2, 11 |
| ; RV32-NEXT: psrli.db a2, a0, 7 |
| ; RV32-NEXT: padd.db a0, a0, a2 |
| ; 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 <8 x i8> %a, splat (i8 15) |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_psdiv_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psdiv_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: div a1, a1, a3 |
| ; RV32-NEXT: div a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: divw a2, a0, a1 |
| ; RV64-NEXT: srli a1, a1, 32 |
| ; RV64-NEXT: srli a0, a0, 32 |
| ; RV64-NEXT: divw a0, a0, a1 |
| ; RV64-NEXT: pack a0, a2, a0 |
| ; RV64-NEXT: ret |
| %res = sdiv <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psdiv_mulhsu_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_psdiv_mulhsu_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a2, 599186 |
| ; RV32-NEXT: addi a2, a2, 1171 |
| ; RV32-NEXT: mulhsu a1, a1, a2 |
| ; RV32-NEXT: mulhsu a0, a0, a2 |
| ; RV32-NEXT: srli a2, a1, 31 |
| ; RV32-NEXT: srai a1, a1, 2 |
| ; RV32-NEXT: srli a3, a0, 31 |
| ; RV32-NEXT: srai a0, a0, 2 |
| ; RV32-NEXT: add a1, a1, a2 |
| ; RV32-NEXT: add a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psdiv_mulhsu_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a1, 599186 |
| ; RV64-NEXT: addi a1, a1, 1171 |
| ; RV64-NEXT: pmv.ws a1, a1 |
| ; RV64-NEXT: pmulhsu.w a0, a0, a1 |
| ; RV64-NEXT: psrai.w a0, a0, 2 |
| ; RV64-NEXT: psrli.w a1, a0, 31 |
| ; RV64-NEXT: padd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = sdiv <2 x i32> %a, splat (i32 7) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_pudiv_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pudiv_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a4, a3, 16 |
| ; RV32-NEXT: srli a5, a1, 16 |
| ; RV32-NEXT: divu a4, a5, a4 |
| ; RV32-NEXT: zext.h a3, a3 |
| ; RV32-NEXT: zext.h a1, a1 |
| ; RV32-NEXT: divu a1, a1, a3 |
| ; RV32-NEXT: srli a3, a2, 16 |
| ; RV32-NEXT: srli a5, a0, 16 |
| ; RV32-NEXT: divu a3, a5, a3 |
| ; RV32-NEXT: zext.h a2, a2 |
| ; RV32-NEXT: zext.h a0, a0 |
| ; RV32-NEXT: divu a0, a0, a2 |
| ; RV32-NEXT: pack a1, a1, a4 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; 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 a3, a1 |
| ; RV64-NEXT: zext.h a4, a0 |
| ; RV64-NEXT: divuw a3, a4, a3 |
| ; RV64-NEXT: srli a4, a1, 48 |
| ; RV64-NEXT: srli a5, a0, 48 |
| ; RV64-NEXT: divuw a4, a5, a4 |
| ; RV64-NEXT: slli a1, a1, 16 |
| ; RV64-NEXT: slli a0, a0, 16 |
| ; RV64-NEXT: srli a1, a1, 48 |
| ; RV64-NEXT: srli a0, a0, 48 |
| ; RV64-NEXT: divuw a0, a0, a1 |
| ; RV64-NEXT: ppaire.h a1, a3, a2 |
| ; RV64-NEXT: ppaire.h a0, a0, a4 |
| ; RV64-NEXT: pack a0, a1, a0 |
| ; RV64-NEXT: ret |
| %res = udiv <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pudiv_mulhu_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_pudiv_mulhu_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: lui a2, 1048571 |
| ; RV32-NEXT: addi a2, a2, -1365 |
| ; RV32-NEXT: pmv.hs a2, a2 |
| ; RV32-NEXT: pmulhu.h a1, a1, a2 |
| ; RV32-NEXT: pmulhu.h a0, a0, a2 |
| ; RV32-NEXT: psrli.dh a0, a0, 1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pudiv_mulhu_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: lui a1, 1048571 |
| ; RV64-NEXT: addi a1, a1, -1365 |
| ; RV64-NEXT: pmv.hs a1, a1 |
| ; RV64-NEXT: pmulhu.h a0, a0, a1 |
| ; RV64-NEXT: psrli.h a0, a0, 1 |
| ; RV64-NEXT: ret |
| %res = udiv <4 x i16> %a, splat (i16 3) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_pudiv_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pudiv_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a4, a3, 24 |
| ; RV32-NEXT: srli a5, a1, 24 |
| ; RV32-NEXT: divu a4, a5, a4 |
| ; RV32-NEXT: slli a5, a3, 8 |
| ; RV32-NEXT: slli a6, a1, 8 |
| ; RV32-NEXT: srli a5, a5, 24 |
| ; RV32-NEXT: srli a6, a6, 24 |
| ; RV32-NEXT: divu a5, a6, a5 |
| ; RV32-NEXT: zext.b a6, a3 |
| ; RV32-NEXT: zext.b a7, a1 |
| ; RV32-NEXT: divu a6, a7, a6 |
| ; RV32-NEXT: slli a3, a3, 16 |
| ; RV32-NEXT: slli a1, a1, 16 |
| ; RV32-NEXT: srli a3, a3, 24 |
| ; RV32-NEXT: srli a1, a1, 24 |
| ; RV32-NEXT: divu a1, a1, a3 |
| ; RV32-NEXT: srli a3, a2, 24 |
| ; RV32-NEXT: srli a7, a0, 24 |
| ; RV32-NEXT: divu a3, a7, a3 |
| ; RV32-NEXT: slli a7, a2, 8 |
| ; RV32-NEXT: slli t0, a0, 8 |
| ; RV32-NEXT: srli a7, a7, 24 |
| ; RV32-NEXT: srli t0, t0, 24 |
| ; RV32-NEXT: divu a7, t0, a7 |
| ; RV32-NEXT: zext.b t0, a2 |
| ; RV32-NEXT: zext.b t1, a0 |
| ; RV32-NEXT: divu t0, t1, t0 |
| ; RV32-NEXT: slli a2, a2, 16 |
| ; RV32-NEXT: slli a0, a0, 16 |
| ; RV32-NEXT: srli a2, a2, 24 |
| ; RV32-NEXT: srli a0, a0, 24 |
| ; RV32-NEXT: divu a0, a0, a2 |
| ; RV32-NEXT: ppaire.b a2, a5, a4 |
| ; RV32-NEXT: ppaire.b a1, a6, a1 |
| ; RV32-NEXT: ppaire.b a3, a7, a3 |
| ; RV32-NEXT: ppaire.b a0, t0, a0 |
| ; RV32-NEXT: pack a1, a1, a2 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pudiv_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a1, 56 |
| ; RV64-NEXT: srli a3, a0, 56 |
| ; RV64-NEXT: divuw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 8 |
| ; RV64-NEXT: slli a4, a0, 8 |
| ; RV64-NEXT: srli a3, a3, 56 |
| ; RV64-NEXT: srli a4, a4, 56 |
| ; RV64-NEXT: divuw a3, a4, a3 |
| ; RV64-NEXT: slli a4, a1, 16 |
| ; RV64-NEXT: slli a5, a0, 16 |
| ; RV64-NEXT: srli a4, a4, 56 |
| ; RV64-NEXT: srli a5, a5, 56 |
| ; RV64-NEXT: divuw a4, a5, a4 |
| ; RV64-NEXT: slli a5, a1, 24 |
| ; RV64-NEXT: slli a6, a0, 24 |
| ; RV64-NEXT: srli a5, a5, 56 |
| ; RV64-NEXT: srli a6, a6, 56 |
| ; RV64-NEXT: divuw a5, a6, a5 |
| ; RV64-NEXT: srliw a6, a1, 24 |
| ; RV64-NEXT: srliw a7, a0, 24 |
| ; RV64-NEXT: divuw a6, a7, a6 |
| ; RV64-NEXT: slli a7, a1, 40 |
| ; RV64-NEXT: slli t0, a0, 40 |
| ; RV64-NEXT: srli a7, a7, 56 |
| ; RV64-NEXT: srli t0, t0, 56 |
| ; RV64-NEXT: divuw a7, t0, a7 |
| ; RV64-NEXT: zext.b t0, a1 |
| ; RV64-NEXT: zext.b t1, a0 |
| ; RV64-NEXT: divuw t0, t1, t0 |
| ; 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 a2, a5, a4 |
| ; RV64-NEXT: ppaire.b a3, a7, a6 |
| ; RV64-NEXT: ppaire.b a0, t0, a0 |
| ; RV64-NEXT: ppaire.h a1, a2, a1 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = udiv <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pudiv_mulhu_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_pudiv_mulhu_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pli.b a2, -85 |
| ; RV32-NEXT: pwmulu.b a4, a1, a2 |
| ; RV32-NEXT: pwmulu.b a2, a0, a2 |
| ; RV32-NEXT: pnsrli.b a1, a4, 9 |
| ; RV32-NEXT: pnsrli.b a0, a2, 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 <8 x i8> %a, splat (i8 3) |
| ret <8 x i8> %res |
| } |
| define <2 x i32> @test_pudiv_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pudiv_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: divu a1, a1, a3 |
| ; RV32-NEXT: divu a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pudiv_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: divuw a2, a0, a1 |
| ; RV64-NEXT: srli a1, a1, 32 |
| ; RV64-NEXT: srli a0, a0, 32 |
| ; RV64-NEXT: divuw a0, a0, a1 |
| ; RV64-NEXT: pack a0, a2, a0 |
| ; RV64-NEXT: ret |
| %res = udiv <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_psrem_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psrem_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srai a4, a3, 16 |
| ; RV32-NEXT: srai a5, a1, 16 |
| ; RV32-NEXT: rem a4, a5, a4 |
| ; RV32-NEXT: sext.h a3, a3 |
| ; RV32-NEXT: sext.h a1, a1 |
| ; RV32-NEXT: rem a1, a1, a3 |
| ; RV32-NEXT: srai a3, a2, 16 |
| ; RV32-NEXT: srai a5, a0, 16 |
| ; RV32-NEXT: rem a3, a5, a3 |
| ; RV32-NEXT: sext.h a2, a2 |
| ; RV32-NEXT: sext.h a0, a0 |
| ; RV32-NEXT: rem a0, a0, a2 |
| ; RV32-NEXT: pack a1, a1, a4 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrem_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srai a2, a1, 48 |
| ; RV64-NEXT: srai a3, a0, 48 |
| ; RV64-NEXT: remw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 16 |
| ; RV64-NEXT: slli a4, a0, 16 |
| ; RV64-NEXT: srai a3, a3, 48 |
| ; RV64-NEXT: srai a4, a4, 48 |
| ; RV64-NEXT: remw a3, a4, a3 |
| ; RV64-NEXT: sext.h a4, a1 |
| ; RV64-NEXT: sext.h a5, a0 |
| ; RV64-NEXT: remw a4, a5, a4 |
| ; 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 a1, a3, a2 |
| ; RV64-NEXT: ppaire.h a0, a4, a0 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = srem <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_psrem_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_psrem_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srai a4, a3, 24 |
| ; RV32-NEXT: srai a5, a1, 24 |
| ; RV32-NEXT: rem a4, a5, a4 |
| ; RV32-NEXT: slli a5, a3, 8 |
| ; RV32-NEXT: slli a6, a1, 8 |
| ; RV32-NEXT: srai a5, a5, 24 |
| ; RV32-NEXT: srai a6, a6, 24 |
| ; RV32-NEXT: rem a5, a6, a5 |
| ; RV32-NEXT: sext.b a6, a3 |
| ; RV32-NEXT: sext.b a7, a1 |
| ; RV32-NEXT: rem a6, a7, a6 |
| ; RV32-NEXT: slli a3, a3, 16 |
| ; RV32-NEXT: slli a1, a1, 16 |
| ; RV32-NEXT: srai a3, a3, 24 |
| ; RV32-NEXT: srai a1, a1, 24 |
| ; RV32-NEXT: rem a1, a1, a3 |
| ; RV32-NEXT: srai a3, a2, 24 |
| ; RV32-NEXT: srai a7, a0, 24 |
| ; RV32-NEXT: rem a3, a7, a3 |
| ; RV32-NEXT: slli a7, a2, 8 |
| ; RV32-NEXT: slli t0, a0, 8 |
| ; RV32-NEXT: srai a7, a7, 24 |
| ; RV32-NEXT: srai t0, t0, 24 |
| ; RV32-NEXT: rem a7, t0, a7 |
| ; RV32-NEXT: sext.b t0, a2 |
| ; RV32-NEXT: sext.b t1, a0 |
| ; RV32-NEXT: rem t0, t1, t0 |
| ; RV32-NEXT: slli a2, a2, 16 |
| ; RV32-NEXT: slli a0, a0, 16 |
| ; RV32-NEXT: srai a2, a2, 24 |
| ; RV32-NEXT: srai a0, a0, 24 |
| ; RV32-NEXT: rem a0, a0, a2 |
| ; RV32-NEXT: ppaire.b a2, a5, a4 |
| ; RV32-NEXT: ppaire.b a1, a6, a1 |
| ; RV32-NEXT: ppaire.b a3, a7, a3 |
| ; RV32-NEXT: ppaire.b a0, t0, a0 |
| ; RV32-NEXT: pack a1, a1, a2 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrem_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srai a2, a1, 56 |
| ; RV64-NEXT: srai a3, a0, 56 |
| ; RV64-NEXT: remw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 8 |
| ; RV64-NEXT: slli a4, a0, 8 |
| ; RV64-NEXT: srai a3, a3, 56 |
| ; RV64-NEXT: srai a4, a4, 56 |
| ; RV64-NEXT: remw a3, a4, a3 |
| ; RV64-NEXT: slli a4, a1, 16 |
| ; RV64-NEXT: slli a5, a0, 16 |
| ; RV64-NEXT: srai a4, a4, 56 |
| ; RV64-NEXT: srai a5, a5, 56 |
| ; RV64-NEXT: remw a4, a5, a4 |
| ; RV64-NEXT: slli a5, a1, 24 |
| ; RV64-NEXT: slli a6, a0, 24 |
| ; RV64-NEXT: srai a5, a5, 56 |
| ; RV64-NEXT: srai a6, a6, 56 |
| ; RV64-NEXT: remw a5, a6, a5 |
| ; RV64-NEXT: slli a6, a1, 32 |
| ; RV64-NEXT: slli a7, a0, 32 |
| ; RV64-NEXT: srai a6, a6, 56 |
| ; RV64-NEXT: srai a7, a7, 56 |
| ; RV64-NEXT: remw a6, a7, a6 |
| ; RV64-NEXT: slli a7, a1, 40 |
| ; RV64-NEXT: slli t0, a0, 40 |
| ; RV64-NEXT: srai a7, a7, 56 |
| ; RV64-NEXT: srai t0, t0, 56 |
| ; RV64-NEXT: remw a7, t0, a7 |
| ; RV64-NEXT: sext.b t0, a1 |
| ; RV64-NEXT: sext.b t1, a0 |
| ; RV64-NEXT: remw t0, t1, t0 |
| ; 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 a2, a5, a4 |
| ; RV64-NEXT: ppaire.b a3, a7, a6 |
| ; RV64-NEXT: ppaire.b a0, t0, a0 |
| ; RV64-NEXT: ppaire.h a1, a2, a1 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = srem <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_psrem_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psrem_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: rem a1, a1, a3 |
| ; RV32-NEXT: rem a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psrem_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: remw a2, a0, a1 |
| ; RV64-NEXT: srai a1, a1, 32 |
| ; RV64-NEXT: srai a0, a0, 32 |
| ; RV64-NEXT: remw a0, a0, a1 |
| ; RV64-NEXT: pack a0, a2, a0 |
| ; RV64-NEXT: ret |
| %res = srem <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_purem_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_purem_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a4, a3, 16 |
| ; RV32-NEXT: srli a5, a1, 16 |
| ; RV32-NEXT: remu a4, a5, a4 |
| ; RV32-NEXT: zext.h a3, a3 |
| ; RV32-NEXT: zext.h a1, a1 |
| ; RV32-NEXT: remu a1, a1, a3 |
| ; RV32-NEXT: srli a3, a2, 16 |
| ; RV32-NEXT: srli a5, a0, 16 |
| ; RV32-NEXT: remu a3, a5, a3 |
| ; RV32-NEXT: zext.h a2, a2 |
| ; RV32-NEXT: zext.h a0, a0 |
| ; RV32-NEXT: remu a0, a0, a2 |
| ; RV32-NEXT: pack a1, a1, a4 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; 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 a3, a1 |
| ; RV64-NEXT: zext.h a4, a0 |
| ; RV64-NEXT: remuw a3, a4, a3 |
| ; RV64-NEXT: srli a4, a1, 48 |
| ; RV64-NEXT: srli a5, a0, 48 |
| ; RV64-NEXT: remuw a4, a5, a4 |
| ; RV64-NEXT: slli a1, a1, 16 |
| ; RV64-NEXT: slli a0, a0, 16 |
| ; RV64-NEXT: srli a1, a1, 48 |
| ; RV64-NEXT: srli a0, a0, 48 |
| ; RV64-NEXT: remuw a0, a0, a1 |
| ; RV64-NEXT: ppaire.h a1, a3, a2 |
| ; RV64-NEXT: ppaire.h a0, a0, a4 |
| ; RV64-NEXT: pack a0, a1, a0 |
| ; RV64-NEXT: ret |
| %res = urem <4 x i16> %a, %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_purem_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_purem_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: srli a4, a3, 24 |
| ; RV32-NEXT: srli a5, a1, 24 |
| ; RV32-NEXT: remu a4, a5, a4 |
| ; RV32-NEXT: slli a5, a3, 8 |
| ; RV32-NEXT: slli a6, a1, 8 |
| ; RV32-NEXT: srli a5, a5, 24 |
| ; RV32-NEXT: srli a6, a6, 24 |
| ; RV32-NEXT: remu a5, a6, a5 |
| ; RV32-NEXT: zext.b a6, a3 |
| ; RV32-NEXT: zext.b a7, a1 |
| ; RV32-NEXT: remu a6, a7, a6 |
| ; RV32-NEXT: slli a3, a3, 16 |
| ; RV32-NEXT: slli a1, a1, 16 |
| ; RV32-NEXT: srli a3, a3, 24 |
| ; RV32-NEXT: srli a1, a1, 24 |
| ; RV32-NEXT: remu a1, a1, a3 |
| ; RV32-NEXT: srli a3, a2, 24 |
| ; RV32-NEXT: srli a7, a0, 24 |
| ; RV32-NEXT: remu a3, a7, a3 |
| ; RV32-NEXT: slli a7, a2, 8 |
| ; RV32-NEXT: slli t0, a0, 8 |
| ; RV32-NEXT: srli a7, a7, 24 |
| ; RV32-NEXT: srli t0, t0, 24 |
| ; RV32-NEXT: remu a7, t0, a7 |
| ; RV32-NEXT: zext.b t0, a2 |
| ; RV32-NEXT: zext.b t1, a0 |
| ; RV32-NEXT: remu t0, t1, t0 |
| ; RV32-NEXT: slli a2, a2, 16 |
| ; RV32-NEXT: slli a0, a0, 16 |
| ; RV32-NEXT: srli a2, a2, 24 |
| ; RV32-NEXT: srli a0, a0, 24 |
| ; RV32-NEXT: remu a0, a0, a2 |
| ; RV32-NEXT: ppaire.b a2, a5, a4 |
| ; RV32-NEXT: ppaire.b a1, a6, a1 |
| ; RV32-NEXT: ppaire.b a3, a7, a3 |
| ; RV32-NEXT: ppaire.b a0, t0, a0 |
| ; RV32-NEXT: pack a1, a1, a2 |
| ; RV32-NEXT: pack a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_purem_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: srli a2, a1, 56 |
| ; RV64-NEXT: srli a3, a0, 56 |
| ; RV64-NEXT: remuw a2, a3, a2 |
| ; RV64-NEXT: slli a3, a1, 8 |
| ; RV64-NEXT: slli a4, a0, 8 |
| ; RV64-NEXT: srli a3, a3, 56 |
| ; RV64-NEXT: srli a4, a4, 56 |
| ; RV64-NEXT: remuw a3, a4, a3 |
| ; RV64-NEXT: slli a4, a1, 16 |
| ; RV64-NEXT: slli a5, a0, 16 |
| ; RV64-NEXT: srli a4, a4, 56 |
| ; RV64-NEXT: srli a5, a5, 56 |
| ; RV64-NEXT: remuw a4, a5, a4 |
| ; RV64-NEXT: slli a5, a1, 24 |
| ; RV64-NEXT: slli a6, a0, 24 |
| ; RV64-NEXT: srli a5, a5, 56 |
| ; RV64-NEXT: srli a6, a6, 56 |
| ; RV64-NEXT: remuw a5, a6, a5 |
| ; RV64-NEXT: srliw a6, a1, 24 |
| ; RV64-NEXT: srliw a7, a0, 24 |
| ; RV64-NEXT: remuw a6, a7, a6 |
| ; RV64-NEXT: slli a7, a1, 40 |
| ; RV64-NEXT: slli t0, a0, 40 |
| ; RV64-NEXT: srli a7, a7, 56 |
| ; RV64-NEXT: srli t0, t0, 56 |
| ; RV64-NEXT: remuw a7, t0, a7 |
| ; RV64-NEXT: zext.b t0, a1 |
| ; RV64-NEXT: zext.b t1, a0 |
| ; RV64-NEXT: remuw t0, t1, t0 |
| ; 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 a2, a5, a4 |
| ; RV64-NEXT: ppaire.b a3, a7, a6 |
| ; RV64-NEXT: ppaire.b a0, t0, a0 |
| ; RV64-NEXT: ppaire.h a1, a2, a1 |
| ; RV64-NEXT: ppaire.h a0, a0, a3 |
| ; RV64-NEXT: pack a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = urem <8 x i8> %a, %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_purem_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_purem_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: remu a1, a1, a3 |
| ; RV32-NEXT: remu a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_purem_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: remuw a2, a0, a1 |
| ; RV64-NEXT: srli a1, a1, 32 |
| ; RV64-NEXT: srli a0, a0, 32 |
| ; RV64-NEXT: remuw a0, a0, a1 |
| ; RV64-NEXT: pack a0, a2, a0 |
| ; RV64-NEXT: ret |
| %res = urem <2 x i32> %a, %b |
| ret <2 x i32> %res |
| } |
| |
| ; Comparison operations for v4i16 |
| define <4 x i16> @test_eq_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_eq_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_eq_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp eq <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_ne_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ne_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.dh a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ne_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.h a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_nez_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_nez_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsnez.dh a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_nez_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsnez.h a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <4 x i16> %a, splat (i16 0) |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_slt_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_slt_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_slt_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp slt <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_sle_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_sle_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dh a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sle_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.h a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sle <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_sgt_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_sgt_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dh a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgt_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.h a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_sge_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_sge_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dh a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sge_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.h a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sge <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_sgez_h(<4 x i16> %a) { |
| ; RV32-LABEL: test_sgez_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltz.dh a0, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgez_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltz.h a0, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <4 x i16> %a, splat (i16 -1); |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_ult_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ult_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ult_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp ult <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_ule_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ule_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dh a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ule_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.h a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ule <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_ugt_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ugt_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dh a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ugt_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.h a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ugt <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_uge_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_uge_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dh a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_uge_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.h a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp uge <4 x i16> %a, %b |
| %res = sext <4 x i1> %cmp to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| ; Comparison operations for v8i8 |
| define <8 x i8> @test_eq_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_eq_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_eq_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp eq <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_ne_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ne_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.db a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ne_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.b a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_nez_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_nez_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsnez.db a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_nez_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsnez.b a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <8 x i8> %a, splat (i8 0) |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_slt_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_slt_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_slt_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp slt <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_sle_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_sle_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.db a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sle_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.b a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sle <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_sgt_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_sgt_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.db a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgt_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.b a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_sge_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_sge_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.db a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sge_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.b a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sge <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_sgez_b(<8 x i8> %a) { |
| ; RV32-LABEL: test_sgez_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltz.db a0, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgez_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltz.b a0, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <8 x i8> %a, splat (i8 -1) |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_ult_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ult_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ult_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp ult <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_ule_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ule_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.db a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ule_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.b a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ule <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_ugt_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ugt_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.db a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ugt_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.b a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ugt <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_uge_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_uge_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.db a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_uge_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.b a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp uge <8 x i8> %a, %b |
| %res = sext <8 x i1> %cmp to <8 x i8> |
| ret <8 x i8> %res |
| } |
| |
| ; Comparison operations for v2i32 |
| define <2 x i32> @test_eq_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_eq_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_eq_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp eq <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_ne_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_ne_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.dw a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ne_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.w a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_nez_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_nez_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsnez.dw a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_nez_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsnez.w a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ne <2 x i32> %a, splat (i32 0) |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_slt_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_slt_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_slt_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp slt <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_sle_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_sle_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dw a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sle_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.w a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sle <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_sgt_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_sgt_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dw a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgt_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.w a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_sge_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_sge_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dw a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sge_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.w a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sge <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_sgez_w(<2 x i32> %a) { |
| ; RV32-LABEL: test_sgez_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltz.dw a0, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sgez_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltz.w a0, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp sgt <2 x i32> %a, splat (i32 -1) |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_ult_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_ult_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ult_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %cmp = icmp ult <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_ule_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_ule_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dw a0, a2, a0 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ule_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.w a0, a1, a0 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ule <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_ugt_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_ugt_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dw a0, a2, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ugt_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.w a0, a1, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp ugt <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_uge_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_uge_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.dw a0, a0, a2 |
| ; RV32-NEXT: not a1, a1 |
| ; RV32-NEXT: not a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_uge_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.w a0, a0, a1 |
| ; RV64-NEXT: not a0, a0 |
| ; RV64-NEXT: ret |
| %cmp = icmp uge <2 x i32> %a, %b |
| %res = sext <2 x i1> %cmp to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| ; Test 8/16/32-bit [s|u]min/[s|u]max |
| define <4 x i16> @test_smin_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_smin_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmin.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smin_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmin.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <4 x i16> @llvm.smin.v2i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %min |
| } |
| |
| define <4 x i16> @test_umin_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_umin_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pminu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umin_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pminu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <4 x i16> @llvm.umin.v2i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %min |
| } |
| |
| define <8 x i8> @test_smin_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_smin_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmin.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smin_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmin.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <8 x i8> @llvm.smin.v4i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %min |
| } |
| |
| define <8 x i8> @test_umin_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_umin_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pminu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umin_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pminu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <8 x i8> @llvm.umin.v4i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %min |
| } |
| |
| define <2 x i32> @test_smin_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_smin_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmin.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smin_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmin.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %min |
| } |
| |
| define <2 x i32> @test_umin_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_umin_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pminu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umin_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pminu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %min |
| } |
| |
| define <4 x i16> @test_smax_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_smax_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmax.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smax_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmax.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <4 x i16> @llvm.smax.v2i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %max |
| } |
| |
| define <4 x i16> @test_umax_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_umax_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmaxu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umax_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmaxu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <4 x i16> @llvm.umax.v2i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %max |
| } |
| |
| define <8 x i8> @test_smax_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_smax_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmax.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smax_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmax.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <8 x i8> @llvm.smax.v4i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %max |
| } |
| |
| define <8 x i8> @test_umax_b(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_umax_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmaxu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umax_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmaxu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <8 x i8> @llvm.umax.v4i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %max |
| } |
| |
| define <2 x i32> @test_smax_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_smax_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmax.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_smax_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmax.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <2 x i32> @llvm.smax.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %max |
| } |
| |
| define <2 x i32> @test_umax_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_umax_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmaxu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_umax_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmaxu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %max |
| } |
| |
| ; Test select operations |
| define <4 x i16> @test_select_v4i16(i1 %cond, <4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_select_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a5, a0, 1 |
| ; RV32-NEXT: bnez a5, .LBB236_2 |
| ; RV32-NEXT: # %bb.1: |
| ; RV32-NEXT: mv a0, a3 |
| ; RV32-NEXT: mv a1, a4 |
| ; RV32-NEXT: ret |
| ; RV32-NEXT: .LBB236_2: |
| ; RV32-NEXT: mv a0, a1 |
| ; RV32-NEXT: mv a1, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_select_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a3, a0, 1 |
| ; RV64-NEXT: mv a0, a1 |
| ; RV64-NEXT: bnez a3, .LBB236_2 |
| ; RV64-NEXT: # %bb.1: |
| ; RV64-NEXT: mv a0, a2 |
| ; RV64-NEXT: .LBB236_2: |
| ; RV64-NEXT: ret |
| %res = select i1 %cond, <4 x i16> %a, <4 x i16> %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_select_v8i8(i1 %cond, <8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_select_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a5, a0, 1 |
| ; RV32-NEXT: bnez a5, .LBB237_2 |
| ; RV32-NEXT: # %bb.1: |
| ; RV32-NEXT: mv a0, a3 |
| ; RV32-NEXT: mv a1, a4 |
| ; RV32-NEXT: ret |
| ; RV32-NEXT: .LBB237_2: |
| ; RV32-NEXT: mv a0, a1 |
| ; RV32-NEXT: mv a1, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_select_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a3, a0, 1 |
| ; RV64-NEXT: mv a0, a1 |
| ; RV64-NEXT: bnez a3, .LBB237_2 |
| ; RV64-NEXT: # %bb.1: |
| ; RV64-NEXT: mv a0, a2 |
| ; RV64-NEXT: .LBB237_2: |
| ; RV64-NEXT: ret |
| %res = select i1 %cond, <8 x i8> %a, <8 x i8> %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_select_v2i32(i1 %cond, <2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_select_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a5, a0, 1 |
| ; RV32-NEXT: bnez a5, .LBB238_2 |
| ; RV32-NEXT: # %bb.1: |
| ; RV32-NEXT: mv a0, a3 |
| ; RV32-NEXT: mv a1, a4 |
| ; RV32-NEXT: ret |
| ; RV32-NEXT: .LBB238_2: |
| ; RV32-NEXT: mv a0, a1 |
| ; RV32-NEXT: mv a1, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_select_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a3, a0, 1 |
| ; RV64-NEXT: mv a0, a1 |
| ; RV64-NEXT: bnez a3, .LBB238_2 |
| ; RV64-NEXT: # %bb.1: |
| ; RV64-NEXT: mv a0, a2 |
| ; RV64-NEXT: .LBB238_2: |
| ; RV64-NEXT: ret |
| %res = select i1 %cond, <2 x i32> %a, <2 x i32> %b |
| ret <2 x i32> %res |
| } |
| |
| ; Test vselect operations |
| define <4 x i16> @test_vselect_v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) { |
| ; RV32-LABEL: test_vselect_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmseq.dh a0, a0, a2 |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_vselect_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmseq.h a0, a0, a1 |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %mask = icmp eq <4 x i16> %a, %b |
| %res = select <4 x i1> %mask, <4 x i16> %c, <4 x i16> %b |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_vselect_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { |
| ; RV32-LABEL: test_vselect_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmsltu.db a0, a0, a2 |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_vselect_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmsltu.b a0, a0, a1 |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %mask = icmp ult <8 x i8> %a, %b |
| %res = select <8 x i1> %mask, <8 x i8> %c, <8 x i8> %b |
| ret <8 x i8> %res |
| } |
| |
| define <2 x i32> @test_vselect_v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) { |
| ; RV32-LABEL: test_vselect_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmslt.dw a6, a2, a0 |
| ; RV32-NEXT: mv a0, a4 |
| ; RV32-NEXT: beqz a7, .LBB241_3 |
| ; RV32-NEXT: # %bb.1: |
| ; RV32-NEXT: beqz a6, .LBB241_4 |
| ; RV32-NEXT: .LBB241_2: |
| ; RV32-NEXT: mv a1, a5 |
| ; RV32-NEXT: ret |
| ; RV32-NEXT: .LBB241_3: |
| ; RV32-NEXT: mv a5, a3 |
| ; RV32-NEXT: bnez a6, .LBB241_2 |
| ; RV32-NEXT: .LBB241_4: |
| ; RV32-NEXT: mv a0, a2 |
| ; RV32-NEXT: mv a1, a5 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_vselect_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmslt.w a0, a1, a0 |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %mask = icmp sgt <2 x i32> %a, %b |
| %res = select <2 x i1> %mask, <2 x i32> %c, <2 x i32> %b |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_bswap_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_bswap_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppairoe.db a0, a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_bswap_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppairoe.b a0, a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.bswap.v4i16(<4 x i16> %a) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_bswap_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_bswap_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: rev8 a1, a1 |
| ; RV32-NEXT: rev8 a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_bswap_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: rev8 a0, a0 |
| ; RV64-NEXT: ppairoe.w a0, a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %a) |
| ret <2 x i32> %res |
| } |
| |
| define <8 x i8> @test_bitreverse_v8i8(<8 x i8> %a) { |
| ; RV32-LABEL: test_bitreverse_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: rev a1, a1 |
| ; RV32-NEXT: rev a0, a0 |
| ; RV32-NEXT: rev8 a1, a1 |
| ; RV32-NEXT: rev8 a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_bitreverse_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: rev a0, a0 |
| ; RV64-NEXT: rev8 a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.bitreverse.v8i8(<8 x i8> %a) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_bitreverse_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_bitreverse_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: rev a1, a1 |
| ; RV32-NEXT: rev a0, a0 |
| ; RV32-NEXT: ppairoe.dh a0, a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_bitreverse_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: rev a0, a0 |
| ; RV64-NEXT: rev16 a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.bitreverse.v4i16(<4 x i16> %a) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_bitreverse_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_bitreverse_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: rev a1, a1 |
| ; RV32-NEXT: rev a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_bitreverse_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: rev a0, a0 |
| ; RV64-NEXT: ppairoe.w a0, a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_zext_v4i8_to_v4i16(<4 x i8> %a) { |
| ; RV32-LABEL: test_zext_v4i8_to_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvtu.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_zext_v4i8_to_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pwcvtu.wb a0, a0 |
| ; RV64-NEXT: ret |
| %res = zext <4 x i8> %a to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_zext_v2i16_to_v2i32(<2 x i16> %a) { |
| ; RV32-LABEL: test_zext_v2i16_to_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvtu.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_zext_v2i16_to_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pwcvtu.wh a0, a0 |
| ; RV64-NEXT: ret |
| %res = zext <2 x i16> %a to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_sext_v4i8_to_v4i16(<4 x i8> %a) { |
| ; RV32-LABEL: test_sext_v4i8_to_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvt.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sext_v4i8_to_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pwcvtu.wb a0, a0 |
| ; RV64-NEXT: psext.h.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = sext <4 x i8> %a to <4 x i16> |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_sext_v2i16_to_v2i32(<2 x i16> %a) { |
| ; RV32-LABEL: test_sext_v2i16_to_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pwcvt.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_sext_v2i16_to_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pwcvtu.wh a0, a0 |
| ; RV64-NEXT: psext.w.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = sext <2 x i16> %a to <2 x i32> |
| ret <2 x i32> %res |
| } |
| |
| define <8 x i8> @test_paadd_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_paadd_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.paadd.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_paaddu_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_paaddu_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.paaddu.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pasub_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pasub_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pasub.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pasubu_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pasubu_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pasubu.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_paadd_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_paadd_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.paadd.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_paaddu_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_paaddu_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.paaddu.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pasub_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pasub_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pasub.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pasubu_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pasubu_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pasubu.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_paadd_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_paadd_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paadd.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paadd_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paadd.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.paadd.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_paaddu_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_paaddu_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paaddu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paaddu_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paaddu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.paaddu.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pasub_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pasub_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasub.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasub_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasub.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pasub.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pasubu_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pasubu_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasubu.dw a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasubu_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasubu.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pasubu.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i16> @test_pnsrai_h(<2 x i32> %a) { |
| ; RV32-LABEL: test_pnsrai_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsrai.h a0, a0, 23 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrai_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrai.w a0, a0, 23 |
| ; RV64-NEXT: pncvt.wh a0, a0 |
| ; RV64-NEXT: ret |
| %ashr = ashr <2 x i32> %a, splat(i32 23) |
| %trunc = trunc <2 x i32> %ashr to <2 x i16> |
| ret <2 x i16> %trunc |
| } |
| |
| define <4 x i8> @test_pnsrai_b(<4 x i16> %a) { |
| ; RV32-LABEL: test_pnsrai_b: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsrai.b a0, a0, 9 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrai_b: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrai.h a0, a0, 9 |
| ; RV64-NEXT: pncvt.wb a0, a0 |
| ; RV64-NEXT: ret |
| %ashr = ashr <4 x i16> %a, splat(i16 9) |
| %trunc = trunc <4 x i16> %ashr to <4 x i8> |
| ret <4 x i8> %trunc |
| } |
| |
| define <4 x i8> @test_pnsrl_bs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_pnsrl_bs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsrl.bs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrl_bs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.hs a0, a0, a1 |
| ; RV64-NEXT: pncvt.wb a0, a0 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %lshr = lshr <4 x i16> %a, %b |
| %trunc = trunc <4 x i16> %lshr to <4 x i8> |
| ret <4 x i8> %trunc |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <4 x i8> @test_pnsrl_bs_mask(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_pnsrl_bs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 15 |
| ; RV32-NEXT: pnsrl.bs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrl_bs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 15 |
| ; RV64-NEXT: psrl.hs a0, a0, a1 |
| ; RV64-NEXT: pncvt.wb a0, a0 |
| ; RV64-NEXT: ret |
| %masked = and i16 %shamt, 15 |
| %insert = insertelement <4 x i16> poison, i16 %masked, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %lshr = lshr <4 x i16> %a, %b |
| %trunc = trunc <4 x i16> %lshr to <4 x i8> |
| ret <4 x i8> %trunc |
| } |
| |
| define <2 x i16> @test_pnsrl_hs(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pnsrl_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsrl.hs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrl_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.ws a0, a0, a1 |
| ; RV64-NEXT: pncvt.wh a0, a0 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %lshr = lshr <2 x i32> %a, %b |
| %trunc = trunc <2 x i32> %lshr to <2 x i16> |
| ret <2 x i16> %trunc |
| } |
| |
| define <2 x i16> @test_pnsrl_hs_mask(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pnsrl_hs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsrl.hs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsrl_hs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psrl.ws a0, a0, a1 |
| ; RV64-NEXT: pncvt.wh a0, a0 |
| ; RV64-NEXT: ret |
| %masked = and i32 %shamt, 31 |
| %insert = insertelement <2 x i32> poison, i32 %masked, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %lshr = lshr <2 x i32> %a, %b |
| %trunc = trunc <2 x i32> %lshr to <2 x i16> |
| ret <2 x i16> %trunc |
| } |
| |
| define <4 x i8> @test_pnsra_bs(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_pnsra_bs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsra.bs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsra_bs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.hs a0, a0, a1 |
| ; RV64-NEXT: pncvt.wb a0, a0 |
| ; RV64-NEXT: ret |
| %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %ashr = ashr <4 x i16> %a, %b |
| %trunc = trunc <4 x i16> %ashr to <4 x i8> |
| ret <4 x i8> %trunc |
| } |
| |
| ; We can't remove the andi, the hardware instruction always reads 5 bits. |
| define <4 x i8> @test_pnsra_bs_mask(<4 x i16> %a, i16 %shamt) { |
| ; RV32-LABEL: test_pnsra_bs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: andi a2, a2, 15 |
| ; RV32-NEXT: pnsra.bs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsra_bs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: andi a1, a1, 15 |
| ; RV64-NEXT: psra.hs a0, a0, a1 |
| ; RV64-NEXT: pncvt.wb a0, a0 |
| ; RV64-NEXT: ret |
| %masked = and i16 %shamt, 15 |
| %insert = insertelement <4 x i16> poison, i16 %masked, i32 0 |
| %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer |
| %ashr = ashr <4 x i16> %a, %b |
| %trunc = trunc <4 x i16> %ashr to <4 x i8> |
| ret <4 x i8> %trunc |
| } |
| |
| define <2 x i16> @test_pnsra_hs(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pnsra_hs: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsra.hs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsra_hs: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.ws a0, a0, a1 |
| ; RV64-NEXT: pncvt.wh a0, a0 |
| ; RV64-NEXT: ret |
| %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %ashr = ashr <2 x i32> %a, %b |
| %trunc = trunc <2 x i32> %ashr to <2 x i16> |
| ret <2 x i16> %trunc |
| } |
| |
| define <2 x i16> @test_pnsra_hs_mask(<2 x i32> %a, i32 %shamt) { |
| ; RV32-LABEL: test_pnsra_hs_mask: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pnsra.hs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pnsra_hs_mask: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psra.ws a0, a0, a1 |
| ; RV64-NEXT: pncvt.wh a0, a0 |
| ; RV64-NEXT: ret |
| %masked = and i32 %shamt, 31 |
| %insert = insertelement <2 x i32> poison, i32 %masked, i32 0 |
| %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer |
| %ashr = ashr <2 x i32> %a, %b |
| %trunc = trunc <2 x i32> %ashr to <2 x i16> |
| ret <2 x i16> %trunc |
| } |
| |
| define <8 x i8> @test_pabd_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabd_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabd.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabd_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabd.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pabd.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_pabd_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pabd_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabd.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabd_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabd.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pabd.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <8 x i8> @test_pabdu_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabdu_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdu.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdu_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pabdu.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_pabdu_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pabdu_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdu.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdu_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdu.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pabdu.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pas_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pas_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pas.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pas_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pas.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pas.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psa_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psa_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psa.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psa_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psa.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psa.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_psas_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_psas_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psas.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psas_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psas.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psas.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pssa_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pssa_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pssa.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssa_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssa.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pssa.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_paas_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_paas_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: paas.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paas_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paas.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.paas.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pasa_x_h(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pasa_x_h: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pasa.dhx a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasa_x_h: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasa.hx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pasa.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pas_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pas_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: add a1, a1, a2 |
| ; RV32-NEXT: sub a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pas_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pas.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pas.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psa_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psa_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: sub a1, a1, a2 |
| ; RV32-NEXT: add a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psa_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psa.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psa.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psas_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_psas_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: sadd a1, a1, a2 |
| ; RV32-NEXT: ssub a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psas_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psas.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psas.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pssa_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pssa_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ssub a1, a1, a2 |
| ; RV32-NEXT: sadd a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pssa_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pssa.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pssa.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_paas_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_paas_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: aadd a1, a1, a2 |
| ; RV32-NEXT: asub a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_paas_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: paas.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.paas.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pasa_x_w(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pasa_x_w: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: asub a1, a1, a2 |
| ; RV32-NEXT: aadd a0, a0, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pasa_x_w: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pasa.wx a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pasa.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| ; Packed reduction sum |
| define i32 @test_predsum_i8x8_i32(<8 x i8> %a, i32 %b) { |
| ; RV32-LABEL: test_predsum_i8x8_i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsum.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsum_i8x8_i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsum.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.predsum.i32.v8i8(<8 x i8> %a, i32 %b) |
| ret i32 %res |
| } |
| |
| define i32 @test_predsumu_u8x8_u32(<8 x i8> %a, i32 %b) { |
| ; RV32-LABEL: test_predsumu_u8x8_u32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsumu.dbs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsumu_u8x8_u32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsumu.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.predsumu.i32.v8i8(<8 x i8> %a, i32 %b) |
| ret i32 %res |
| } |
| |
| define i64 @test_predsum_i8x8_i64(<8 x i8> %a, i64 %b) { |
| ; RV32-LABEL: test_predsum_i8x8_i64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsum.dbs a0, a0, zero |
| ; RV32-NEXT: wadda a2, a0, zero |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsum_i8x8_i64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsum.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsum.i64.v8i8(<8 x i8> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| define i64 @test_predsumu_u8x8_u64(<8 x i8> %a, i64 %b) { |
| ; RV32-LABEL: test_predsumu_u8x8_u64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsumu.dbs a0, a0, zero |
| ; RV32-NEXT: waddau a2, a0, zero |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsumu_u8x8_u64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsumu.bs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsumu.i64.v8i8(<8 x i8> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| define i32 @test_predsum_i16x4_i32(<4 x i16> %a, i32 %b) { |
| ; RV32-LABEL: test_predsum_i16x4_i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsum.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsum_i16x4_i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsum.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.predsum.i32.v4i16(<4 x i16> %a, i32 %b) |
| ret i32 %res |
| } |
| |
| define i32 @test_predsumu_u16x4_u32(<4 x i16> %a, i32 %b) { |
| ; RV32-LABEL: test_predsumu_u16x4_u32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsumu.dhs a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsumu_u16x4_u32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsumu.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.predsumu.i32.v4i16(<4 x i16> %a, i32 %b) |
| ret i32 %res |
| } |
| |
| define i64 @test_predsum_i16x4_i64(<4 x i16> %a, i64 %b) { |
| ; RV32-LABEL: test_predsum_i16x4_i64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsum.dhs a0, a0, zero |
| ; RV32-NEXT: wadda a2, a0, zero |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsum_i16x4_i64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsum.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsum.i64.v4i16(<4 x i16> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| define i64 @test_predsumu_u16x4_u64(<4 x i16> %a, i64 %b) { |
| ; RV32-LABEL: test_predsumu_u16x4_u64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: predsumu.dhs a0, a0, zero |
| ; RV32-NEXT: waddau a2, a0, zero |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsumu_u16x4_u64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsumu.hs a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsumu.i64.v4i16(<4 x i16> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| define i64 @test_predsum_i32x2_i64(<2 x i32> %a, i64 %b) { |
| ; RV32-LABEL: test_predsum_i32x2_i64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: wadda a2, a0, a1 |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsum_i32x2_i64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsum.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsum.i64.v2i32(<2 x i32> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| define i64 @test_predsumu_u32x2_u64(<2 x i32> %a, i64 %b) { |
| ; RV32-LABEL: test_predsumu_u32x2_u64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: waddau a2, a0, a1 |
| ; RV32-NEXT: mvd a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_predsumu_u32x2_u64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: predsumu.ws a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.predsumu.i64.v2i32(<2 x i32> %a, i64 %b) |
| ret i64 %res |
| } |
| |
| ; Packed Merge |
| define <8 x i8> @test_pmerge_merge_u8x8(<8 x i8> %rd, <8 x i8> %rs1, <8 x i8> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_u8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_u8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmerge_mvm_u8x8(<8 x i8> %rs1, <8 x i8> %rd, <8 x i8> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_u8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_u8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmerge_mvmn_u8x8(<8 x i8> %rs2, <8 x i8> %rs1, <8 x i8> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_u8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_u8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmerge_merge_i8x8(<8 x i8> %rd, <8 x i8> %rs1, <8 x i8> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_i8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_i8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmerge_mvm_i8x8(<8 x i8> %rs1, <8 x i8> %rd, <8 x i8> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_i8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_i8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_pmerge_mvmn_i8x8(<8 x i8> %rs2, <8 x i8> %rs1, <8 x i8> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_i8x8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_i8x8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.pmerge.v8i8(<8 x i8> %rs1, <8 x i8> %rs2, <8 x i8> %rd) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_pmerge_merge_u16x4(<4 x i16> %rd, <4 x i16> %rs1, <4 x i16> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_u16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_u16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmerge_mvm_u16x4(<4 x i16> %rs1, <4 x i16> %rd, <4 x i16> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_u16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_u16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmerge_mvmn_u16x4(<4 x i16> %rs2, <4 x i16> %rs1, <4 x i16> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_u16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_u16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmerge_merge_i16x4(<4 x i16> %rd, <4 x i16> %rs1, <4 x i16> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_i16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_i16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmerge_mvm_i16x4(<4 x i16> %rs1, <4 x i16> %rd, <4 x i16> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_i16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_i16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmerge_mvmn_i16x4(<4 x i16> %rs2, <4 x i16> %rs1, <4 x i16> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_i16x4: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_i16x4: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmerge.v4i16(<4 x i16> %rs1, <4 x i16> %rs2, <4 x i16> %rd) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmerge_merge_u32x2(<2 x i32> %rd, <2 x i32> %rs1, <2 x i32> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_u32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_u32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmerge_mvm_u32x2(<2 x i32> %rs1, <2 x i32> %rd, <2 x i32> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_u32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_u32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmerge_mvmn_u32x2(<2 x i32> %rs2, <2 x i32> %rs1, <2 x i32> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_u32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_u32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmerge_merge_i32x2(<2 x i32> %rd, <2 x i32> %rs1, <2 x i32> %rs2) { |
| ; RV32-LABEL: test_pmerge_merge_i32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: merge a1, a3, a5 |
| ; RV32-NEXT: merge a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_merge_i32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: merge a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmerge_mvm_i32x2(<2 x i32> %rs1, <2 x i32> %rd, <2 x i32> %rs2) { |
| ; RV32-LABEL: test_pmerge_mvm_i32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvm a1, a5, a3 |
| ; RV32-NEXT: mvm a0, a4, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvm_i32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvm a0, a2, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmerge_mvmn_i32x2(<2 x i32> %rs2, <2 x i32> %rs1, <2 x i32> %rd) { |
| ; RV32-LABEL: test_pmerge_mvmn_i32x2: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mvmn a1, a3, a5 |
| ; RV32-NEXT: mvmn a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmerge_mvmn_i32x2: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: mvmn a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmerge.v2i32(<2 x i32> %rs1, <2 x i32> %rs2, <2 x i32> %rd) |
| ret <2 x i32> %res |
| } |
| |
| ; Packed sign and zero extend |
| define <4 x i16> @test_psext_b_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_psext_b_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dh.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psext_b_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.h.b a0, a0 |
| ; RV64-NEXT: ret |
| %shl = shl <4 x i16> %a, splat (i16 8) |
| %res = ashr <4 x i16> %shl, splat (i16 8) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_psext_b_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_psext_b_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dw.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psext_b_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.w.b a0, a0 |
| ; RV64-NEXT: ret |
| %shl = shl <2 x i32> %a, splat (i32 24) |
| %res = ashr <2 x i32> %shl, splat (i32 24) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_psext_h_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_psext_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dw.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psext_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.w.h a0, a0 |
| ; RV64-NEXT: ret |
| %shl = shl <2 x i32> %a, splat (i32 16) |
| %res = ashr <2 x i32> %shl, splat (i32 16) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_pzext_b_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_pzext_b_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pzext.dh.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pzext_b_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pzext.h.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = and <4 x i16> %a, splat (i16 255) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pzext_h_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_pzext_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pzext.dw.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pzext_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pzext.w.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = and <2 x i32> %a, splat (i32 65535) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_riscv_psext_b_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_riscv_psext_b_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dh.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_riscv_psext_b_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.h.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psext.b.v4i16(<4 x i16> %a) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_riscv_psext_b_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_riscv_psext_b_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dw.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_riscv_psext_b_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.w.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psext.b.v2i32(<2 x i32> %a) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_riscv_psext_h_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_riscv_psext_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psext.dw.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_riscv_psext_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psext.w.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.psext.h.v2i32(<2 x i32> %a) |
| ret <2 x i32> %res |
| } |
| |
| define <4 x i16> @test_riscv_pzext_b_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_riscv_pzext_b_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pzext.dh.b a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_riscv_pzext_b_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pzext.h.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pzext.b.v4i16(<4 x i16> %a) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_riscv_pzext_h_v2i32(<2 x i32> %a) { |
| ; RV32-LABEL: test_riscv_pzext_h_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pzext.dw.h a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_riscv_pzext_h_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pzext.w.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pzext.h.v2i32(<2 x i32> %a) |
| ret <2 x i32> %res |
| } |
| |
| ; Packed absolute difference sum |
| define i32 @test_pabdsumu_u8x8_u32(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabdsumu_u8x8_u32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdsumu.b a0, a0, a2 |
| ; RV32-NEXT: pabdsumau.b a0, a1, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdsumu_u8x8_u32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdsumu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.pabdsumu.i32.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret i32 %res |
| } |
| |
| define i64 @test_pabdsumu_u8x8_u64(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabdsumu_u8x8_u64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdsumu.b a1, a1, a3 |
| ; RV32-NEXT: pabdsumu.b a0, a0, a2 |
| ; RV32-NEXT: waddu a0, a0, a1 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdsumu_u8x8_u64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdsumu.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.pabdsumu.i64.v8i8(<8 x i8> %a, <8 x i8> %b) |
| ret i64 %res |
| } |
| |
| define i32 @test_pabdsumau_u8x8_u32(i32 %rd, <8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabdsumau_u8x8_u32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdsumau.b a0, a1, a3 |
| ; RV32-NEXT: pabdsumau.b a0, a2, a4 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdsumau_u8x8_u32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdsumau.b a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call i32 @llvm.riscv.pabdsumau.i32.v8i8(i32 %rd, <8 x i8> %a, <8 x i8> %b) |
| ret i32 %res |
| } |
| |
| define i64 @test_pabdsumau_u8x8_u64(i64 %rd, <8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_pabdsumau_u8x8_u64: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pabdsumu.b a3, a3, a5 |
| ; RV32-NEXT: pabdsumu.b a2, a2, a4 |
| ; RV32-NEXT: waddau a0, a2, a3 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pabdsumau_u8x8_u64: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pabdsumau.b a0, a1, a2 |
| ; RV64-NEXT: ret |
| %res = call i64 @llvm.riscv.pabdsumau.i64.v8i8(i64 %rd, <8 x i8> %a, <8 x i8> %b) |
| ret i64 %res |
| } |
| |
| ; Packed Saturating Absolute Value |
| define <8 x i8> @test_psabs_v8i8(<8 x i8> %a) { |
| ; RV32-LABEL: test_psabs_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psabs.db a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psabs_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psabs.b a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <8 x i8> @llvm.riscv.psabs.v8i8(<8 x i8> %a) |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_psabs_v4i16(<4 x i16> %a) { |
| ; RV32-LABEL: test_psabs_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: psabs.dh a0, a0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_psabs_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: psabs.h a0, a0 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.psabs.v4i16(<4 x i16> %a) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmulq_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulq_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulq.h a1, a1, a3 |
| ; RV32-NEXT: pmulq.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulq_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulq.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmulq.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_pmulqr_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_pmulqr_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: pmulqr.h a1, a1, a3 |
| ; RV32-NEXT: pmulqr.h a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulqr_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulqr.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <4 x i16> @llvm.riscv.pmulqr.v4i16(<4 x i16> %a, <4 x i16> %b) |
| ret <4 x i16> %res |
| } |
| |
| define <2 x i32> @test_pmulq_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulq_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulq a1, a1, a3 |
| ; RV32-NEXT: mulq a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulq_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulq.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmulq.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_pmulqr_v2i32(<2 x i32> %a, <2 x i32> %b) { |
| ; RV32-LABEL: test_pmulqr_v2i32: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: mulqr a1, a1, a3 |
| ; RV32-NEXT: mulqr a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_pmulqr_v2i32: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: pmulqr.w a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = call <2 x i32> @llvm.riscv.pmulqr.v2i32(<2 x i32> %a, <2 x i32> %b) |
| ret <2 x i32> %res |
| } |
| |
| define <2 x i32> @test_return_zero() { |
| ; RV32-LABEL: test_return_zero: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: li a1, 0 |
| ; RV32-NEXT: li a0, 0 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_return_zero: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: li a0, 0 |
| ; RV64-NEXT: ret |
| ret <2 x i32> splat (i32 0) |
| } |
| |
| define <8 x i8> @test_undef_v8i8() { |
| ; CHECK-LABEL: test_undef_v8i8: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| ret <8 x i8> undef |
| } |
| |
| define <4 x i16> @test_undef_v4i16() { |
| ; CHECK-LABEL: test_undef_v4i16: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| ret <4 x i16> undef |
| } |
| |
| define <2 x i32> @test_undef_v2i32() { |
| ; CHECK-LABEL: test_undef_v2i32: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: ret |
| ret <2 x i32> undef |
| } |
| |
| define <8 x i8> @test_ppaireo_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ppaireo_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppaireo.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ppaireo_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppaireo.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15> |
| ret <8 x i8> %res |
| } |
| |
| define <8 x i8> @test_ppairoe_v8i8(<8 x i8> %a, <8 x i8> %b) { |
| ; RV32-LABEL: test_ppairoe_v8i8: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppairoe.db a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ppairoe_v8i8: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppairoe.b a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 8, i32 3, i32 10, i32 5, i32 12, i32 7, i32 14> |
| ret <8 x i8> %res |
| } |
| |
| define <4 x i16> @test_ppaireo_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ppaireo_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppaireo.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ppaireo_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppaireo.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 7> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @test_ppairoe_v4i16(<4 x i16> %a, <4 x i16> %b) { |
| ; RV32-LABEL: test_ppairoe_v4i16: |
| ; RV32: # %bb.0: |
| ; RV32-NEXT: ppairoe.dh a0, a0, a2 |
| ; RV32-NEXT: ret |
| ; |
| ; RV64-LABEL: test_ppairoe_v4i16: |
| ; RV64: # %bb.0: |
| ; RV64-NEXT: ppairoe.h a0, a0, a1 |
| ; RV64-NEXT: ret |
| %res = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 4, i32 3, i32 6> |
| ret <4 x i16> %res |
| } |