[RISCV] Define vlxe/vsxe/vsuxe intrinsics.

Define vlxe/vsxe intrinsics and lower to vlxei<EEW>/vsxei<EEW>
instructions.

We work with @rogfer01 from BSC to come out this patch.

Authored-by: Roger Ferrer Ibanez <rofirrim@gmail.com>
Co-Authored-by: Zakk Chen <zakk.chen@sifive.com>

Differential Revision: https://reviews.llvm.org/D93471
This commit is contained in:
Zakk Chen 2020-12-17 09:30:03 -08:00
parent 9c895aea11
commit 9cf3b1b666
8 changed files with 27030 additions and 1 deletions

View File

@ -125,6 +125,21 @@ let TargetPrefix = "riscv" in {
LLVMPointerType<LLVMMatchType<0>>, llvm_anyint_ty, LLVMPointerType<LLVMMatchType<0>>, llvm_anyint_ty,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>], LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>],
[NoCapture<ArgIndex<1>>, IntrReadMem]>, RISCVVIntrinsic; [NoCapture<ArgIndex<1>>, IntrReadMem]>, RISCVVIntrinsic;
// For indexed load
// Input: (pointer, index, vl)
class RISCVILoad
: Intrinsic<[llvm_anyvector_ty],
[LLVMPointerType<LLVMMatchType<0>>,
llvm_anyvector_ty, llvm_anyint_ty],
[NoCapture<ArgIndex<0>>, IntrReadMem]>, RISCVVIntrinsic;
// For indexed load with mask
// Input: (maskedoff, pointer, index, mask, vl)
class RISCVILoadMask
: Intrinsic<[llvm_anyvector_ty ],
[LLVMMatchType<0>,
LLVMPointerType<LLVMMatchType<0>>, llvm_anyvector_ty,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty],
[NoCapture<ArgIndex<1>>, IntrReadMem]>, RISCVVIntrinsic;
// For unit stride store // For unit stride store
// Input: (vector_in, pointer, vl) // Input: (vector_in, pointer, vl)
class RISCVUSStore class RISCVUSStore
@ -158,6 +173,22 @@ let TargetPrefix = "riscv" in {
LLVMPointerType<LLVMMatchType<0>>, llvm_anyint_ty, LLVMPointerType<LLVMMatchType<0>>, llvm_anyint_ty,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>], LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>],
[NoCapture<ArgIndex<1>>, IntrWriteMem]>, RISCVVIntrinsic; [NoCapture<ArgIndex<1>>, IntrWriteMem]>, RISCVVIntrinsic;
// For indexed store
// Input: (vector_in, pointer, index, vl)
class RISCVIStore
: Intrinsic<[],
[llvm_anyvector_ty,
LLVMPointerType<LLVMMatchType<0>>,
llvm_anyint_ty, llvm_anyint_ty],
[NoCapture<ArgIndex<1>>, IntrWriteMem]>, RISCVVIntrinsic;
// For indexed store with mask
// Input: (vector_in, pointer, index, mask, vl)
class RISCVIStoreMask
: Intrinsic<[],
[llvm_anyvector_ty,
LLVMPointerType<LLVMMatchType<0>>, llvm_anyvector_ty,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty],
[NoCapture<ArgIndex<1>>, IntrWriteMem]>, RISCVVIntrinsic;
// For destination vector type is the same as first source vector. // For destination vector type is the same as first source vector.
// Input: (vector_in, vector_in/scalar_in, vl) // Input: (vector_in, vector_in/scalar_in, vl)
class RISCVBinaryAAXNoMask class RISCVBinaryAAXNoMask
@ -260,6 +291,10 @@ let TargetPrefix = "riscv" in {
def "int_riscv_" # NAME : RISCVSLoad; def "int_riscv_" # NAME : RISCVSLoad;
def "int_riscv_" # NAME # "_mask" : RISCVSLoadMask; def "int_riscv_" # NAME # "_mask" : RISCVSLoadMask;
} }
multiclass RISCVILoad {
def "int_riscv_" # NAME : RISCVILoad;
def "int_riscv_" # NAME # "_mask" : RISCVILoadMask;
}
multiclass RISCVUSStore { multiclass RISCVUSStore {
def "int_riscv_" # NAME : RISCVUSStore; def "int_riscv_" # NAME : RISCVUSStore;
def "int_riscv_" # NAME # "_mask" : RISCVUSStoreMask; def "int_riscv_" # NAME # "_mask" : RISCVUSStoreMask;
@ -268,7 +303,10 @@ let TargetPrefix = "riscv" in {
def "int_riscv_" # NAME : RISCVSStore; def "int_riscv_" # NAME : RISCVSStore;
def "int_riscv_" # NAME # "_mask" : RISCVSStoreMask; def "int_riscv_" # NAME # "_mask" : RISCVSStoreMask;
} }
multiclass RISCVIStore {
def "int_riscv_" # NAME : RISCVIStore;
def "int_riscv_" # NAME # "_mask" : RISCVIStoreMask;
}
multiclass RISCVBinaryAAX { multiclass RISCVBinaryAAX {
def "int_riscv_" # NAME : RISCVBinaryAAXNoMask; def "int_riscv_" # NAME : RISCVBinaryAAXNoMask;
def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAXMask; def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAXMask;
@ -295,6 +333,9 @@ let TargetPrefix = "riscv" in {
defm vse : RISCVUSStore; defm vse : RISCVUSStore;
defm vlse: RISCVSLoad; defm vlse: RISCVSLoad;
defm vsse: RISCVSStore; defm vsse: RISCVSStore;
defm vlxe: RISCVILoad;
defm vsxe: RISCVIStore;
defm vsuxe: RISCVIStore;
defm vadd : RISCVBinaryAAX; defm vadd : RISCVBinaryAAX;
defm vsub : RISCVBinaryAAX; defm vsub : RISCVBinaryAAX;

View File

@ -347,6 +347,39 @@ class VPseudoSLoadMask<VReg RetClass>:
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
} }
class VPseudoILoadNoMask<VReg RetClass, VReg IdxClass>:
Pseudo<(outs RetClass:$rd),
(ins GPR:$rs1, IdxClass:$rs2, GPR:$vl, ixlenimm:$sew),[]>,
RISCVVPseudo {
let mayLoad = 1;
let mayStore = 0;
let hasSideEffects = 0;
let usesCustomInserter = 1;
let Uses = [VL, VTYPE];
let VLIndex = 3;
let SEWIndex = 4;
let HasDummyMask = 1;
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
}
class VPseudoILoadMask<VReg RetClass, VReg IdxClass>:
Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd),
(ins GetVRegNoV0<RetClass>.R:$merge,
GPR:$rs1, IdxClass:$rs2,
VMaskOp:$vm, GPR:$vl, ixlenimm:$sew),[]>,
RISCVVPseudo {
let mayLoad = 1;
let mayStore = 0;
let hasSideEffects = 0;
let usesCustomInserter = 1;
let Constraints = "$rd = $merge";
let Uses = [VL, VTYPE];
let VLIndex = 5;
let SEWIndex = 6;
let MergeOpIndex = 1;
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
}
class VPseudoUSStoreNoMask<VReg StClass>: class VPseudoUSStoreNoMask<VReg StClass>:
Pseudo<(outs), Pseudo<(outs),
(ins StClass:$rd, GPR:$rs1, GPR:$vl, ixlenimm:$sew),[]>, (ins StClass:$rd, GPR:$rs1, GPR:$vl, ixlenimm:$sew),[]>,
@ -440,6 +473,35 @@ class VPseudoBinaryNoMask<VReg RetClass,
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
} }
class VPseudoIStoreNoMask<VReg StClass, VReg IdxClass>:
Pseudo<(outs),
(ins StClass:$rd, GPR:$rs1, IdxClass:$rs2, GPR:$vl, ixlenimm:$sew),[]>,
RISCVVPseudo {
let mayLoad = 0;
let mayStore = 1;
let hasSideEffects = 0;
let usesCustomInserter = 1;
let Uses = [VL, VTYPE];
let VLIndex = 3;
let SEWIndex = 4;
let HasDummyMask = 1;
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
}
class VPseudoIStoreMask<VReg StClass, VReg IdxClass>:
Pseudo<(outs),
(ins StClass:$rd, GPR:$rs1, IdxClass:$rs2, VMaskOp:$vm, GPR:$vl, ixlenimm:$sew),[]>,
RISCVVPseudo {
let mayLoad = 0;
let mayStore = 1;
let hasSideEffects = 0;
let usesCustomInserter = 1;
let Uses = [VL, VTYPE];
let VLIndex = 4;
let SEWIndex = 5;
let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
}
class VPseudoBinaryMask<VReg RetClass, class VPseudoBinaryMask<VReg RetClass,
VReg Op1Class, VReg Op1Class,
DAGOperand Op2Class, DAGOperand Op2Class,
@ -508,6 +570,20 @@ multiclass VPseudoSLoad {
} }
} }
multiclass VPseudoILoad {
foreach lmul = MxList.m in
foreach idx_lmul = MxList.m in {
defvar LInfo = lmul.MX;
defvar Vreg = lmul.vrclass;
defvar IdxLInfo = idx_lmul.MX;
defvar IdxVreg = idx_lmul.vrclass;
let VLMul = lmul.value in {
def "_V_" # IdxLInfo # "_" # LInfo : VPseudoILoadNoMask<Vreg, IdxVreg>;
def "_V_" # IdxLInfo # "_" # LInfo # "_MASK" : VPseudoILoadMask<Vreg, IdxVreg>;
}
}
}
multiclass VPseudoUSStore { multiclass VPseudoUSStore {
foreach lmul = MxList.m in { foreach lmul = MxList.m in {
defvar LInfo = lmul.MX; defvar LInfo = lmul.MX;
@ -530,6 +606,20 @@ multiclass VPseudoSStore {
} }
} }
multiclass VPseudoIStore {
foreach lmul = MxList.m in
foreach idx_lmul = MxList.m in {
defvar LInfo = lmul.MX;
defvar Vreg = lmul.vrclass;
defvar IdxLInfo = idx_lmul.MX;
defvar IdxVreg = idx_lmul.vrclass;
let VLMul = lmul.value in {
def "_V_" # IdxLInfo # "_" # LInfo : VPseudoIStoreNoMask<Vreg, IdxVreg>;
def "_V_" # IdxLInfo # "_" # LInfo # "_MASK" : VPseudoIStoreMask<Vreg, IdxVreg>;
}
}
}
multiclass VPseudoBinary<VReg RetClass, multiclass VPseudoBinary<VReg RetClass,
VReg Op1Class, VReg Op1Class,
DAGOperand Op2Class, DAGOperand Op2Class,
@ -854,6 +944,31 @@ multiclass VPatSLoad<string intrinsic,
$rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>; $rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>;
} }
multiclass VPatILoad<string intrinsic,
string inst,
LLVMType type,
LLVMType idx_type,
LLVMType mask_type,
int sew,
LMULInfo vlmul,
LMULInfo idx_vlmul,
VReg reg_class,
VReg idx_reg_class>
{
defvar Intr = !cast<Intrinsic>(intrinsic);
defvar Pseudo = !cast<Instruction>(inst#"_V_"#idx_vlmul.MX#"_"#vlmul.MX);
def : Pat<(type (Intr GPR:$rs1, (idx_type idx_reg_class:$rs2), GPR:$vl)),
(Pseudo $rs1, $rs2, (NoX0 GPR:$vl), sew)>;
defvar IntrMask = !cast<Intrinsic>(intrinsic # "_mask");
defvar PseudoMask = !cast<Instruction>(inst#"_V_"#idx_vlmul.MX#"_"#vlmul.MX#"_MASK");
def : Pat<(type (IntrMask (type GetVRegNoV0<reg_class>.R:$merge),
GPR:$rs1, (idx_type idx_reg_class:$rs2),
(mask_type V0), GPR:$vl)),
(PseudoMask $merge,
$rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>;
}
multiclass VPatUSStore<string intrinsic, multiclass VPatUSStore<string intrinsic,
string inst, string inst,
LLVMType type, LLVMType type,
@ -890,6 +1005,29 @@ multiclass VPatSStore<string intrinsic,
(PseudoMask $rs3, $rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>; (PseudoMask $rs3, $rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>;
} }
multiclass VPatIStore<string intrinsic,
string inst,
LLVMType type,
LLVMType idx_type,
LLVMType mask_type,
int sew,
LMULInfo vlmul,
LMULInfo idx_vlmul,
VReg reg_class,
VReg idx_reg_class>
{
defvar Intr = !cast<Intrinsic>(intrinsic);
defvar Pseudo = !cast<Instruction>(inst#"_V_"#idx_vlmul.MX#"_"#vlmul.MX);
def : Pat<(Intr (type reg_class:$rs3), GPR:$rs1,
(idx_type idx_reg_class:$rs2), GPR:$vl),
(Pseudo $rs3, $rs1, $rs2, (NoX0 GPR:$vl), sew)>;
defvar IntrMask = !cast<Intrinsic>(intrinsic # "_mask");
defvar PseudoMask = !cast<Instruction>(inst#"_V_"#idx_vlmul.MX#"_"#vlmul.MX#"_MASK");
def : Pat<(IntrMask (type reg_class:$rs3), GPR:$rs1,
(idx_type idx_reg_class:$rs2), (mask_type V0), GPR:$vl),
(PseudoMask $rs3, $rs1, $rs2, (mask_type V0), (NoX0 GPR:$vl), sew)>;
}
multiclass VPatBinary<string intrinsic, multiclass VPatBinary<string intrinsic,
string inst, string inst,
string kind, string kind,
@ -1243,6 +1381,17 @@ foreach eew = EEWList in {
defm PseudoVSSE # eew : VPseudoSStore; defm PseudoVSSE # eew : VPseudoSStore;
} }
//===----------------------------------------------------------------------===//
// 7.6 Vector Indexed Instructions
//===----------------------------------------------------------------------===//
// Vector Indexed Loads and Stores
foreach eew = EEWList in {
defm PseudoVLXEI # eew : VPseudoILoad;
defm PseudoVSXEI # eew : VPseudoIStore;
defm PseudoVSUXEI # eew : VPseudoIStore;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Pseudo Instructions // Pseudo Instructions
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1448,6 +1597,55 @@ foreach vti = AllVectors in
vti.Vector, vti.Mask, vti.SEW, vti.LMul, vti.RegClass>; vti.Vector, vti.Mask, vti.SEW, vti.LMul, vti.RegClass>;
} }
//===----------------------------------------------------------------------===//
// 7.6 Vector Indexed Instructions
//===----------------------------------------------------------------------===//
foreach vti = AllVectors in
foreach eew = EEWList in {
defvar vlmul = vti.LMul;
defvar octuple_lmul = !cond(!eq(vti.LMul.MX, "MF8") : 1,
!eq(vti.LMul.MX, "MF4") : 2,
!eq(vti.LMul.MX, "MF2") : 4,
!eq(vti.LMul.MX, "M1") : 8,
!eq(vti.LMul.MX, "M2") : 16,
!eq(vti.LMul.MX, "M4") : 32,
!eq(vti.LMul.MX, "M8") : 64);
defvar log_sew = shift_amount<vti.SEW>.val;
// The data vector register group has EEW=SEW, EMUL=LMUL, while the offset
// vector register group has EEW encoding in the instruction and EMUL=(EEW/SEW)*LMUL.
// calculate octuple elmul which is (eew * octuple_lmul) >> log_sew
defvar octuple_elmul = !srl(!mul(eew, octuple_lmul), log_sew);
// legal octuple elmul should be more than 0 and less than equal 64
if !gt(octuple_elmul, 0) then {
if !le(octuple_elmul, 64) then {
defvar log_elmul = shift_amount<octuple_elmul>.val;
// 0, 1, 2 -> V_MF8 ~ V_MF2
// 3, 4, 5, 6 -> V_M1 ~ V_M8
defvar elmul_str = !if(!eq(log_elmul, 0), "MF8",
!if(!eq(log_elmul, 1), "MF4",
!if(!eq(log_elmul, 2), "MF2",
"M" # !cast<string>(!shl(1, !add(log_elmul, -3))))));
defvar elmul =!cast<LMULInfo>("V_" # elmul_str);
defvar idx_vti = !cast<VTypeInfo>("VI" # eew # elmul_str);
defm : VPatILoad<"int_riscv_vlxe",
"PseudoVLXEI"#eew,
vti.Vector, idx_vti.Vector, vti.Mask, vti.SEW,
vlmul, elmul, vti.RegClass, idx_vti.RegClass>;
defm : VPatIStore<"int_riscv_vsxe",
"PseudoVSXEI"#eew,
vti.Vector, idx_vti.Vector, vti.Mask, vti.SEW,
vlmul, elmul, vti.RegClass, idx_vti.RegClass>;
defm : VPatIStore<"int_riscv_vsuxe",
"PseudoVSUXEI"#eew,
vti.Vector, idx_vti.Vector, vti.Mask, vti.SEW,
vlmul, elmul, vti.RegClass, idx_vti.RegClass>;
}
}
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// 12. Vector Integer Arithmetic Instructions // 12. Vector Integer Arithmetic Instructions
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff