Skip to content

Commit 6518c41

Browse files
authored
[LLVM][XTHeadVector] Implement 16.2-16.6 vmpopc/vmfirst/vmsbf/vmsif/vmsof (llvm#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`
1 parent 46ecdfa commit 6518c41

File tree

7 files changed

+1423
-0
lines changed

7 files changed

+1423
-0
lines changed

llvm/include/llvm/IR/IntrinsicsRISCVXTHeadV.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,4 +910,15 @@ let TargetPrefix = "riscv" in {
910910
def int_riscv_th_vmclr : RISCVNullaryIntrinsic;
911911
def int_riscv_th_vmset : RISCVNullaryIntrinsic;
912912

913+
// 16.2. Vector mask population count vpopc
914+
defm th_vmpopc : RISCVMaskedUnarySOut;
915+
// 16.3. vfirst find-first-set mask bit
916+
defm th_vmfirst : RISCVMaskedUnarySOut;
917+
// 16.4. vmsbf.m set-before-first mask bit
918+
defm th_vmsbf : RISCVMaskedUnaryMOut;
919+
// 16.5. vmsif.m set-including-first mask bit
920+
defm th_vmsif : RISCVMaskedUnaryMOut;
921+
// 16.6. vmsof.m set-only-first mask bit
922+
defm th_vmsof : RISCVMaskedUnaryMOut;
923+
913924
} // TargetPrefix = "riscv"

llvm/lib/Target/RISCV/RISCVInstrInfoXTHeadVPseudos.td

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,19 @@ class XVPseudoTiedBinaryMaskRoundingMode<VReg RetClass,
17441744
let UsesVXRM = 0;
17451745
}
17461746

1747+
class XVPseudoUnaryMask<VReg RetClass, VReg OpClass, string Constraint = ""> :
1748+
Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd),
1749+
(ins GetVRegNoV0<RetClass>.R:$merge, OpClass:$rs2,
1750+
VMaskOp:$vm, AVL:$vl, ixlenimm:$sew), []>,
1751+
RISCVVPseudo {
1752+
let mayLoad = 0;
1753+
let mayStore = 0;
1754+
let hasSideEffects = 0;
1755+
let Constraints = !interleave([Constraint, "$rd = $merge"], ",");
1756+
let HasVLOp = 1;
1757+
let HasSEWOp = 1;
1758+
}
1759+
17471760
multiclass XVPseudoBinary<VReg RetClass,
17481761
VReg Op1Class,
17491762
DAGOperand Op2Class,
@@ -2517,6 +2530,49 @@ multiclass XVPseudoVALU_MM {
25172530
}
25182531
}
25192532

