Skip to content

Commit

Permalink
[Clang][XTHeadVector] Implement vadd/vsub/vrsub/vneg intrinsics (ll…
Browse files Browse the repository at this point in the history
…vm#58)

* [Clang][XTHeadVector] Implement `vadd/vsub/vrsub`

* [Clang][XTHeadVector] Test some handwritten `vadd` cases

* [Clang][XTHeadVector] Add tests

* [Clang][XTHeadVector] Add wrappers and tests

* [Clang][XTHeadVector] Add `vneg`
  • Loading branch information
imkiva committed Jan 26, 2024
1 parent 8294393 commit d9c904f
Show file tree
Hide file tree
Showing 10 changed files with 3,814 additions and 0 deletions.
41 changes: 41 additions & 0 deletions clang/include/clang/Basic/riscv_vector_xtheadv.td
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ multiclass RVVUSSegLoad<string ir, string bhwe, bit with_eew, list<string> types
if (IsMasked)
Operands.push_back(Ops[0]);
Operands.push_back(Ops[Offset + 1]); // VL
// TODO: no policy in LLVM side for masked intrinsics.
if (IsMasked)
Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));

Expand Down Expand Up @@ -712,6 +713,7 @@ multiclass RVVUSSegLoadFF<string ir, string bhwe, bit with_eew, list<string> typ
if (IsMasked)
Operands.push_back(Ops[0]);
Operands.push_back(Ops[Offset + 2]); // vl
// TODO: no policy in LLVM side for masked intrinsics.
if (IsMasked)
Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));

Expand Down Expand Up @@ -779,8 +781,47 @@ let UnMaskedPolicyScheme = NonePolicy,
// 12. Vector Integer Arithmetic Operations
//===----------------------------------------------------------------------===//

multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
let Name = NAME,
IRName = IR,
MaskedIRName = IR # "_mask",
UnMaskedPolicyScheme = HasPassthruOperand,
ManualCodegen = [{
{
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
}
auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));

if (IsMasked) {
// TODO: no policy in LLVM side for masked intrinsics.
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, op2, mask, vl, policy
IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
} else {
// passthru, op1, op2, vl
IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
}
break;
}
}] in {
def : RVVBuiltin<"v", "vv", type_range>;
}
}

let UnMaskedPolicyScheme = HasPassthruOperand in {
defm th_vadd : RVVIntBinBuiltinSet;
defm th_vsub : RVVIntBinBuiltinSet;
defm th_vrsub : RVVOutOp1BuiltinSet<"th_vrsub", "csil",
[["vx", "v", "vve"],
["vx", "Uv", "UvUvUe"]]>;
}
defm th_vneg_v : RVVPseudoUnaryBuiltin<"th_vrsub", "csil">;

