Skip to content

Commit

Permalink
[LLVM][XTHeadVector] Implement 16.2-16.6 `vmpopc/vmfirst/vmsbf/vmsif/…
Browse files Browse the repository at this point in the history
…vmsof` (#97)

* [LLVM][XTHeadVector] Implement 16.2-16.6 `vmpopc/vmfirst/vmsbf/vmsif/vmsof`

* [LLVM][XTHeadVector] Test 16.2~16.6 `vmpopc/vmfirst/vmsbf/vmsif/vmsof`
  • Loading branch information
imkiva authored Apr 11, 2024
1 parent 46ecdfa commit 6518c41
Show file tree
Hide file tree
Showing 7 changed files with 1,423 additions and 0 deletions.
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsRISCVXTHeadV.td
Original file line number Diff line number Diff line change
Expand Up @@ -910,4 +910,15 @@ let TargetPrefix = "riscv" in {
def int_riscv_th_vmclr : RISCVNullaryIntrinsic;
def int_riscv_th_vmset : RISCVNullaryIntrinsic;

// 16.2. Vector mask population count vpopc
defm th_vmpopc : RISCVMaskedUnarySOut;
// 16.3. vfirst find-first-set mask bit
defm th_vmfirst : RISCVMaskedUnarySOut;
// 16.4. vmsbf.m set-before-first mask bit
defm th_vmsbf : RISCVMaskedUnaryMOut;
// 16.5. vmsif.m set-including-first mask bit
defm th_vmsif : RISCVMaskedUnaryMOut;
// 16.6. vmsof.m set-only-first mask bit
defm th_vmsof : RISCVMaskedUnaryMOut;

} // TargetPrefix = "riscv"
123 changes: 123 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXTHeadVPseudos.td
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,19 @@ class XVPseudoTiedBinaryMaskRoundingMode<VReg RetClass,
let UsesVXRM = 0;
}

class XVPseudoUnaryMask<VReg RetClass, VReg OpClass, string Constraint = ""> :
Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd),
(ins GetVRegNoV0<RetClass>.R:$merge, OpClass:$rs2,
VMaskOp:$vm, AVL:$vl, ixlenimm:$sew), []>,
RISCVVPseudo {
let mayLoad = 0;
let mayStore = 0;
let hasSideEffects = 0;
let Constraints = !interleave([Constraint, "$rd = $merge"], ",");
let HasVLOp = 1;
let HasSEWOp = 1;
}

multiclass XVPseudoBinary<VReg RetClass,
VReg Op1Class,
DAGOperand Op2Class,
Expand Down Expand Up @@ -2517,6 +2530,49 @@ multiclass XVPseudoVALU_MM {
}
}