2533+
multiclass XVPseudoVPOP_M {
2534+
foreach mti = AllXMasks in {
2535+
defvar mx = mti.LMul.MX;
2536+
defvar WriteVMPopV_MX = !cast<SchedWrite>("WriteVMPopV_" # mx);
2537+
defvar ReadVMPopV_MX = !cast<SchedRead>("ReadVMPopV_" # mx);
2538+
let VLMul = mti.LMul.value in {
2539+
def "_M_" # mti.BX : VPseudoUnaryNoMaskGPROut,
2540+
Sched<[WriteVMPopV_MX, ReadVMPopV_MX, ReadVMPopV_MX]>;
2541+
def "_M_" # mti.BX # "_MASK" : VPseudoUnaryMaskGPROut,
2542+
Sched<[WriteVMPopV_MX, ReadVMPopV_MX, ReadVMPopV_MX]>;
2543+
}
2544+
}
2545+
}
2546+
2547+
multiclass XVPseudoV1ST_M {
2548+
foreach mti = AllXMasks in {
2549+
defvar mx = mti.LMul.MX;
2550+
defvar WriteVMFFSV_MX = !cast<SchedWrite>("WriteVMFFSV_" # mx);
2551+
defvar ReadVMFFSV_MX = !cast<SchedRead>("ReadVMFFSV_" # mx);
2552+
let VLMul = mti.LMul.value in {
2553+
def "_M_" # mti.BX : VPseudoUnaryNoMaskGPROut,
2554+
Sched<[WriteVMFFSV_MX, ReadVMFFSV_MX, ReadVMFFSV_MX]>;
2555+
def "_M_" # mti.BX # "_MASK" : VPseudoUnaryMaskGPROut,
2556+
Sched<[WriteVMFFSV_MX, ReadVMFFSV_MX, ReadVMFFSV_MX]>;
2557+
}
2558+
}
2559+
}
2560+
2561+
multiclass XVPseudoVSFS_M {
2562+
defvar constraint = "@earlyclobber $rd";
2563+
foreach mti = AllXMasks in {
2564+
defvar mx = mti.LMul.MX;
2565+
defvar WriteVMSFSV_MX = !cast<SchedWrite>("WriteVMSFSV_" # mx);
2566+
defvar ReadVMSFSV_MX = !cast<SchedRead>("ReadVMSFSV_" # mx);
2567+
let VLMul = mti.LMul.value in {
2568+
def "_M_" # mti.BX : XVPseudoUnaryNoMask<VR, VR, constraint>,
2569+
Sched<[WriteVMSFSV_MX, ReadVMSFSV_MX, ReadVMask]>;
2570+
def "_M_" # mti.BX # "_MASK" : XVPseudoUnaryMask<VR, VR, constraint>,
2571+
Sched<[WriteVMSFSV_MX, ReadVMSFSV_MX, ReadVMask]>;
2572+
}
2573+
}
2574+
}
2575+
25202576
//===----------------------------------------------------------------------===//
25212577
// Helpers to define the intrinsic patterns for the XTHeadVector extension.
25222578
//===----------------------------------------------------------------------===//
@@ -2995,6 +3051,52 @@ multiclass XVPatNullaryM<string intrinsic, string inst> {
29953051
GPR:$vl, mti.Log2SEW)>;
29963052
}
29973053

3054+
multiclass XVPatUnaryS_M<string intrinsic_name,
3055+
string inst> {
3056+
foreach mti = AllXMasks in {
3057+
def : Pat<(XLenVT (!cast<Intrinsic>(intrinsic_name)
3058+
(mti.Mask VR:$rs1), VLOpFrag)),
3059+
(!cast<Instruction>(inst#"_M_"#mti.BX) $rs1,
3060+
GPR:$vl, mti.Log2SEW)>;
3061+
def : Pat<(XLenVT (!cast<Intrinsic>(intrinsic_name # "_mask")
3062+
(mti.Mask VR:$rs1), (mti.Mask V0), VLOpFrag)),
3063+
(!cast<Instruction>(inst#"_M_"#mti.BX#"_MASK") $rs1,
3064+
(mti.Mask V0), GPR:$vl, mti.Log2SEW)>;
3065+
}
3066+
}
3067+
3068+
class XVPatMaskUnaryNoMask<string intrinsic_name,
3069+
string inst,
3070+
MTypeInfo mti> :
3071+
Pat<(mti.Mask (!cast<Intrinsic>(intrinsic_name)
3072+
(mti.Mask VR:$rs2),
3073+
VLOpFrag)),
3074+
(!cast<Instruction>(inst#"_M_"#mti.BX)
3075+
(mti.Mask (IMPLICIT_DEF)),
3076+
(mti.Mask VR:$rs2),
3077+
GPR:$vl, mti.Log2SEW)>;
3078+
3079+
class XVPatMaskUnaryMask<string intrinsic_name,
3080+
string inst,
3081+
MTypeInfo mti> :
3082+
Pat<(mti.Mask (!cast<Intrinsic>(intrinsic_name#"_mask")
3083+
(mti.Mask VR:$merge),
3084+
(mti.Mask VR:$rs2),
3085+
(mti.Mask V0),
3086+
VLOpFrag)),
3087+
(!cast<Instruction>(inst#"_M_"#mti.BX#"_MASK")
3088+
(mti.Mask VR:$merge),
3089+
(mti.Mask VR:$rs2),
3090+
(mti.Mask V0), GPR:$vl, mti.Log2SEW)>;
3091+
3092+
multiclass XVPatUnaryM_M<string intrinsic,
3093+
string inst> {
3094+
foreach mti = AllXMasks in {
3095+
def : XVPatMaskUnaryNoMask<intrinsic, inst, mti>;
3096+
def : XVPatMaskUnaryMask<intrinsic, inst, mti>;
3097+
}
3098+
}
3099+
29983100
multiclass XVPatCompare_VI<string intrinsic, string inst,
29993101
ImmLeaf ImmType> {
30003102
foreach vti = AllIntegerXVectors in {
@@ -3911,4 +4013,25 @@ let Predicates = [HasVendorXTHeadV] in {
39114013
defm : XVPatNullaryM<"int_riscv_th_vmset", "PseudoTH_VMSET">;
39124014
}
39134015

4016+
//===----------------------------------------------------------------------===//
4017+
// 16.2. Vector mask population count vpopc
4018+
// 16.3. vfirst find-first-set mask bit
4019+
// 16.4. vmsbf.m set-before-first mask bit
4020+
// 16.5. vmsif.m set-including-first mask bit
4021+
// 16.6. vmsof.m set-only-first mask bit
4022+
//===----------------------------------------------------------------------===//
4023+
4024+
defm PseudoTH_VMPOPC: XVPseudoVPOP_M;
4025+
defm PseudoTH_VMFIRST: XVPseudoV1ST_M;
4026+
defm PseudoTH_VMSBF: XVPseudoVSFS_M;
4027+
defm PseudoTH_VMSIF: XVPseudoVSFS_M;
4028+
defm PseudoTH_VMSOF: XVPseudoVSFS_M;
4029+
4030+
// Patterns
4031+
defm : XVPatUnaryS_M<"int_riscv_th_vmpopc", "PseudoTH_VMPOPC">;
4032+
defm : XVPatUnaryS_M<"int_riscv_th_vmfirst", "PseudoTH_VMFIRST">;
4033+
defm : XVPatUnaryM_M<"int_riscv_th_vmsbf", "PseudoTH_VMSBF">;
4034+
defm : XVPatUnaryM_M<"int_riscv_th_vmsif", "PseudoTH_VMSIF">;
4035+
defm : XVPatUnaryM_M<"int_riscv_th_vmsof", "PseudoTH_VMSOF">;
4036+
39144037
include "RISCVInstrInfoXTHeadVVLPatterns.td"
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+xtheadvector \
3+
; RUN: -verify-machineinstrs | FileCheck %s
4+
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+xtheadvector \
5+
; RUN: -verify-machineinstrs | FileCheck %s
6+
7+
declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv8i1(
8+
<vscale x 8 x i1>,
9+
iXLen);
10+
11+
define iXLen @intrinsic_vmfirst_m_nxv8i1(<vscale x 8 x i1> %0, iXLen %1) nounwind {
12+
; CHECK-LABEL: intrinsic_vmfirst_m_nxv8i1:
13+
; CHECK: # %bb.0: # %entry
14+
; CHECK-NEXT: csrr a1, vl
15+
; CHECK-NEXT: csrr a2, vtype
16+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
17+
; CHECK-NEXT: th.vsetvl zero, a1, a2
18+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m1, d1
19+
; CHECK-NEXT: th.vmfirst.m a0, v0
20+
; CHECK-NEXT: ret
21+
entry:
22+
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv8i1(
23+
<vscale x 8 x i1> %0,
24+
iXLen %1)
25+
26+
ret iXLen %a
27+
}
28+
29+
declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv8i1(
30+
<vscale x 8 x i1>,
31+
<vscale x 8 x i1>,
32+
iXLen);
33+
34+
define iXLen @intrinsic_vmfirst_mask_m_nxv8i1(<vscale x 8 x i1> %0, <vscale x 8 x i1> %1, iXLen %2) nounwind {
35+
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv8i1:
36+
; CHECK: # %bb.0: # %entry
37+
; CHECK-NEXT: csrr a1, vl
38+
; CHECK-NEXT: csrr a2, vtype
39+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
40+
; CHECK-NEXT: th.vsetvl zero, a1, a2
41+
; CHECK-NEXT: csrr a1, vl
42+
; CHECK-NEXT: csrr a2, vtype
43+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
44+
; CHECK-NEXT: th.vmv.v.v v9, v0
45+
; CHECK-NEXT: th.vsetvl zero, a1, a2
46+
; CHECK-NEXT: csrr a1, vl
47+
; CHECK-NEXT: csrr a2, vtype
48+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
49+
; CHECK-NEXT: th.vmv.v.v v0, v8
50+
; CHECK-NEXT: th.vsetvl zero, a1, a2
51+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m1, d1
52+
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
53+
; CHECK-NEXT: ret
54+
entry:
55+
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv8i1(
56+
<vscale x 8 x i1> %0,
57+
<vscale x 8 x i1> %1,
58+
iXLen %2)
59+
60+
ret iXLen %a
61+
}
62+
63+
declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv16i1(
64+
<vscale x 16 x i1>,
65+
iXLen);
66+
67+
define iXLen @intrinsic_vmfirst_m_nxv16i1(<vscale x 16 x i1> %0, iXLen %1) nounwind {
68+
; CHECK-LABEL: intrinsic_vmfirst_m_nxv16i1:
69+
; CHECK: # %bb.0: # %entry
70+
; CHECK-NEXT: csrr a1, vl
71+
; CHECK-NEXT: csrr a2, vtype
72+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
73+
; CHECK-NEXT: th.vsetvl zero, a1, a2
74+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m2, d1
75+
; CHECK-NEXT: th.vmfirst.m a0, v0
76+
; CHECK-NEXT: ret
77+
entry:
78+
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv16i1(
79+
<vscale x 16 x i1> %0,
80+
iXLen %1)
81+
82+
ret iXLen %a
83+
}
84+
85+
declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv16i1(
86+
<vscale x 16 x i1>,
87+
<vscale x 16 x i1>,
88+
iXLen);
89+
90+
define iXLen @intrinsic_vmfirst_mask_m_nxv16i1(<vscale x 16 x i1> %0, <vscale x 16 x i1> %1, iXLen %2) nounwind {
91+
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv16i1:
92+
; CHECK: # %bb.0: # %entry
93+
; CHECK-NEXT: csrr a1, vl
94+
; CHECK-NEXT: csrr a2, vtype
95+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
96+
; CHECK-NEXT: th.vsetvl zero, a1, a2
97+
; CHECK-NEXT: csrr a1, vl
98+
; CHECK-NEXT: csrr a2, vtype
99+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
100+
; CHECK-NEXT: th.vmv.v.v v9, v0
101+
; CHECK-NEXT: th.vsetvl zero, a1, a2
102+
; CHECK-NEXT: csrr a1, vl
103+
; CHECK-NEXT: csrr a2, vtype
104+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
105+
; CHECK-NEXT: th.vmv.v.v v0, v8
106+
; CHECK-NEXT: th.vsetvl zero, a1, a2
107+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m2, d1
108+
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
109+
; CHECK-NEXT: ret
110+
entry:
111+
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv16i1(
112+
<vscale x 16 x i1> %0,
113+
<vscale x 16 x i1> %1,
114+
iXLen %2)
115+
116+
ret iXLen %a
117+
}
118+
119+
declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv32i1(
120+
<vscale x 32 x i1>,
121+
iXLen);
122+
123+
define iXLen @intrinsic_vmfirst_m_nxv32i1(<vscale x 32 x i1> %0, iXLen %1) nounwind {
124+
; CHECK-LABEL: intrinsic_vmfirst_m_nxv32i1:
125+
; CHECK: # %bb.0: # %entry
126+
; CHECK-NEXT: csrr a1, vl
127+
; CHECK-NEXT: csrr a2, vtype
128+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
129+
; CHECK-NEXT: th.vsetvl zero, a1, a2
130+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m4, d1
131+
; CHECK-NEXT: th.vmfirst.m a0, v0
132+
; CHECK-NEXT: ret
133+
entry:
134+
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv32i1(
135+
<vscale x 32 x i1> %0,
136+
iXLen %1)
137+
138+
ret iXLen %a
139+
}
140+
141+
declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv32i1(
142+
<vscale x 32 x i1>,
143+
<vscale x 32 x i1>,
144+
iXLen);
145+
146+
define iXLen @intrinsic_vmfirst_mask_m_nxv32i1(<vscale x 32 x i1> %0, <vscale x 32 x i1> %1, iXLen %2) nounwind {
147+
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv32i1:
148+
; CHECK: # %bb.0: # %entry
149+
; CHECK-NEXT: csrr a1, vl
150+
; CHECK-NEXT: csrr a2, vtype
151+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
152+
; CHECK-NEXT: th.vsetvl zero, a1, a2
153+
; CHECK-NEXT: csrr a1, vl
154+
; CHECK-NEXT: csrr a2, vtype
155+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
156+
; CHECK-NEXT: th.vmv.v.v v9, v0
157+
; CHECK-NEXT: th.vsetvl zero, a1, a2
158+
; CHECK-NEXT: csrr a1, vl
159+
; CHECK-NEXT: csrr a2, vtype
160+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
161+
; CHECK-NEXT: th.vmv.v.v v0, v8
162+
; CHECK-NEXT: th.vsetvl zero, a1, a2
163+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m4, d1
164+
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
165+
; CHECK-NEXT: ret
166+
entry:
167+
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv32i1(
168+
<vscale x 32 x i1> %0,
169+
<vscale x 32 x i1> %1,
170+
iXLen %2)
171+
172+
ret iXLen %a
173+
}
174+
175+
declare iXLen @llvm.riscv.th.vmfirst.iXLen.nxv64i1(
176+
<vscale x 64 x i1>,
177+
iXLen);
178+
179+
define iXLen @intrinsic_vmfirst_m_nxv64i1(<vscale x 64 x i1> %0, iXLen %1) nounwind {
180+
; CHECK-LABEL: intrinsic_vmfirst_m_nxv64i1:
181+
; CHECK: # %bb.0: # %entry
182+
; CHECK-NEXT: csrr a1, vl
183+
; CHECK-NEXT: csrr a2, vtype
184+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
185+
; CHECK-NEXT: th.vsetvl zero, a1, a2
186+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m8, d1
187+
; CHECK-NEXT: th.vmfirst.m a0, v0
188+
; CHECK-NEXT: ret
189+
entry:
190+
%a = call iXLen @llvm.riscv.th.vmfirst.iXLen.nxv64i1(
191+
<vscale x 64 x i1> %0,
192+
iXLen %1)
193+
194+
ret iXLen %a
195+
}
196+
197+
declare iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv64i1(
198+
<vscale x 64 x i1>,
199+
<vscale x 64 x i1>,
200+
iXLen);
201+
202+
define iXLen @intrinsic_vmfirst_mask_m_nxv64i1(<vscale x 64 x i1> %0, <vscale x 64 x i1> %1, iXLen %2) nounwind {
203+
; CHECK-LABEL: intrinsic_vmfirst_mask_m_nxv64i1:
204+
; CHECK: # %bb.0: # %entry
205+
; CHECK-NEXT: csrr a1, vl
206+
; CHECK-NEXT: csrr a2, vtype
207+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
208+
; CHECK-NEXT: th.vsetvl zero, a1, a2
209+
; CHECK-NEXT: csrr a1, vl
210+
; CHECK-NEXT: csrr a2, vtype
211+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
212+
; CHECK-NEXT: th.vmv.v.v v9, v0
213+
; CHECK-NEXT: th.vsetvl zero, a1, a2
214+
; CHECK-NEXT: csrr a1, vl
215+
; CHECK-NEXT: csrr a2, vtype
216+
; CHECK-NEXT: th.vsetvli zero, zero, e8, m1, d1
217+
; CHECK-NEXT: th.vmv.v.v v0, v8
218+
; CHECK-NEXT: th.vsetvl zero, a1, a2
219+
; CHECK-NEXT: th.vsetvli zero, a0, e8, m8, d1
220+
; CHECK-NEXT: th.vmfirst.m a0, v9, v0.t
221+
; CHECK-NEXT: ret
222+
entry:
223+
%a = call iXLen @llvm.riscv.th.vmfirst.mask.iXLen.nxv64i1(
224+
<vscale x 64 x i1> %0,
225+
<vscale x 64 x i1> %1,
226+
iXLen %2)
227+
228+
ret iXLen %a
229+
}

0 commit comments

Comments
 (0)