|
@@ -0,0 +1,1278 @@
|
|
|
+From 29318f779da9c962af60d574b19159ecc10cfdd7 Mon Sep 17 00:00:00 2001
|
|
|
+From: Eric Tang <eric.tang@starfivetech.com>
|
|
|
+Date: Thu, 15 Jun 2023 09:30:16 +0800
|
|
|
+Subject: [PATCH 2/9] [neon2rvv] Model vxrm in LLVM intrinsics and add
|
|
|
+ optimization for removing redundant csrwi
|
|
|
+
|
|
|
+Signed-off-by: Eric Tang <eric.tang@starfivetech.com>
|
|
|
+---
|
|
|
+ clang/include/clang/Basic/riscv_vector.td | 134 +++++-
|
|
|
+ llvm/include/llvm/IR/IntrinsicsRISCV.td | 94 +++-
|
|
|
+ llvm/lib/Target/RISCV/CMakeLists.txt | 1 +
|
|
|
+ .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 8 +
|
|
|
+ llvm/lib/Target/RISCV/RISCV.h | 3 +
|
|
|
+ .../Target/RISCV/RISCVInsertReadWriteCSR.cpp | 115 +++++
|
|
|
+ llvm/lib/Target/RISCV/RISCVInstrFormats.td | 3 +
|
|
|
+ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +
|
|
|
+ .../Target/RISCV/RISCVInstrInfoVPseudos.td | 428 +++++++++++++++++-
|
|
|
+ llvm/lib/Target/RISCV/RISCVMCInstLower.cpp | 2 +
|
|
|
+ llvm/lib/Target/RISCV/RISCVSystemOperands.td | 2 +-
|
|
|
+ llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 2 +
|
|
|
+ 12 files changed, 747 insertions(+), 47 deletions(-)
|
|
|
+ create mode 100644 llvm/lib/Target/RISCV/RISCVInsertReadWriteCSR.cpp
|
|
|
+
|
|
|
+diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
|
|
|
+index b23e26ecaa57..9d443be0403c 100644
|
|
|
+--- a/clang/include/clang/Basic/riscv_vector.td
|
|
|
++++ b/clang/include/clang/Basic/riscv_vector.td
|
|
|
+@@ -316,11 +316,21 @@ multiclass RVVSignedBinBuiltinSet
|
|
|
+ [["vv", "v", "vvv"],
|
|
|
+ ["vx", "v", "vve"]]>;
|
|
|
+
|
|
|
++multiclass RVVSignedBinBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
++ [["vv", "v", "vvvu"],
|
|
|
++ ["vx", "v", "vveu"]]>;
|
|
|
++
|
|
|
+ multiclass RVVUnsignedBinBuiltinSet
|
|
|
+ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
+ [["vv", "Uv", "UvUvUv"],
|
|
|
+ ["vx", "Uv", "UvUvUe"]]>;
|
|
|
+
|
|
|
++multiclass RVVUnsignedBinBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
++ [["vv", "Uv", "UvUvUvu"],
|
|
|
++ ["vx", "Uv", "UvUvUeu"]]>;
|
|
|
++
|
|
|
+ multiclass RVVIntBinBuiltinSet
|
|
|
+ : RVVSignedBinBuiltinSet,
|
|
|
+ RVVUnsignedBinBuiltinSet;
|
|
|
+@@ -335,11 +345,21 @@ multiclass RVVSignedShiftBuiltinSet
|
|
|
+ [["vv", "v", "vvUv"],
|
|
|
+ ["vx", "v", "vvz"]]>;
|
|
|
+
|
|
|
++multiclass RVVSignedShiftBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
++ [["vv", "v", "vvUvu"],
|
|
|
++ ["vx", "v", "vvzu"]]>;
|
|
|
++
|
|
|
+ multiclass RVVUnsignedShiftBuiltinSet
|
|
|
+ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
+ [["vv", "Uv", "UvUvUv"],
|
|
|
+ ["vx", "Uv", "UvUvz"]]>;
|
|
|
+
|
|
|
++multiclass RVVUnsignedShiftBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp1BuiltinSet<NAME, "csil",
|
|
|
++ [["vv", "Uv", "UvUvUvu"],
|
|
|
++ ["vx", "Uv", "UvUvzu"]]>;
|
|
|
++
|
|
|
+ multiclass RVVShiftBuiltinSet
|
|
|
+ : RVVSignedShiftBuiltinSet,
|
|
|
+ RVVUnsignedShiftBuiltinSet;
|
|
|
+@@ -349,10 +369,18 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
|
|
|
+ : RVVOutOp0Op1BuiltinSet<NAME, "csil",
|
|
|
+ [["wv", "v", "vwUv"],
|
|
|
+ ["wx", "v", "vwz"]]>;
|
|
|
++ multiclass RVVSignedNShiftBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp0Op1BuiltinSet<NAME, "csil",
|
|
|
++ [["wv", "v", "vwUvu"],
|
|
|
++ ["wx", "v", "vwzu"]]>;
|
|
|
+ multiclass RVVUnsignedNShiftBuiltinSet
|
|
|
+ : RVVOutOp0Op1BuiltinSet<NAME, "csil",
|
|
|
+ [["wv", "Uv", "UvUwUv"],
|
|
|
+ ["wx", "Uv", "UvUwz"]]>;
|
|
|
++ multiclass RVVUnsignedNShiftBuiltinSetRoundingMode
|
|
|
++ : RVVOutOp0Op1BuiltinSet<NAME, "csil",
|
|
|
++ [["wv", "Uv", "UvUwUvu"],
|
|
|
++ ["wx", "Uv", "UvUwzu"]]>;
|
|
|
+ }
|
|
|
+
|
|
|
+ multiclass RVVCarryinBuiltinSet
|
|
|
+@@ -1928,6 +1956,17 @@ let HasMasked = false,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 13. Vector Fixed-Point Arithmetic Instructions
|
|
|
++let HeaderCode =
|
|
|
++[{
|
|
|
++enum __RISCV_VXRM {
|
|
|
++ __RISCV_VXRM_RNU = 0,
|
|
|
++ __RISCV_VXRM_RNE = 1,
|
|
|
++ __RISCV_VXRM_RDN = 2,
|
|
|
++ __RISCV_VXRM_ROD = 3,
|
|
|
++};
|
|
|
++}] in
|
|
|
++def vxrm_enum : RVVHeader;
|
|
|
++
|
|
|
+ // 13.1. Vector Single-Width Saturating Add and Subtract
|
|
|
+ let UnMaskedPolicyScheme = HasPassthruOperand in {
|
|
|
+ defm vsaddu : RVVUnsignedBinBuiltinSet;
|
|
|
+@@ -1936,23 +1975,94 @@ defm vssubu : RVVUnsignedBinBuiltinSet;
|
|
|
+ defm vssub : RVVSignedBinBuiltinSet;
|
|
|
+
|
|
|
+ // 13.2. Vector Single-Width Averaging Add and Subtract
|
|
|
+-defm vaaddu : RVVUnsignedBinBuiltinSet;
|
|
|
+-defm vaadd : RVVSignedBinBuiltinSet;
|
|
|
+-defm vasubu : RVVUnsignedBinBuiltinSet;
|
|
|
+-defm vasub : RVVSignedBinBuiltinSet;
|
|
|
++let ManualCodegen = [{
|
|
|
++ {
|
|
|
++ // LLVM intrinsic
|
|
|
++ // Unmasked: (passthru, op0, op1, round_mode, vl)
|
|
|
++ // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy)
|
|
|
++
|
|
|
++ SmallVector<llvm::Value*, 7> Operands;
|
|
|
++ bool HasMaskedOff = !(
|
|
|
++ (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
|
|
++ (!IsMasked && PolicyAttrs & RVV_VTA));
|
|
|
++ unsigned Offset = IsMasked ?
|
|
|
++ (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0);
|
|
|
++
|
|
|
++ if (!HasMaskedOff)
|
|
|
++ Operands.push_back(llvm::PoisonValue::get(ResultType));
|
|
|
++ else
|
|
|
++ Operands.push_back(Ops[Offset]);
|
|
|
++
|
|
|
++ Operands.push_back(Ops[Offset]); // op0
|
|
|
++ Operands.push_back(Ops[Offset + 1]); // op1
|
|
|
++
|
|
|
++ if (IsMasked)
|
|
|
++ Operands.push_back(Ops[0]); // mask
|
|
|
++
|
|
|
++ Operands.push_back(Ops[Offset + 2]); // vxrm
|
|
|
++ Operands.push_back(Ops[Offset + 3]); // vl
|
|
|
++
|
|
|
++ if (IsMasked)
|
|
|
++ Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
|
|
++
|
|
|
++ IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(), Ops.back()->getType()};
|
|
|
++ llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
|
|
++ return Builder.CreateCall(F, Operands, "");
|
|
|
++ }
|
|
|
++}] in {
|
|
|
++ defm vaaddu : RVVUnsignedBinBuiltinSetRoundingMode;
|
|
|
++ defm vaadd : RVVSignedBinBuiltinSetRoundingMode;
|
|
|
++ defm vasubu : RVVUnsignedBinBuiltinSetRoundingMode;
|
|
|
++ defm vasub : RVVSignedBinBuiltinSetRoundingMode;
|
|
|
+
|
|
|
+ // 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
|
|
|
+-let RequiredFeatures = ["FullMultiply"] in {
|
|
|
+-defm vsmul : RVVSignedBinBuiltinSet;
|
|
|
+-}
|
|
|
++ let RequiredFeatures = ["FullMultiply"] in {
|
|
|
++ defm vsmul : RVVSignedBinBuiltinSetRoundingMode;
|
|
|
++ }
|
|
|
+
|
|
|
+ // 13.4. Vector Single-Width Scaling Shift Instructions
|
|
|
+-defm vssrl : RVVUnsignedShiftBuiltinSet;
|
|
|
+-defm vssra : RVVSignedShiftBuiltinSet;
|
|
|
+-
|
|
|
++ defm vssrl : RVVUnsignedShiftBuiltinSetRoundingMode;
|
|
|
++ defm vssra : RVVSignedShiftBuiltinSetRoundingMode;
|
|
|
++}
|
|
|
++let ManualCodegen = [{
|
|
|
++ {
|
|
|
++ // LLVM intrinsic
|
|
|
++ // Unmasked: (passthru, op0, op1, round_mode, vl)
|
|
|
++ // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy)
|
|
|
++
|
|
|
++ SmallVector<llvm::Value*, 7> Operands;
|
|
|
++ bool HasMaskedOff = !(
|
|
|
++ (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
|
|
++ (!IsMasked && PolicyAttrs & RVV_VTA));
|
|
|
++ unsigned Offset = IsMasked ?
|
|
|
++ (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0);
|
|
|
++
|
|
|
++ if (!HasMaskedOff)
|
|
|
++ Operands.push_back(llvm::PoisonValue::get(ResultType));
|
|
|
++ else
|
|
|
++ Operands.push_back(Ops[Offset - 1]);
|
|
|
++
|
|
|
++ Operands.push_back(Ops[Offset]); // op0
|
|
|
++ Operands.push_back(Ops[Offset + 1]); // op1
|
|
|
++
|
|
|
++ if (IsMasked)
|
|
|
++ Operands.push_back(Ops[0]); // mask
|
|
|
++
|
|
|
++ Operands.push_back(Ops[Offset + 2]); // vxrm
|
|
|
++ Operands.push_back(Ops[Offset + 3]); // vl
|
|
|
++
|
|
|
++ if (IsMasked)
|
|
|
++ Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
|
|
++
|
|
|
++ IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), Ops.back()->getType()};
|
|
|
++ llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
|
|
++ return Builder.CreateCall(F, Operands, "");
|
|
|
++ }
|
|
|
++}] in {
|
|
|
+ // 13.5. Vector Narrowing Fixed-Point Clip Instructions
|
|
|
+-defm vnclipu : RVVUnsignedNShiftBuiltinSet;
|
|
|
+-defm vnclip : RVVSignedNShiftBuiltinSet;
|
|
|
++ defm vnclipu : RVVUnsignedNShiftBuiltinSetRoundingMode;
|
|
|
++ defm vnclip : RVVSignedNShiftBuiltinSetRoundingMode;
|
|
|
++}
|
|
|
+
|
|
|
+ // 14. Vector Floating-Point Instructions
|
|
|
+ // 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
|
|
|
+diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
|
|
|
+index e9c88f468076..7103bb5f5e39 100644
|
|
|
+--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
|
|
|
++++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
|
|
|
+@@ -586,6 +586,17 @@ let TargetPrefix = "riscv" in {
|
|
|
+ let ScalarOperand = 2;
|
|
|
+ let VLOperand = 3;
|
|
|
+ }
|
|
|
++ // For Saturating binary operations with rounding-mode operand
|
|
|
++ // The destination vector type is the same as first source vector.
|
|
|
++ // Input: (passthru, vector_in, vector_in/scalar_in, vxrm, vl)
|
|
|
++ class RISCVSaturatingBinaryAAXUnMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
|
|
|
++ llvm_anyint_ty, LLVMMatchType<2>],
|
|
|
++ [ImmArg<ArgIndex<3>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let ScalarOperand = 2;
|
|
|
++ let VLOperand = 4;
|
|
|
++ }
|
|
|
+ // For Saturating binary operations with mask.
|
|
|
+ // The destination vector type is the same as first source vector.
|
|
|
+ // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
|
|
|
+@@ -598,6 +609,18 @@ let TargetPrefix = "riscv" in {
|
|
|
+ let ScalarOperand = 2;
|
|
|
+ let VLOperand = 4;
|
|
|
+ }
|
|
|
++ // For Saturating binary operations with mask and rounding-mode operand
|
|
|
++ // The destination vector type is the same as first source vector.
|
|
|
++ // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy)
|
|
|
++ class RISCVSaturatingBinaryAAXMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
|
|
|
++ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty,
|
|
|
++ LLVMMatchType<2>, LLVMMatchType<2>],
|
|
|
++ [ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<6>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let ScalarOperand = 2;
|
|
|
++ let VLOperand = 5;
|
|
|
++ }
|
|
|
+ // For Saturating binary operations.
|
|
|
+ // The destination vector type is the same as first source vector.
|
|
|
+ // The second source operand matches the destination type or is an XLen scalar.
|
|
|
+@@ -609,6 +632,15 @@ let TargetPrefix = "riscv" in {
|
|
|
+ [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic {
|
|
|
+ let VLOperand = 3;
|
|
|
+ }
|
|
|
++
|
|
|
++ // Input: (passthru, vector_in, vector_in/scalar_in, vxrm, vl)
|
|
|
++ class RISCVSaturatingBinaryAAShiftUnMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
|
|
|
++ llvm_anyint_ty, LLVMMatchType<2>],
|
|
|
++ [ImmArg<ArgIndex<3>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let VLOperand = 4;
|
|
|
++ }
|
|
|
+ // For Saturating binary operations with mask.
|
|
|
+ // The destination vector type is the same as first source vector.
|
|
|
+ // The second source operand matches the destination type or is an XLen scalar.
|
|
|
+@@ -621,6 +653,17 @@ let TargetPrefix = "riscv" in {
|
|
|
+ [ImmArg<ArgIndex<5>>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic {
|
|
|
+ let VLOperand = 4;
|
|
|
+ }
|
|
|
++
|
|
|
++ // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy)
|
|
|
++ class RISCVSaturatingBinaryAAShiftMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
|
|
|
++ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty,
|
|
|
++ LLVMMatchType<2>, LLVMMatchType<2>],
|
|
|
++ [ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<6>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let VLOperand = 5;
|
|
|
++ }
|
|
|
++
|
|
|
+ // For Saturating binary operations.
|
|
|
+ // The destination vector type is NOT the same as first source vector.
|
|
|
+ // The second source operand matches the destination type or is an XLen scalar.
|
|
|
+@@ -632,6 +675,16 @@ let TargetPrefix = "riscv" in {
|
|
|
+ [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic {
|
|
|
+ let VLOperand = 3;
|
|
|
+ }
|
|
|
++
|
|
|
++ // Input: (passthru, vector_in, vector_in/scalar_in, vxrm, vl)
|
|
|
++ class RISCVSaturatingBinaryABShiftUnMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty,
|
|
|
++ llvm_anyint_ty, LLVMMatchType<3>],
|
|
|
++ [ImmArg<ArgIndex<3>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let VLOperand = 4;
|
|
|
++ }
|
|
|
++
|
|
|
+ // For Saturating binary operations with mask.
|
|
|
+ // The destination vector type is NOT the same as first source vector (with mask).
|
|
|
+ // The second source operand matches the destination type or is an XLen scalar.
|
|
|
+@@ -644,6 +697,17 @@ let TargetPrefix = "riscv" in {
|
|
|
+ [ImmArg<ArgIndex<5>>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic {
|
|
|
+ let VLOperand = 4;
|
|
|
+ }
|
|
|
++
|
|
|
++ // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy)
|
|
|
++ class RISCVSaturatingBinaryABShiftMaskedRoundingMode
|
|
|
++ : Intrinsic<[llvm_anyvector_ty],
|
|
|
++ [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty,
|
|
|
++ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty,
|
|
|
++ LLVMMatchType<3>, LLVMMatchType<3>],
|
|
|
++ [ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<6>>, IntrNoMem]>, RISCVVIntrinsic {
|
|
|
++ let VLOperand = 5;
|
|
|
++ }
|
|
|
++
|
|
|
+ // Input: (vector_in, vector_in, scalar_in, vl, policy)
|
|
|
+ class RVVSlideUnMasked
|
|
|
+ : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
|
|
|
+@@ -1074,14 +1138,26 @@ let TargetPrefix = "riscv" in {
|
|
|
+ def "int_riscv_" # NAME : RISCVSaturatingBinaryAAXUnMasked;
|
|
|
+ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAXMasked;
|
|
|
+ }
|
|
|
++ multiclass RISCVSaturatingBinaryAAXRoundingMode {
|
|
|
++ def "int_riscv_" # NAME : RISCVSaturatingBinaryAAXUnMaskedRoundingMode;
|
|
|
++ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAXMaskedRoundingMode;
|
|
|
++ }
|
|
|
+ multiclass RISCVSaturatingBinaryAAShift {
|
|
|
+ def "int_riscv_" # NAME : RISCVSaturatingBinaryAAShiftUnMasked;
|
|
|
+ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAShiftMasked;
|
|
|
+ }
|
|
|
++ multiclass RISCVSaturatingBinaryAAShiftRoundingMode {
|
|
|
++ def "int_riscv_" # NAME : RISCVSaturatingBinaryAAShiftUnMaskedRoundingMode;
|
|
|
++ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAShiftMaskedRoundingMode;
|
|
|
++ }
|
|
|
+ multiclass RISCVSaturatingBinaryABShift {
|
|
|
+ def "int_riscv_" # NAME : RISCVSaturatingBinaryABShiftUnMasked;
|
|
|
+ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryABShiftMasked;
|
|
|
+ }
|
|
|
++ multiclass RISCVSaturatingBinaryABShiftRoundingMode {
|
|
|
++ def "int_riscv_" # NAME : RISCVSaturatingBinaryABShiftUnMaskedRoundingMode;
|
|
|
++ def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryABShiftMaskedRoundingMode;
|
|
|
++ }
|
|
|
+ multiclass RVVSlide {
|
|
|
+ def "int_riscv_" # NAME : RVVSlideUnMasked;
|
|
|
+ def "int_riscv_" # NAME # "_mask" : RVVSlideMasked;
|
|
|
+@@ -1350,18 +1426,18 @@ let TargetPrefix = "riscv" in {
|
|
|
+
|
|
|
+ def "int_riscv_vcompress" : RISCVCompress;
|
|
|
+
|
|
|
+- defm vaaddu : RISCVSaturatingBinaryAAX;
|
|
|
+- defm vaadd : RISCVSaturatingBinaryAAX;
|
|
|
+- defm vasubu : RISCVSaturatingBinaryAAX;
|
|
|
+- defm vasub : RISCVSaturatingBinaryAAX;
|
|
|
++ defm vaaddu : RISCVSaturatingBinaryAAXRoundingMode;
|
|
|
++ defm vaadd : RISCVSaturatingBinaryAAXRoundingMode;
|
|
|
++ defm vasubu : RISCVSaturatingBinaryAAXRoundingMode;
|
|
|
++ defm vasub : RISCVSaturatingBinaryAAXRoundingMode;
|
|
|
+
|
|
|
+- defm vsmul : RISCVSaturatingBinaryAAX;
|
|
|
++ defm vsmul : RISCVSaturatingBinaryAAXRoundingMode;
|
|
|
+
|
|
|
+- defm vssrl : RISCVSaturatingBinaryAAShift;
|
|
|
+- defm vssra : RISCVSaturatingBinaryAAShift;
|
|
|
++ defm vssrl : RISCVSaturatingBinaryAAShiftRoundingMode;
|
|
|
++ defm vssra : RISCVSaturatingBinaryAAShiftRoundingMode;
|
|
|
+
|
|
|
+- defm vnclipu : RISCVSaturatingBinaryABShift;
|
|
|
+- defm vnclip : RISCVSaturatingBinaryABShift;
|
|
|
++ defm vnclipu : RISCVSaturatingBinaryABShiftRoundingMode;
|
|
|
++ defm vnclip : RISCVSaturatingBinaryABShiftRoundingMode;
|
|
|
+
|
|
|
+ defm vmfeq : RISCVCompare;
|
|
|
+ defm vmfne : RISCVCompare;
|
|
|
+diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
|
|
|
+index f909e0017e2b..db84f0504f21 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/CMakeLists.txt
|
|
|
++++ b/llvm/lib/Target/RISCV/CMakeLists.txt
|
|
|
+@@ -27,6 +27,7 @@ add_llvm_target(RISCVCodeGen
|
|
|
+ RISCVFrameLowering.cpp
|
|
|
+ RISCVGatherScatterLowering.cpp
|
|
|
+ RISCVInsertVSETVLI.cpp
|
|
|
++ RISCVInsertReadWriteCSR.cpp
|
|
|
+ RISCVInstrInfo.cpp
|
|
|
+ RISCVISelDAGToDAG.cpp
|
|
|
+ RISCVISelLowering.cpp
|
|
|
+diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
|
|
+index 2cf2045c1719..eb43f4bf0a02 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
|
|
++++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
|
|
+@@ -102,6 +102,9 @@ enum {
|
|
|
+ // in bits 63:31. Used by the SExtWRemoval pass.
|
|
|
+ IsSignExtendingOpWShift = UsesMaskPolicyShift + 1,
|
|
|
+ IsSignExtendingOpWMask = 1ULL << IsSignExtendingOpWShift,
|
|
|
++
|
|
|
++ HasRoundModeOpShift = IsSignExtendingOpWShift + 1,
|
|
|
++ HasRoundModeOpMask = 1 << HasRoundModeOpShift,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Match with the definitions in RISCVInstrFormats.td
|
|
|
+@@ -176,6 +179,11 @@ static inline bool usesMaskPolicy(uint64_t TSFlags) {
|
|
|
+ return TSFlags & UsesMaskPolicyMask;
|
|
|
+ }
|
|
|
+
|
|
|
++/// \returns true if there is a rounding mode operand for this instruction
|
|
|
++static inline bool hasRoundModeOp(uint64_t TSFlags) {
|
|
|
++ return TSFlags & HasRoundModeOpMask;
|
|
|
++}
|
|
|
++
|
|
|
+ static inline unsigned getMergeOpNum(const MCInstrDesc &Desc) {
|
|
|
+ assert(hasMergeOp(Desc.TSFlags));
|
|
|
+ assert(!Desc.isVariadic());
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
|
|
|
+index c42fb070aade..f629bd2faea9 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCV.h
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCV.h
|
|
|
+@@ -68,6 +68,9 @@ void initializeRISCVExpandAtomicPseudoPass(PassRegistry &);
|
|
|
+ FunctionPass *createRISCVInsertVSETVLIPass();
|
|
|
+ void initializeRISCVInsertVSETVLIPass(PassRegistry &);
|
|
|
+
|
|
|
++FunctionPass *createRISCVInsertReadWriteCSRPass();
|
|
|
++void initializeRISCVInsertReadWriteCSRPass(PassRegistry &);
|
|
|
++
|
|
|
+ FunctionPass *createRISCVRedundantCopyEliminationPass();
|
|
|
+ void initializeRISCVRedundantCopyEliminationPass(PassRegistry &);
|
|
|
+
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVInsertReadWriteCSR.cpp b/llvm/lib/Target/RISCV/RISCVInsertReadWriteCSR.cpp
|
|
|
+new file mode 100644
|
|
|
+index 000000000000..9cc06adf658c
|
|
|
+--- /dev/null
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVInsertReadWriteCSR.cpp
|
|
|
+@@ -0,0 +1,115 @@
|
|
|
++//===-- RISCVInsertReadWriteCSR.cpp - Insert Read/Write of RISC-V CSR -----===//
|
|
|
++//
|
|
|
++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
++// See https://llvm.org/LICENSE.txt for license information.
|
|
|
++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
++//
|
|
|
++//===----------------------------------------------------------------------===//
|
|
|
++// This file implements the machine function pass to insert read/write of CSR-s
|
|
|
++// of the RISC-V instructions.
|
|
|
++//
|
|
|
++// Currently the pass implements naive insertion of a write to vxrm before an
|
|
|
++// RVV fixed-point instruction.
|
|
|
++//
|
|
|
++//===----------------------------------------------------------------------===//
|
|
|
++
|
|
|
++#include "RISCV.h"
|
|
|
++#include "RISCVSubtarget.h"
|
|
|
++#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
|
++using namespace llvm;
|
|
|
++
|
|
|
++#define DEBUG_TYPE "riscv-insert-read-write-csr"
|
|
|
++#define RISCV_INSERT_READ_WRITE_CSR_NAME "RISC-V Insert Read/Write CSR Pass"
|
|
|
++
|
|
|
++namespace {
|
|
|
++
|
|
|
++class RISCVInsertReadWriteCSR : public MachineFunctionPass {
|
|
|
++ const TargetInstrInfo *TII;
|
|
|
++
|
|
|
++public:
|
|
|
++ static char ID;
|
|
|
++
|
|
|
++ RISCVInsertReadWriteCSR() : MachineFunctionPass(ID) {
|
|
|
++ initializeRISCVInsertReadWriteCSRPass(*PassRegistry::getPassRegistry());
|
|
|
++ }
|
|
|
++
|
|
|
++ bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
++
|
|
|
++ void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
++ AU.setPreservesCFG();
|
|
|
++ MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
++ }
|
|
|
++
|
|
|
++ StringRef getPassName() const override {
|
|
|
++ return RISCV_INSERT_READ_WRITE_CSR_NAME;
|
|
|
++ }
|
|
|
++
|
|
|
++private:
|
|
|
++ bool emitWriteVXRM(MachineBasicBlock &MBB);
|
|
|
++ std::optional<unsigned> getRoundModeIdx(const MachineInstr &MI);
|
|
|
++};
|
|
|
++
|
|
|
++} // end anonymous namespace
|
|
|
++
|
|
|
++char RISCVInsertReadWriteCSR::ID = 0;
|
|
|
++
|
|
|
++static unsigned PreVXRMValue = 4;
|
|
|
++
|
|
|
++INITIALIZE_PASS(RISCVInsertReadWriteCSR, DEBUG_TYPE,
|
|
|
++ RISCV_INSERT_READ_WRITE_CSR_NAME, false, false)
|
|
|
++
|
|
|
++// This function returns the index to the rounding mode immediate value if any,
|
|
|
++// otherwise the function will return None.
|
|
|
++std::optional<unsigned>
|
|
|
++RISCVInsertReadWriteCSR::getRoundModeIdx(const MachineInstr &MI) {
|
|
|
++ uint64_t TSFlags = MI.getDesc().TSFlags;
|
|
|
++ if (!RISCVII::hasRoundModeOp(TSFlags))
|
|
|
++ return std::nullopt;
|
|
|
++
|
|
|
++ // The operand order
|
|
|
++ // -------------------------------------
|
|
|
++ // | n-1 (if any) | n-2 | n-3 | n-4 |
|
|
|
++ // | policy | sew | vl | rm |
|
|
|
++ // -------------------------------------
|
|
|
++ return MI.getNumExplicitOperands() - RISCVII::hasVecPolicyOp(TSFlags) - 3;
|
|
|
++}
|
|
|
++
|
|
|
++// This function inserts a write to vxrm when encountering an RVV fixed-point
|
|
|
++// instruction.
|
|
|
++bool RISCVInsertReadWriteCSR::emitWriteVXRM(MachineBasicBlock &MBB) {
|
|
|
++ bool Changed = false;
|
|
|
++ for (MachineInstr &MI : MBB) {
|
|
|
++ if (auto RoundModeIdx = getRoundModeIdx(MI)) {
|
|
|
++ unsigned VXRMImm = MI.getOperand(*RoundModeIdx).getImm();
|
|
|
++ if (VXRMImm == PreVXRMValue)
|
|
|
++ continue;
|
|
|
++ PreVXRMValue = VXRMImm;
|
|
|
++ Changed = true;
|
|
|
++ BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::WriteVXRMImm))
|
|
|
++ .addImm(VXRMImm);
|
|
|
++ MI.addOperand(MachineOperand::CreateReg(RISCV::VXRM, /*IsDef*/ false,
|
|
|
++ /*IsImp*/ true));
|
|
|
++ }
|
|
|
++ }
|
|
|
++ return Changed;
|
|
|
++}
|
|
|
++
|
|
|
++bool RISCVInsertReadWriteCSR::runOnMachineFunction(MachineFunction &MF) {
|
|
|
++ // Skip if the vector extension is not enabled.
|
|
|
++ const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
|
|
|
++ if (!ST.hasVInstructions())
|
|
|
++ return false;
|
|
|
++
|
|
|
++ TII = ST.getInstrInfo();
|
|
|
++
|
|
|
++ bool Changed = false;
|
|
|
++
|
|
|
++ for (MachineBasicBlock &MBB : MF)
|
|
|
++ Changed |= emitWriteVXRM(MBB);
|
|
|
++
|
|
|
++ return Changed;
|
|
|
++}
|
|
|
++
|
|
|
++FunctionPass *llvm::createRISCVInsertReadWriteCSRPass() {
|
|
|
++ return new RISCVInsertReadWriteCSR();
|
|
|
++}
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
|
|
+index 3a494a5e3b58..f2cd4ed8857f 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
|
|
+@@ -211,6 +211,9 @@ class RVInst<dag outs, dag ins, string opcodestr, string argstr,
|
|
|
+ // in bits 63:31. Used by the SExtWRemoval pass.
|
|
|
+ bit IsSignExtendingOpW = 0;
|
|
|
+ let TSFlags{19} = IsSignExtendingOpW;
|
|
|
++
|
|
|
++ bit HasRoundModeOp = 0;
|
|
|
++ let TSFlags{20} = HasRoundModeOp;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Pseudo instructions
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
|
|
+index c699a94943d8..75fee3f962d0 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
|
|
+@@ -1693,6 +1693,8 @@ def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;
|
|
|
+ def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>;
|
|
|
+ def SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>;
|
|
|
+
|
|
|
++def WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>;
|
|
|
++
|
|
|
+ let hasSideEffects = true in {
|
|
|
+ def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;
|
|
|
+ def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
|
|
|
+index 3f69b5e41cf1..ec7af31a23e2 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
|
|
|
+@@ -1139,6 +1139,65 @@ class VPseudoBinaryNoMaskTU<VReg RetClass,
|
|
|
+ let HasMergeOp = 1;
|
|
|
+ }
|
|
|
+
|
|
|
++class VPseudoBinaryNoMaskRoundingMode<VReg RetClass,
|
|
|
++ VReg Op1Class,
|
|
|
++ DAGOperand Op2Class,
|
|
|
++ string Constraint,
|
|
|
++ int DummyMask = 1> :
|
|
|
++ Pseudo<(outs RetClass:$rd),
|
|
|
++ (ins Op1Class:$rs2, Op2Class:$rs1, ixlenimm:$rm, AVL:$vl, ixlenimm:$sew), []>,
|
|
|
++ RISCVVPseudo {
|
|
|
++ let mayLoad = 0;
|
|
|
++ let mayStore = 0;
|
|
|
++ let hasSideEffects = 0;
|
|
|
++ let Constraints = Constraint;
|
|
|
++ let HasVLOp = 1;
|
|
|
++ let HasSEWOp = 1;
|
|
|
++ let HasDummyMask = DummyMask;
|
|
|
++ let HasRoundModeOp = 1;
|
|
|
++}
|
|
|
++
|
|
|
++class VPseudoBinaryNoMaskTURoundingMode<VReg RetClass,
|
|
|
++ VReg Op1Class,
|
|
|
++ DAGOperand Op2Class,
|
|
|
++ string Constraint> :
|
|
|
++ Pseudo<(outs RetClass:$rd),
|
|
|
++ (ins RetClass:$merge, Op1Class:$rs2, Op2Class:$rs1, ixlenimm:$rm,
|
|
|
++ AVL:$vl, ixlenimm:$sew), []>,
|
|
|
++ RISCVVPseudo {
|
|
|
++ let mayLoad = 0;
|
|
|
++ let mayStore = 0;
|
|
|
++ let hasSideEffects = 0;
|
|
|
++ let Constraints = Join<[Constraint, "$rd = $merge"], ",">.ret;
|
|
|
++ let HasVLOp = 1;
|
|
|
++ let HasSEWOp = 1;
|
|
|
++ let HasDummyMask = 1;
|
|
|
++ let HasMergeOp = 1;
|
|
|
++ let HasRoundModeOp = 1;
|
|
|
++}
|
|
|
++
|
|
|
++class VPseudoBinaryMaskPolicyRoundingMode<VReg RetClass,
|
|
|
++ RegisterClass Op1Class,
|
|
|
++ DAGOperand Op2Class,
|
|
|
++ string Constraint> :
|
|
|
++ Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd),
|
|
|
++ (ins GetVRegNoV0<RetClass>.R:$merge,
|
|
|
++ Op1Class:$rs2, Op2Class:$rs1,
|
|
|
++ VMaskOp:$vm, ixlenimm:$rm, AVL:$vl,
|
|
|
++ ixlenimm:$sew, ixlenimm:$policy), []>,
|
|
|
++ RISCVVPseudo {
|
|
|
++ let mayLoad = 0;
|
|
|
++ let mayStore = 0;
|
|
|
++ let hasSideEffects = 0;
|
|
|
++ let Constraints = Join<[Constraint, "$rd = $merge"], ",">.ret;
|
|
|
++ let HasVLOp = 1;
|
|
|
++ let HasSEWOp = 1;
|
|
|
++ let HasMergeOp = 1;
|
|
|
++ let HasVecPolicyOp = 1;
|
|
|
++ let UsesMaskPolicy = 1;
|
|
|
++ let HasRoundModeOp = 1;
|
|
|
++}
|
|
|
++
|
|
|
+ // Special version of VPseudoBinaryNoMask where we pretend the first source is
|
|
|
+ // tied to the destination.
|
|
|
+ // This allows maskedoff and rs2 to be the same register.
|
|
|
+@@ -1923,6 +1982,24 @@ multiclass VPseudoBinary<VReg RetClass,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryRoundingMode<VReg RetClass,
|
|
|
++ VReg Op1Class,
|
|
|
++ DAGOperand Op2Class,
|
|
|
++ LMULInfo MInfo,
|
|
|
++ string Constraint = ""> {
|
|
|
++ let VLMul = MInfo.value in {
|
|
|
++ def "_" # MInfo.MX :
|
|
|
++ VPseudoBinaryNoMaskRoundingMode<RetClass, Op1Class, Op2Class, Constraint>;
|
|
|
++ def "_" # MInfo.MX # "_TU" :
|
|
|
++ VPseudoBinaryNoMaskTURoundingMode<RetClass, Op1Class, Op2Class,
|
|
|
++ Constraint>;
|
|
|
++ def "_" # MInfo.MX # "_MASK" :
|
|
|
++ VPseudoBinaryMaskPolicyRoundingMode<RetClass, Op1Class, Op2Class,
|
|
|
++ Constraint>,
|
|
|
++ RISCVMaskedPseudo</*MaskOpIdx*/ 3>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoBinaryM<VReg RetClass,
|
|
|
+ VReg Op1Class,
|
|
|
+ DAGOperand Op2Class,
|
|
|
+@@ -1971,6 +2048,10 @@ multiclass VPseudoBinaryV_VV<LMULInfo m, string Constraint = ""> {
|
|
|
+ defm _VV : VPseudoBinary<m.vrclass, m.vrclass, m.vrclass, m, Constraint>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_VV_RM<LMULInfo m, string Constraint = ""> {
|
|
|
++ defm _VV : VPseudoBinaryRoundingMode<m.vrclass, m.vrclass, m.vrclass, m, Constraint>;
|
|
|
++}
|
|
|
++
|
|
|
+ // Similar to VPseudoBinaryV_VV, but uses MxListF.
|
|
|
+ multiclass VPseudoBinaryFV_VV<LMULInfo m, string Constraint = ""> {
|
|
|
+ defm _VV : VPseudoBinary<m.vrclass, m.vrclass, m.vrclass, m, Constraint>;
|
|
|
+@@ -2000,6 +2081,10 @@ multiclass VPseudoBinaryV_VX<LMULInfo m, string Constraint = ""> {
|
|
|
+ defm "_VX" : VPseudoBinary<m.vrclass, m.vrclass, GPR, m, Constraint>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_VX_RM<LMULInfo m, string Constraint = ""> {
|
|
|
++ defm "_VX" : VPseudoBinaryRoundingMode<m.vrclass, m.vrclass, GPR, m, Constraint>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVSLD1_VX<string Constraint = ""> {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -2036,6 +2121,10 @@ multiclass VPseudoBinaryV_VI<Operand ImmType = simm5, LMULInfo m, string Constra
|
|
|
+ defm _VI : VPseudoBinary<m.vrclass, m.vrclass, ImmType, m, Constraint>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_VI_RM<Operand ImmType = simm5, LMULInfo m, string Constraint = ""> {
|
|
|
++ defm _VI : VPseudoBinaryRoundingMode<m.vrclass, m.vrclass, ImmType, m, Constraint>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVALU_MM {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -2098,16 +2187,31 @@ multiclass VPseudoBinaryV_WV<LMULInfo m> {
|
|
|
+ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_WV_RM<LMULInfo m> {
|
|
|
++ defm _WV : VPseudoBinaryRoundingMode<m.vrclass, m.wvrclass, m.vrclass, m,
|
|
|
++ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoBinaryV_WX<LMULInfo m> {
|
|
|
+ defm _WX : VPseudoBinary<m.vrclass, m.wvrclass, GPR, m,
|
|
|
+ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_WX_RM<LMULInfo m> {
|
|
|
++ defm _WX : VPseudoBinaryRoundingMode<m.vrclass, m.wvrclass, GPR, m,
|
|
|
++ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoBinaryV_WI<LMULInfo m> {
|
|
|
+ defm _WI : VPseudoBinary<m.vrclass, m.wvrclass, uimm5, m,
|
|
|
+ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoBinaryV_WI_RM<LMULInfo m> {
|
|
|
++ defm _WI : VPseudoBinaryRoundingMode<m.vrclass, m.wvrclass, uimm5, m,
|
|
|
++ !if(!ge(m.octuple, 8), "@earlyclobber $rd", "")>;
|
|
|
++}
|
|
|
++
|
|
|
+ // For vadc and vsbc, the instruction encoding is reserved if the destination
|
|
|
+ // vector register is v0.
|
|
|
+ // For vadc and vsbc, CarryIn == 1 and CarryOut == 0
|
|
|
+@@ -2419,6 +2523,23 @@ multiclass VPseudoVSALU_VV_VX_VI<Operand ImmType = simm5, string Constraint = ""
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVSALU_VV_VX_VI_RM<Operand ImmType = simm5, string Constraint = ""> {
|
|
|
++ foreach m = MxList in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVSALUV_MX = !cast<SchedWrite>("WriteVSALUV_" # mx);
|
|
|
++ defvar WriteVSALUX_MX = !cast<SchedWrite>("WriteVSALUX_" # mx);
|
|
|
++ defvar WriteVSALUI_MX = !cast<SchedWrite>("WriteVSALUI_" # mx);
|
|
|
++ defvar ReadVSALUV_MX = !cast<SchedRead>("ReadVSALUV_" # mx);
|
|
|
++ defvar ReadVSALUX_MX = !cast<SchedRead>("ReadVSALUX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_VV_RM<m, Constraint>,
|
|
|
++ Sched<[WriteVSALUV_MX, ReadVSALUV_MX, ReadVSALUV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VX_RM<m, Constraint>,
|
|
|
++ Sched<[WriteVSALUX_MX, ReadVSALUV_MX, ReadVSALUX_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VI_RM<ImmType, m, Constraint>,
|
|
|
++ Sched<[WriteVSALUI_MX, ReadVSALUV_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
+
|
|
|
+ multiclass VPseudoVSHT_VV_VX_VI<Operand ImmType = simm5, string Constraint = ""> {
|
|
|
+ foreach m = MxList in {
|
|
|
+@@ -2456,6 +2577,24 @@ multiclass VPseudoVSSHT_VV_VX_VI<Operand ImmType = simm5, string Constraint = ""
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVSSHT_VV_VX_VI_RM<Operand ImmType = simm5, string Constraint = ""> {
|
|
|
++ foreach m = MxList in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVSShiftV_MX = !cast<SchedWrite>("WriteVSShiftV_" # mx);
|
|
|
++ defvar WriteVSShiftX_MX = !cast<SchedWrite>("WriteVSShiftX_" # mx);
|
|
|
++ defvar WriteVSShiftI_MX = !cast<SchedWrite>("WriteVSShiftI_" # mx);
|
|
|
++ defvar ReadVSShiftV_MX = !cast<SchedRead>("ReadVSShiftV_" # mx);
|
|
|
++ defvar ReadVSShiftX_MX = !cast<SchedRead>("ReadVSShiftX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_VV_RM<m, Constraint>,
|
|
|
++ Sched<[WriteVSShiftV_MX, ReadVSShiftV_MX, ReadVSShiftV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VX_RM<m, Constraint>,
|
|
|
++ Sched<[WriteVSShiftX_MX, ReadVSShiftV_MX, ReadVSShiftX_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VI_RM<ImmType, m, Constraint>,
|
|
|
++ Sched<[WriteVSShiftI_MX, ReadVSShiftV_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVALU_VV_VX_VI<Operand ImmType = simm5, string Constraint = ""> {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -2489,6 +2628,21 @@ multiclass VPseudoVSALU_VV_VX {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVSALU_VV_VX_RM {
|
|
|
++ foreach m = MxList in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVSALUV_MX = !cast<SchedWrite>("WriteVSALUV_" # mx);
|
|
|
++ defvar WriteVSALUX_MX = !cast<SchedWrite>("WriteVSALUX_" # mx);
|
|
|
++ defvar ReadVSALUV_MX = !cast<SchedRead>("ReadVSALUV_" # mx);
|
|
|
++ defvar ReadVSALUX_MX = !cast<SchedRead>("ReadVSALUX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_VV_RM<m>,
|
|
|
++ Sched<[WriteVSALUV_MX, ReadVSALUV_MX, ReadVSALUV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VX_RM<m>,
|
|
|
++ Sched<[WriteVSALUX_MX, ReadVSALUV_MX, ReadVSALUX_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVSMUL_VV_VX {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -2504,6 +2658,21 @@ multiclass VPseudoVSMUL_VV_VX {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVSMUL_VV_VX_RM {
|
|
|
++ foreach m = MxList in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVSMulV_MX = !cast<SchedWrite>("WriteVSMulV_" # mx);
|
|
|
++ defvar WriteVSMulX_MX = !cast<SchedWrite>("WriteVSMulX_" # mx);
|
|
|
++ defvar ReadVSMulV_MX = !cast<SchedRead>("ReadVSMulV_" # mx);
|
|
|
++ defvar ReadVSMulX_MX = !cast<SchedRead>("ReadVSMulX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_VV_RM<m>,
|
|
|
++ Sched<[WriteVSMulV_MX, ReadVSMulV_MX, ReadVSMulV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VX_RM<m>,
|
|
|
++ Sched<[WriteVSMulX_MX, ReadVSMulV_MX, ReadVSMulX_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVAALU_VV_VX {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -2519,6 +2688,21 @@ multiclass VPseudoVAALU_VV_VX {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVAALU_VV_VX_RM {
|
|
|
++ foreach m = MxList in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVAALUV_MX = !cast<SchedWrite>("WriteVAALUV_" # mx);
|
|
|
++ defvar WriteVAALUX_MX = !cast<SchedWrite>("WriteVAALUX_" # mx);
|
|
|
++ defvar ReadVAALUV_MX = !cast<SchedRead>("ReadVAALUV_" # mx);
|
|
|
++ defvar ReadVAALUX_MX = !cast<SchedRead>("ReadVAALUX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_VV_RM<m>,
|
|
|
++ Sched<[WriteVAALUV_MX, ReadVAALUV_MX, ReadVAALUV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_VX_RM<m>,
|
|
|
++ Sched<[WriteVAALUX_MX, ReadVAALUV_MX, ReadVAALUX_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVMINMAX_VV_VX {
|
|
|
+ foreach m = MxList in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -3002,6 +3186,24 @@ multiclass VPseudoVNCLP_WV_WX_WI {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPseudoVNCLP_WV_WX_WI_RM {
|
|
|
++ foreach m = MxListW in {
|
|
|
++ defvar mx = m.MX;
|
|
|
++ defvar WriteVNClipV_MX = !cast<SchedWrite>("WriteVNClipV_" # mx);
|
|
|
++ defvar WriteVNClipX_MX = !cast<SchedWrite>("WriteVNClipX_" # mx);
|
|
|
++ defvar WriteVNClipI_MX = !cast<SchedWrite>("WriteVNClipI_" # mx);
|
|
|
++ defvar ReadVNClipV_MX = !cast<SchedRead>("ReadVNClipV_" # mx);
|
|
|
++ defvar ReadVNClipX_MX = !cast<SchedRead>("ReadVNClipX_" # mx);
|
|
|
++
|
|
|
++ defm "" : VPseudoBinaryV_WV_RM<m>,
|
|
|
++ Sched<[WriteVNClipV_MX, ReadVNClipV_MX, ReadVNClipV_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_WX_RM<m>,
|
|
|
++ Sched<[WriteVNClipX_MX, ReadVNClipV_MX, ReadVNClipX_MX, ReadVMask]>;
|
|
|
++ defm "" : VPseudoBinaryV_WI_RM<m>,
|
|
|
++ Sched<[WriteVNClipI_MX, ReadVNClipV_MX, ReadVMask]>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPseudoVNSHT_WV_WX_WI {
|
|
|
+ foreach m = MxListW in {
|
|
|
+ defvar mx = m.MX;
|
|
|
+@@ -3881,6 +4083,48 @@ class VPatBinaryNoMaskTU<string intrinsic_name,
|
|
|
+ (op2_type op2_kind:$rs2),
|
|
|
+ GPR:$vl, sew)>;
|
|
|
+
|
|
|
++class VPatBinaryNoMaskTARoundingMode<string intrinsic_name,
|
|
|
++ string inst,
|
|
|
++ ValueType result_type,
|
|
|
++ ValueType op1_type,
|
|
|
++ ValueType op2_type,
|
|
|
++ int sew,
|
|
|
++ VReg op1_reg_class,
|
|
|
++ DAGOperand op2_kind> :
|
|
|
++ Pat<(result_type (!cast<Intrinsic>(intrinsic_name)
|
|
|
++ (result_type (undef)),
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ VLOpFrag)),
|
|
|
++ (!cast<Instruction>(inst)
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ GPR:$vl, sew)>;
|
|
|
++
|
|
|
++class VPatBinaryNoMaskTURoundingMode<string intrinsic_name,
|
|
|
++ string inst,
|
|
|
++ ValueType result_type,
|
|
|
++ ValueType op1_type,
|
|
|
++ ValueType op2_type,
|
|
|
++ int sew,
|
|
|
++ VReg result_reg_class,
|
|
|
++ VReg op1_reg_class,
|
|
|
++ DAGOperand op2_kind> :
|
|
|
++ Pat<(result_type (!cast<Intrinsic>(intrinsic_name)
|
|
|
++ (result_type result_reg_class:$merge),
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ VLOpFrag)),
|
|
|
++ (!cast<Instruction>(inst#"_TU")
|
|
|
++ (result_type result_reg_class:$merge),
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ GPR:$vl, sew)>;
|
|
|
++
|
|
|
+ // Same as above but source operands are swapped.
|
|
|
+ class VPatBinaryNoMaskSwapped<string intrinsic_name,
|
|
|
+ string inst,
|
|
|
+@@ -3943,6 +4187,31 @@ class VPatBinaryMaskTA<string intrinsic_name,
|
|
|
+ (op2_type op2_kind:$rs2),
|
|
|
+ (mask_type V0), GPR:$vl, sew, (XLenVT timm:$policy))>;
|
|
|
+
|
|
|
++class VPatBinaryMaskTARoundingMode<string intrinsic_name,
|
|
|
++ string inst,
|
|
|
++ ValueType result_type,
|
|
|
++ ValueType op1_type,
|
|
|
++ ValueType op2_type,
|
|
|
++ ValueType mask_type,
|
|
|
++ int sew,
|
|
|
++ VReg result_reg_class,
|
|
|
++ VReg op1_reg_class,
|
|
|
++ DAGOperand op2_kind> :
|
|
|
++ Pat<(result_type (!cast<Intrinsic>(intrinsic_name#"_mask")
|
|
|
++ (result_type result_reg_class:$merge),
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (mask_type V0),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ VLOpFrag, (XLenVT timm:$policy))),
|
|
|
++ (!cast<Instruction>(inst#"_MASK")
|
|
|
++ (result_type result_reg_class:$merge),
|
|
|
++ (op1_type op1_reg_class:$rs1),
|
|
|
++ (op2_type op2_kind:$rs2),
|
|
|
++ (mask_type V0),
|
|
|
++ (XLenVT timm:$round),
|
|
|
++ GPR:$vl, sew, (XLenVT timm:$policy))>;
|
|
|
++
|
|
|
+ // Same as above but source operands are swapped.
|
|
|
+ class VPatBinaryMaskSwapped<string intrinsic_name,
|
|
|
+ string inst,
|
|
|
+@@ -4261,6 +4530,26 @@ multiclass VPatBinaryTA<string intrinsic,
|
|
|
+ op2_kind>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryTARoundingMode<string intrinsic,
|
|
|
++ string inst,
|
|
|
++ ValueType result_type,
|
|
|
++ ValueType op1_type,
|
|
|
++ ValueType op2_type,
|
|
|
++ ValueType mask_type,
|
|
|
++ int sew,
|
|
|
++ VReg result_reg_class,
|
|
|
++ VReg op1_reg_class,
|
|
|
++ DAGOperand op2_kind>
|
|
|
++{
|
|
|
++ def : VPatBinaryNoMaskTARoundingMode<intrinsic, inst, result_type, op1_type, op2_type,
|
|
|
++ sew, op1_reg_class, op2_kind>;
|
|
|
++ def : VPatBinaryNoMaskTURoundingMode<intrinsic, inst, result_type, op1_type, op2_type,
|
|
|
++ sew, result_reg_class, op1_reg_class, op2_kind>;
|
|
|
++ def : VPatBinaryMaskTARoundingMode<intrinsic, inst, result_type, op1_type, op2_type,
|
|
|
++ mask_type, sew, result_reg_class, op1_reg_class,
|
|
|
++ op2_kind>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinarySwapped<string intrinsic,
|
|
|
+ string inst,
|
|
|
+ ValueType result_type,
|
|
|
+@@ -4387,6 +4676,15 @@ multiclass VPatBinaryV_VV<string intrinsic, string instruction,
|
|
|
+ vti.RegClass, vti.RegClass>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_VVRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfo> vtilist> {
|
|
|
++ foreach vti = vtilist in
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction # "_VV_" # vti.LMul.MX,
|
|
|
++ vti.Vector, vti.Vector, vti.Vector,vti.Mask,
|
|
|
++ vti.Log2SEW, vti.RegClass,
|
|
|
++ vti.RegClass, vti.RegClass>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VV_INT<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfo> vtilist> {
|
|
|
+ foreach vti = vtilist in {
|
|
|
+@@ -4428,6 +4726,17 @@ multiclass VPatBinaryV_VX<string intrinsic, string instruction,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_VXRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfo> vtilist> {
|
|
|
++ foreach vti = vtilist in {
|
|
|
++ defvar kind = "V"#vti.ScalarSuffix;
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction#"_"#kind#"_"#vti.LMul.MX,
|
|
|
++ vti.Vector, vti.Vector, vti.Scalar, vti.Mask,
|
|
|
++ vti.Log2SEW, vti.RegClass,
|
|
|
++ vti.RegClass, vti.ScalarRegClass>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VX_INT<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfo> vtilist> {
|
|
|
+ foreach vti = vtilist in
|
|
|
+@@ -4446,6 +4755,15 @@ multiclass VPatBinaryV_VI<string intrinsic, string instruction,
|
|
|
+ vti.RegClass, imm_type>;
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_VIRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfo> vtilist, Operand imm_type> {
|
|
|
++ foreach vti = vtilist in
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction # "_VI_" # vti.LMul.MX,
|
|
|
++ vti.Vector, vti.Vector, XLenVT, vti.Mask,
|
|
|
++ vti.Log2SEW, vti.RegClass,
|
|
|
++ vti.RegClass, imm_type>;
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryM_MM<string intrinsic, string instruction> {
|
|
|
+ foreach mti = AllMasks in
|
|
|
+ def : VPatBinaryM<intrinsic, instruction # "_MM_" # mti.LMul.MX,
|
|
|
+@@ -4529,6 +4847,18 @@ multiclass VPatBinaryV_WV<string intrinsic, string instruction,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_WVRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfoToWide> vtilist> {
|
|
|
++ foreach VtiToWti = vtilist in {
|
|
|
++ defvar Vti = VtiToWti.Vti;
|
|
|
++ defvar Wti = VtiToWti.Wti;
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction # "_WV_" # Vti.LMul.MX,
|
|
|
++ Vti.Vector, Wti.Vector, Vti.Vector, Vti.Mask,
|
|
|
++ Vti.Log2SEW, Vti.RegClass,
|
|
|
++ Wti.RegClass, Vti.RegClass>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_WX<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfoToWide> vtilist> {
|
|
|
+ foreach VtiToWti = vtilist in {
|
|
|
+@@ -4542,6 +4872,19 @@ multiclass VPatBinaryV_WX<string intrinsic, string instruction,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_WXRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfoToWide> vtilist> {
|
|
|
++ foreach VtiToWti = vtilist in {
|
|
|
++ defvar Vti = VtiToWti.Vti;
|
|
|
++ defvar Wti = VtiToWti.Wti;
|
|
|
++ defvar kind = "W"#Vti.ScalarSuffix;
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX,
|
|
|
++ Vti.Vector, Wti.Vector, Vti.Scalar, Vti.Mask,
|
|
|
++ Vti.Log2SEW, Vti.RegClass,
|
|
|
++ Wti.RegClass, Vti.ScalarRegClass>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_WI<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfoToWide> vtilist> {
|
|
|
+ foreach VtiToWti = vtilist in {
|
|
|
+@@ -4554,6 +4897,18 @@ multiclass VPatBinaryV_WI<string intrinsic, string instruction,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++multiclass VPatBinaryV_WIRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfoToWide> vtilist> {
|
|
|
++ foreach VtiToWti = vtilist in {
|
|
|
++ defvar Vti = VtiToWti.Vti;
|
|
|
++ defvar Wti = VtiToWti.Wti;
|
|
|
++ defm : VPatBinaryTARoundingMode<intrinsic, instruction # "_WI_" # Vti.LMul.MX,
|
|
|
++ Vti.Vector, Wti.Vector, XLenVT, Vti.Mask,
|
|
|
++ Vti.Log2SEW, Vti.RegClass,
|
|
|
++ Wti.RegClass, uimm5>;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VM<string intrinsic, string instruction,
|
|
|
+ bit CarryOut = 0,
|
|
|
+ list<VTypeInfo> vtilist = AllIntegerVectors> {
|
|
|
+@@ -4688,11 +5043,22 @@ multiclass VPatBinaryV_VV_VX_VI<string intrinsic, string instruction,
|
|
|
+ VPatBinaryV_VX<intrinsic, instruction, vtilist>,
|
|
|
+ VPatBinaryV_VI<intrinsic, instruction, vtilist, ImmType>;
|
|
|
+
|
|
|
++multiclass VPatBinaryV_VV_VX_VIRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfo> vtilist, Operand ImmType = simm5>
|
|
|
++ : VPatBinaryV_VVRoundingMode<intrinsic, instruction, vtilist>,
|
|
|
++ VPatBinaryV_VXRoundingMode<intrinsic, instruction, vtilist>,
|
|
|
++ VPatBinaryV_VIRoundingMode<intrinsic, instruction, vtilist, ImmType>;
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VV_VX<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfo> vtilist>
|
|
|
+ : VPatBinaryV_VV<intrinsic, instruction, vtilist>,
|
|
|
+ VPatBinaryV_VX<intrinsic, instruction, vtilist>;
|
|
|
+
|
|
|
++multiclass VPatBinaryV_VV_VXRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfo> vtilist>
|
|
|
++ : VPatBinaryV_VVRoundingMode<intrinsic, instruction, vtilist>,
|
|
|
++ VPatBinaryV_VXRoundingMode<intrinsic, instruction, vtilist>;
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VX_VI<string intrinsic, string instruction,
|
|
|
+ list<VTypeInfo> vtilist>
|
|
|
+ : VPatBinaryV_VX<intrinsic, instruction, vtilist>,
|
|
|
+@@ -4714,6 +5080,12 @@ multiclass VPatBinaryV_WV_WX_WI<string intrinsic, string instruction,
|
|
|
+ VPatBinaryV_WX<intrinsic, instruction, vtilist>,
|
|
|
+ VPatBinaryV_WI<intrinsic, instruction, vtilist>;
|
|
|
+
|
|
|
++multiclass VPatBinaryV_WV_WX_WIRoundingMode<string intrinsic, string instruction,
|
|
|
++ list<VTypeInfoToWide> vtilist>
|
|
|
++ : VPatBinaryV_WVRoundingMode<intrinsic, instruction, vtilist>,
|
|
|
++ VPatBinaryV_WXRoundingMode<intrinsic, instruction, vtilist>,
|
|
|
++ VPatBinaryV_WIRoundingMode<intrinsic, instruction, vtilist>;
|
|
|
++
|
|
|
+ multiclass VPatBinaryV_VM_XM_IM<string intrinsic, string instruction>
|
|
|
+ : VPatBinaryV_VM_TAIL<intrinsic, instruction>,
|
|
|
+ VPatBinaryV_XM_TAIL<intrinsic, instruction>,
|
|
|
+@@ -5382,34 +5754,34 @@ let Defs = [VXSAT], hasSideEffects = 1 in {
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.2. Vector Single-Width Averaging Add and Subtract
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-let Uses = [VXRM], hasSideEffects = 1 in {
|
|
|
+- defm PseudoVAADDU : VPseudoVAALU_VV_VX;
|
|
|
+- defm PseudoVAADD : VPseudoVAALU_VV_VX;
|
|
|
+- defm PseudoVASUBU : VPseudoVAALU_VV_VX;
|
|
|
+- defm PseudoVASUB : VPseudoVAALU_VV_VX;
|
|
|
++let hasSideEffects = 1 in {
|
|
|
++ defm PseudoVAADDU : VPseudoVAALU_VV_VX_RM;
|
|
|
++ defm PseudoVAADD : VPseudoVAALU_VV_VX_RM;
|
|
|
++ defm PseudoVASUBU : VPseudoVAALU_VV_VX_RM;
|
|
|
++ defm PseudoVASUB : VPseudoVAALU_VV_VX_RM;
|
|
|
+ }
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-let Uses = [VXRM], Defs = [VXSAT], hasSideEffects = 1 in {
|
|
|
+- defm PseudoVSMUL : VPseudoVSMUL_VV_VX;
|
|
|
++let Defs = [VXSAT], hasSideEffects = 1 in {
|
|
|
++ defm PseudoVSMUL : VPseudoVSMUL_VV_VX_RM;
|
|
|
+ }
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.4. Vector Single-Width Scaling Shift Instructions
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-let Uses = [VXRM], hasSideEffects = 1 in {
|
|
|
+- defm PseudoVSSRL : VPseudoVSSHT_VV_VX_VI<uimm5>;
|
|
|
+- defm PseudoVSSRA : VPseudoVSSHT_VV_VX_VI<uimm5>;
|
|
|
++let hasSideEffects = 1 in {
|
|
|
++ defm PseudoVSSRL : VPseudoVSSHT_VV_VX_VI_RM<uimm5>;
|
|
|
++ defm PseudoVSSRA : VPseudoVSSHT_VV_VX_VI_RM<uimm5>;
|
|
|
+ }
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.5. Vector Narrowing Fixed-Point Clip Instructions
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-let Uses = [VXRM], Defs = [VXSAT], hasSideEffects = 1 in {
|
|
|
+- defm PseudoVNCLIP : VPseudoVNCLP_WV_WX_WI;
|
|
|
+- defm PseudoVNCLIPU : VPseudoVNCLP_WV_WX_WI;
|
|
|
++let Defs = [VXSAT], hasSideEffects = 1 in {
|
|
|
++ defm PseudoVNCLIP : VPseudoVNCLP_WV_WX_WI_RM;
|
|
|
++ defm PseudoVNCLIPU : VPseudoVNCLP_WV_WX_WI_RM;
|
|
|
+ }
|
|
|
+
|
|
|
+ } // Predicates = [HasVInstructions]
|
|
|
+@@ -6040,30 +6412,36 @@ defm : VPatBinaryV_VV_VX<"int_riscv_vssub", "PseudoVSSUB", AllIntegerVectors>;
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.2. Vector Single-Width Averaging Add and Subtract
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-defm : VPatBinaryV_VV_VX<"int_riscv_vaaddu", "PseudoVAADDU", AllIntegerVectors>;
|
|
|
+-defm : VPatBinaryV_VV_VX<"int_riscv_vaadd", "PseudoVAADD", AllIntegerVectors>;
|
|
|
+-defm : VPatBinaryV_VV_VX<"int_riscv_vasubu", "PseudoVASUBU", AllIntegerVectors>;
|
|
|
+-defm : VPatBinaryV_VV_VX<"int_riscv_vasub", "PseudoVASUB", AllIntegerVectors>;
|
|
|
++defm : VPatBinaryV_VV_VXRoundingMode<"int_riscv_vaaddu", "PseudoVAADDU",
|
|
|
++ AllIntegerVectors>;
|
|
|
++defm : VPatBinaryV_VV_VXRoundingMode<"int_riscv_vasubu", "PseudoVASUBU",
|
|
|
++ AllIntegerVectors>;
|
|
|
++defm : VPatBinaryV_VV_VXRoundingMode<"int_riscv_vasub", "PseudoVASUB",
|
|
|
++ AllIntegerVectors>;
|
|
|
++defm : VPatBinaryV_VV_VXRoundingMode<"int_riscv_vaadd", "PseudoVAADD",
|
|
|
++ AllIntegerVectors>;
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-defm : VPatBinaryV_VV_VX<"int_riscv_vsmul", "PseudoVSMUL", AllIntegerVectors>;
|
|
|
++defm : VPatBinaryV_VV_VXRoundingMode<"int_riscv_vsmul", "PseudoVSMUL",
|
|
|
++ AllIntegerVectors>;
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.4. Vector Single-Width Scaling Shift Instructions
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-defm : VPatBinaryV_VV_VX_VI<"int_riscv_vssrl", "PseudoVSSRL", AllIntegerVectors,
|
|
|
+- uimm5>;
|
|
|
+-defm : VPatBinaryV_VV_VX_VI<"int_riscv_vssra", "PseudoVSSRA", AllIntegerVectors,
|
|
|
+- uimm5>;
|
|
|
++defm : VPatBinaryV_VV_VX_VIRoundingMode<"int_riscv_vssrl", "PseudoVSSRL",
|
|
|
++ AllIntegerVectors, uimm5>;
|
|
|
++defm : VPatBinaryV_VV_VX_VIRoundingMode<"int_riscv_vssra", "PseudoVSSRA",
|
|
|
++ AllIntegerVectors, uimm5>;
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ // 12.5. Vector Narrowing Fixed-Point Clip Instructions
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+-defm : VPatBinaryV_WV_WX_WI<"int_riscv_vnclipu", "PseudoVNCLIPU", AllWidenableIntVectors>;
|
|
|
+-defm : VPatBinaryV_WV_WX_WI<"int_riscv_vnclip", "PseudoVNCLIP", AllWidenableIntVectors>;
|
|
|
+-
|
|
|
++defm : VPatBinaryV_WV_WX_WIRoundingMode<"int_riscv_vnclipu", "PseudoVNCLIPU",
|
|
|
++ AllWidenableIntVectors>;
|
|
|
++defm : VPatBinaryV_WV_WX_WIRoundingMode<"int_riscv_vnclip", "PseudoVNCLIP",
|
|
|
++ AllWidenableIntVectors>;
|
|
|
+ } // Predicates = [HasVInstructions]
|
|
|
+
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp b/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp
|
|
|
+index 281918259cdb..7455df64c38a 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp
|
|
|
+@@ -159,6 +159,8 @@ static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI,
|
|
|
+ --NumOps;
|
|
|
+ if (RISCVII::hasVLOp(TSFlags))
|
|
|
+ --NumOps;
|
|
|
++ if (RISCVII::hasRoundModeOp(TSFlags))
|
|
|
++ --NumOps;
|
|
|
+ if (RISCVII::hasSEWOp(TSFlags))
|
|
|
+ --NumOps;
|
|
|
+
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
|
|
|
+index b9aa25b321b0..ced58fbb2a6d 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
|
|
|
+@@ -350,7 +350,7 @@ def : SysReg<"dscratch1", 0x7B3>;
|
|
|
+ //===----------------------------------------------------------------------===//
|
|
|
+ def : SysReg<"vstart", 0x008>;
|
|
|
+ def : SysReg<"vxsat", 0x009>;
|
|
|
+-def : SysReg<"vxrm", 0x00A>;
|
|
|
++def SysRegVXRM : SysReg<"vxrm", 0x00A>;
|
|
|
+ def : SysReg<"vcsr", 0x00F>;
|
|
|
+ def : SysReg<"vl", 0xC20>;
|
|
|
+ def : SysReg<"vtype", 0xC21>;
|
|
|
+diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
|
|
|
+index cc881406666c..28908e88f39f 100644
|
|
|
+--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
|
|
|
++++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
|
|
|
+@@ -81,6 +81,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
|
|
|
+ initializeRISCVPreRAExpandPseudoPass(*PR);
|
|
|
+ initializeRISCVExpandPseudoPass(*PR);
|
|
|
+ initializeRISCVInsertVSETVLIPass(*PR);
|
|
|
++ initializeRISCVInsertReadWriteCSRPass(*PR);
|
|
|
+ initializeRISCVDAGToDAGISelPass(*PR);
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -354,6 +355,7 @@ void RISCVPassConfig::addPreRegAlloc() {
|
|
|
+ if (TM->getOptLevel() != CodeGenOpt::None)
|
|
|
+ addPass(createRISCVMergeBaseOffsetOptPass());
|
|
|
+ addPass(createRISCVInsertVSETVLIPass());
|
|
|
++ addPass(createRISCVInsertReadWriteCSRPass());
|
|
|
+ }
|
|
|
+
|
|
|
+ void RISCVPassConfig::addPostRegAlloc() {
|
|
|
+--
|
|
|
+2.25.1
|
|
|
+
|