multiclass XVPseudoVPOP_M {
foreach mti = AllXMasks in {
defvar mx = mti.LMul.MX;
defvar WriteVMPopV_MX = !cast<SchedWrite>("WriteVMPopV_" # mx);
defvar ReadVMPopV_MX = !cast<SchedRead>("ReadVMPopV_" # mx);
let VLMul = mti.LMul.value in {
def "_M_" # mti.BX : VPseudoUnaryNoMaskGPROut,
Sched<[WriteVMPopV_MX, ReadVMPopV_MX, ReadVMPopV_MX]>;
def "_M_" # mti.BX # "_MASK" : VPseudoUnaryMaskGPROut,
Sched<[WriteVMPopV_MX, ReadVMPopV_MX, ReadVMPopV_MX]>;
}
}
}

multiclass XVPseudoV1ST_M {
foreach mti = AllXMasks in {
defvar mx = mti.LMul.MX;
defvar WriteVMFFSV_MX = !cast<SchedWrite>("WriteVMFFSV_" # mx);
defvar ReadVMFFSV_MX = !cast<SchedRead>("ReadVMFFSV_" # mx);
let VLMul = mti.LMul.value in {
def "_M_" # mti.BX : VPseudoUnaryNoMaskGPROut,
Sched<[WriteVMFFSV_MX, ReadVMFFSV_MX, ReadVMFFSV_MX]>;
def "_M_" # mti.BX # "_MASK" : VPseudoUnaryMaskGPROut,
Sched<[WriteVMFFSV_MX, ReadVMFFSV_MX, ReadVMFFSV_MX]>;
}
}
}

multiclass XVPseudoVSFS_M {
defvar constraint = "@earlyclobber $rd";
foreach mti = AllXMasks in {
defvar mx = mti.LMul.MX;
defvar WriteVMSFSV_MX = !cast<SchedWrite>("WriteVMSFSV_" # mx);
defvar ReadVMSFSV_MX = !cast<SchedRead>("ReadVMSFSV_" # mx);
let VLMul = mti.LMul.value in {
def "_M_" # mti.BX : XVPseudoUnaryNoMask<VR, VR, constraint>,
Sched<[WriteVMSFSV_MX, ReadVMSFSV_MX, ReadVMask]>;
def "_M_" # mti.BX # "_MASK" : XVPseudoUnaryMask<VR, VR, constraint>,
Sched<[WriteVMSFSV_MX, ReadVMSFSV_MX, ReadVMask]>;
}
}
}

//===----------------------------------------------------------------------===//
// Helpers to define the intrinsic patterns for the XTHeadVector extension.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2995,6 +3051,52 @@ multiclass XVPatNullaryM<string intrinsic, string inst> {
GPR:$vl, mti.Log2SEW)>;
}

multiclass XVPatUnaryS_M<string intrinsic_name,
string inst> {
foreach mti = AllXMasks in {
def : Pat<(XLenVT (!cast<Intrinsic>(intrinsic_name)
(mti.Mask VR:$rs1), VLOpFrag)),
(!cast<Instruction>(inst#"_M_"#mti.BX) $rs1,
GPR:$vl, mti.Log2SEW)>;
def : Pat<(XLenVT (!cast<Intrinsic>(intrinsic_name # "_mask")
(mti.Mask VR:$rs1), (mti.Mask V0), VLOpFrag)),
(!cast<Instruction>(inst#"_M_"#mti.BX#"_MASK") $rs1,
(mti.Mask V0), GPR:$vl, mti.Log2SEW)>;
}
}

class XVPatMaskUnaryNoMask<string intrinsic_name,
string inst,
MTypeInfo mti> :
Pat<(mti.Mask (!cast<Intrinsic>(intrinsic_name)
(mti.Mask VR:$rs2),
VLOpFrag)),
(!cast<Instruction>(inst#"_M_"#mti.BX)
(mti.Mask (IMPLICIT_DEF)),
(mti.Mask VR:$rs2),
GPR:$vl, mti.Log2SEW)>;

class XVPatMaskUnaryMask<string intrinsic_name,
string inst,
MTypeInfo mti> :
Pat<(mti.Mask (!cast<Intrinsic>(intrinsic_name#"_mask")
(mti.Mask VR:$merge),
(mti.Mask VR:$rs2),
(mti.Mask V0),
VLOpFrag)),
(!cast<Instruction>(inst#"_M_"#mti.BX#"_MASK")
(mti.Mask VR:$merge),
(mti.Mask VR:$rs2),
(mti.Mask V0), GPR:$vl, mti.Log2SEW)>;

multiclass XVPatUnaryM_M<string intrinsic,
string inst> {
foreach mti = AllXMasks in {
def : XVPatMaskUnaryNoMask<intrinsic, inst, mti>;
def : XVPatMaskUnaryMask<intrinsic, inst, mti>;
}
}

multiclass XVPatCompare_VI<string intrinsic, string inst,
ImmLeaf ImmType> {
foreach vti = AllIntegerXVectors in {
Expand Down Expand Up @@ -3911,4 +4013,25 @@ let Predicates = [HasVendorXTHeadV] in {
defm : XVPatNullaryM<"int_riscv_th_vmset", "PseudoTH_VMSET">;
}

//===----------------------------------------------------------------------===//
// 16.2. Vector mask population count vpopc
// 16.3. vfirst find-first-set mask bit
// 16.4. vmsbf.m set-before-first mask bit
// 16.5. vmsif.m set-including-first mask bit
// 16.6. vmsof.m set-only-first mask bit
//===----------------------------------------------------------------------===//

defm PseudoTH_VMPOPC: XVPseudoVPOP_M;
defm PseudoTH_VMFIRST: XVPseudoV1ST_M;
defm PseudoTH_VMSBF: XVPseudoVSFS_M;
defm PseudoTH_VMSIF: XVPseudoVSFS_M;
defm PseudoTH_VMSOF: XVPseudoVSFS_M;

// Patterns
defm : XVPatUnaryS_M<"int_riscv_th_vmpopc", "PseudoTH_VMPOPC">;
defm : XVPatUnaryS_M<"int_riscv_th_vmfirst", "PseudoTH_VMFIRST">;
defm : XVPatUnaryM_M<"int_riscv_th_vmsbf", "PseudoTH_VMSBF">;
defm : XVPatUnaryM_M<"int_riscv_th_vmsif", "PseudoTH_VMSIF">;
defm : XVPatUnaryM_M<"int_riscv_th_vmsof", "PseudoTH_VMSOF">;

include "RISCVInstrInfoXTHeadVVLPatterns.td"
229 changes: 229 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv0p71/vmfirst.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+xtheadvector \
; RUN: -verify-machineinstrs | FileCheck %s
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+xtheadvector \
; RUN: -verify-machineinstrs | FileCheck %s

declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv8i1(
<vscale x 8 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_m_nxv8i1(<vscale x 8 x i1> %0, iXLen %1) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_m_nxv8i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m1, d1
; CHECK-NEXT: th.vmfirst.m a0, v0
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv8i1(
<vscale x 8 x i1> %0,
iXLen %1)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv8i1(
<vscale x 8 x i1>,
<vscale x 8 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_mask_m_nxv8i1(<vscale x 8 x i1> %0, <vscale x 8 x i1> %1, iXLen %2) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv8i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v9, v0
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v0, v8
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m1, d1
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv8i1(
<vscale x 8 x i1> %0,
<vscale x 8 x i1> %1,
iXLen %2)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv16i1(
<vscale x 16 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_m_nxv16i1(<vscale x 16 x i1> %0, iXLen %1) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_m_nxv16i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m2, d1
; CHECK-NEXT: th.vmfirst.m a0, v0
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv16i1(
<vscale x 16 x i1> %0,
iXLen %1)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv16i1(
<vscale x 16 x i1>,
<vscale x 16 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_mask_m_nxv16i1(<vscale x 16 x i1> %0, <vscale x 16 x i1> %1, iXLen %2) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv16i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v9, v0
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v0, v8
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m2, d1
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv16i1(
<vscale x 16 x i1> %0,
<vscale x 16 x i1> %1,
iXLen %2)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv32i1(
<vscale x 32 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_m_nxv32i1(<vscale x 32 x i1> %0, iXLen %1) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_m_nxv32i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m4, d1
; CHECK-NEXT: th.vmfirst.m a0, v0
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv32i1(
<vscale x 32 x i1> %0,
iXLen %1)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv32i1(
<vscale x 32 x i1>,
<vscale x 32 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_mask_m_nxv32i1(<vscale x 32 x i1> %0, <vscale x 32 x i1> %1, iXLen %2) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv32i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v9, v0
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v0, v8
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m4, d1
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv32i1(
<vscale x 32 x i1> %0,
<vscale x 32 x i1> %1,
iXLen %2)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv64i1(
<vscale x 64 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_m_nxv64i1(<vscale x 64 x i1> %0, iXLen %1) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_m_nxv64i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m8, d1
; CHECK-NEXT: th.vmfirst.m a0, v0
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv64i1(
<vscale x 64 x i1> %0,
iXLen %1)

ret iXLen %a
}

declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv64i1(
<vscale x 64 x i1>,
<vscale x 64 x i1>,
iXLen);

define iXLen @intrinsic_vmfirst_mask_m_nxv64i1(<vscale x 64 x i1> %0, <vscale x 64 x i1> %1, iXLen %2) nounwind {
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv64i1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v9, v0
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: csrr a1, vl
; CHECK-NEXT: csrr a2, vtype
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
; CHECK-NEXT: th.vmv.v.v v0, v8
; CHECK-NEXT: th.vsetvl zero, a1, a2
; CHECK-NEXT: th.vsetvli zero, a0, e8, m8, d1
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
; CHECK-NEXT: ret
entry:
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv64i1(
<vscale x 64 x i1> %0,
<vscale x 64 x i1> %1,
iXLen %2)

ret iXLen %a
}
Loading

0 comments on commit 6518c41

Please sign in to comment.