include "riscv_vector_xtheadv_wrappers.td"
205 changes: 205 additions & 0 deletions clang/include/clang/Basic/riscv_vector_xtheadv_wrappers.td

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// RUN: %clang_cc1 -triple riscv64 -target-feature +xtheadvector \
// RUN: -disable-O0-optnone -emit-llvm %s -o - | \
// RUN: opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x i8> @test_vneg_v_i8m1
// CHECK-RV64-SAME: (<vscale x 8 x i8> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i8> @llvm.riscv.th.vrsub.nxv8i8.i8.i64(<vscale x 8 x i8> poison, <vscale x 8 x i8> [[OP1]], i8 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x i8> [[TMP0]]
//
vint8m1_t test_vneg_v_i8m1(vint8m1_t op1, size_t vl) {
return __riscv_th_vneg_v_i8m1(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i8> @test_vneg_v_i8m2
// CHECK-RV64-SAME: (<vscale x 16 x i8> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i8> @llvm.riscv.th.vrsub.nxv16i8.i8.i64(<vscale x 16 x i8> poison, <vscale x 16 x i8> [[OP1]], i8 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x i8> [[TMP0]]
//
vint8m2_t test_vneg_v_i8m2(vint8m2_t op1, size_t vl) {
return __riscv_th_vneg_v_i8m2(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x i8> @test_vneg_v_i8m4
// CHECK-RV64-SAME: (<vscale x 32 x i8> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x i8> @llvm.riscv.th.vrsub.nxv32i8.i8.i64(<vscale x 32 x i8> poison, <vscale x 32 x i8> [[OP1]], i8 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 32 x i8> [[TMP0]]
//
vint8m4_t test_vneg_v_i8m4(vint8m4_t op1, size_t vl) {
return __riscv_th_vneg_v_i8m4(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 64 x i8> @test_vneg_v_i8m8
// CHECK-RV64-SAME: (<vscale x 64 x i8> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 64 x i8> @llvm.riscv.th.vrsub.nxv64i8.i8.i64(<vscale x 64 x i8> poison, <vscale x 64 x i8> [[OP1]], i8 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 64 x i8> [[TMP0]]
//
vint8m8_t test_vneg_v_i8m8(vint8m8_t op1, size_t vl) {
return __riscv_th_vneg_v_i8m8(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x i16> @test_vneg_v_i16m1
// CHECK-RV64-SAME: (<vscale x 4 x i16> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i16> @llvm.riscv.th.vrsub.nxv4i16.i16.i64(<vscale x 4 x i16> poison, <vscale x 4 x i16> [[OP1]], i16 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x i16> [[TMP0]]
//
vint16m1_t test_vneg_v_i16m1(vint16m1_t op1, size_t vl) {
return __riscv_th_vneg_v_i16m1(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x i16> @test_vneg_v_i16m2
// CHECK-RV64-SAME: (<vscale x 8 x i16> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i16> @llvm.riscv.th.vrsub.nxv8i16.i16.i64(<vscale x 8 x i16> poison, <vscale x 8 x i16> [[OP1]], i16 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x i16> [[TMP0]]
//
vint16m2_t test_vneg_v_i16m2(vint16m2_t op1, size_t vl) {
return __riscv_th_vneg_v_i16m2(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i16> @test_vneg_v_i16m4
// CHECK-RV64-SAME: (<vscale x 16 x i16> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i16> @llvm.riscv.th.vrsub.nxv16i16.i16.i64(<vscale x 16 x i16> poison, <vscale x 16 x i16> [[OP1]], i16 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x i16> [[TMP0]]
//
vint16m4_t test_vneg_v_i16m4(vint16m4_t op1, size_t vl) {
return __riscv_th_vneg_v_i16m4(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x i16> @test_vneg_v_i16m8
// CHECK-RV64-SAME: (<vscale x 32 x i16> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x i16> @llvm.riscv.th.vrsub.nxv32i16.i16.i64(<vscale x 32 x i16> poison, <vscale x 32 x i16> [[OP1]], i16 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 32 x i16> [[TMP0]]
//
vint16m8_t test_vneg_v_i16m8(vint16m8_t op1, size_t vl) {
return __riscv_th_vneg_v_i16m8(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x i32> @test_vneg_v_i32m1
// CHECK-RV64-SAME: (<vscale x 2 x i32> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x i32> @llvm.riscv.th.vrsub.nxv2i32.i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> [[OP1]], i32 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 2 x i32> [[TMP0]]
//
vint32m1_t test_vneg_v_i32m1(vint32m1_t op1, size_t vl) {
return __riscv_th_vneg_v_i32m1(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x i32> @test_vneg_v_i32m2
// CHECK-RV64-SAME: (<vscale x 4 x i32> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i32> @llvm.riscv.th.vrsub.nxv4i32.i32.i64(<vscale x 4 x i32> poison, <vscale x 4 x i32> [[OP1]], i32 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x i32> [[TMP0]]
//
vint32m2_t test_vneg_v_i32m2(vint32m2_t op1, size_t vl) {
return __riscv_th_vneg_v_i32m2(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x i32> @test_vneg_v_i32m4
// CHECK-RV64-SAME: (<vscale x 8 x i32> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i32> @llvm.riscv.th.vrsub.nxv8i32.i32.i64(<vscale x 8 x i32> poison, <vscale x 8 x i32> [[OP1]], i32 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x i32> [[TMP0]]
//
vint32m4_t test_vneg_v_i32m4(vint32m4_t op1, size_t vl) {
return __riscv_th_vneg_v_i32m4(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vneg_v_i32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.th.vrsub.nxv16i32.i32.i64(<vscale x 16 x i32> poison, <vscale x 16 x i32> [[OP1]], i32 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vint32m8_t test_vneg_v_i32m8(vint32m8_t op1, size_t vl) {
return __riscv_th_vneg_v_i32m8(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x i64> @test_vneg_v_i64m1
// CHECK-RV64-SAME: (<vscale x 1 x i64> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x i64> @llvm.riscv.th.vrsub.nxv1i64.i64.i64(<vscale x 1 x i64> poison, <vscale x 1 x i64> [[OP1]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 1 x i64> [[TMP0]]
//
vint64m1_t test_vneg_v_i64m1(vint64m1_t op1, size_t vl) {
return __riscv_th_vneg_v_i64m1(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x i64> @test_vneg_v_i64m2
// CHECK-RV64-SAME: (<vscale x 2 x i64> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x i64> @llvm.riscv.th.vrsub.nxv2i64.i64.i64(<vscale x 2 x i64> poison, <vscale x 2 x i64> [[OP1]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 2 x i64> [[TMP0]]
//
vint64m2_t test_vneg_v_i64m2(vint64m2_t op1, size_t vl) {
return __riscv_th_vneg_v_i64m2(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x i64> @test_vneg_v_i64m4
// CHECK-RV64-SAME: (<vscale x 4 x i64> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x i64> @llvm.riscv.th.vrsub.nxv4i64.i64.i64(<vscale x 4 x i64> poison, <vscale x 4 x i64> [[OP1]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x i64> [[TMP0]]
//
vint64m4_t test_vneg_v_i64m4(vint64m4_t op1, size_t vl) {
return __riscv_th_vneg_v_i64m4(op1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x i64> @test_vneg_v_i64m8
// CHECK-RV64-SAME: (<vscale x 8 x i64> [[OP1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i64> @llvm.riscv.th.vrsub.nxv8i64.i64.i64(<vscale x 8 x i64> poison, <vscale x 8 x i64> [[OP1]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x i64> [[TMP0]]
//
vint64m8_t test_vneg_v_i64m8(vint64m8_t op1, size_t vl) {
return __riscv_th_vneg_v_i64m8(op1, vl);
}
Loading

0 comments on commit d9c904f

Please sign in to comment.