diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -148,6 +148,12 @@ [LLVMPointerType>, llvm_anyint_ty], [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; + // Input: (dest, pointer, vl) + class RISCVUSLoadTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMPointerType>, + llvm_anyint_ty], + [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; // For unit stride fault-only-first load // Input: (pointer, vl) // Output: (data, vl) @@ -158,6 +164,13 @@ [LLVMPointerType>, LLVMMatchType<1>], [NoCapture>]>, RISCVVIntrinsic; + // Input: (dest, pointer, vl) + class RISCVUSLoadFFTU + : Intrinsic<[llvm_anyvector_ty, llvm_anyint_ty], + [LLVMMatchType<0>, LLVMPointerType>, + LLVMMatchType<1>], + [NoCapture>]>, + RISCVVIntrinsic; // For unit stride load with mask // Input: (maskedoff, pointer, mask, vl, ta) class RISCVUSLoadMask @@ -187,6 +200,12 @@ [LLVMPointerType>, llvm_anyint_ty, LLVMMatchType<1>], [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; + // Input: (dest, pointer, stride, vl) + class RISCVSLoadTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMPointerType>, + llvm_anyint_ty, LLVMMatchType<1>], + [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; // For strided load with mask // Input: (maskedoff, pointer, stride, mask, vl, ta) class RISCVSLoadMask @@ -204,6 +223,12 @@ [LLVMPointerType>, llvm_anyvector_ty, llvm_anyint_ty], [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; + // Input: (dest, pointer, index, vl) + class RISCVILoadTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMPointerType>, + llvm_anyvector_ty, llvm_anyint_ty], + [NoCapture>, IntrReadMem]>, RISCVVIntrinsic; // For indexed load with mask // Input: (maskedoff, pointer, index, mask, vl, ta) class RISCVILoadMask @@ -269,6 +294,11 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vl) + class RISCVUnaryAATU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is the same as first source vector (with mask). // Input: (vector_in, mask, vl, ta) class RISCVUnaryAAMask @@ -294,6 +324,12 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMVectorOfBitcastsToInt<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, int_vector_in, vl) + class RISCVRGatherVVTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMVectorOfBitcastsToInt<0>, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is the same as first and second source vector. // Input: (vector_in, vector_in, int_vector_in, vl, ta) class RISCVRGatherVVMask @@ -308,6 +344,13 @@ [LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i16_ty>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, int16_vector_in, vl) + class RISCVRGatherEI16VVTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i16_ty>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is the same as first and second source vector. // Input: (vector_in, vector_in, int16_vector_in, vl, ta) class RISCVRGatherEI16VVMask @@ -325,6 +368,13 @@ [LLVMMatchType<0>, llvm_anyint_ty, LLVMMatchType<1>], [IntrNoMem]>, RISCVVIntrinsic { } + // Input: (dest, vector_in, xlen_in, vl) + class RISCVGatherVXTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty, + LLVMMatchType<1>], + [IntrNoMem]>, RISCVVIntrinsic { + } // For destination vector type is the same as first source vector (with mask). // Second operand is XLen. // Input: (maskedoff, vector_in, xlen_in, mask, vl, ta) @@ -343,6 +393,13 @@ [IntrNoMem]>, RISCVVIntrinsic { let SplatOperand = 2; } + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVBinaryAAXTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic { + let SplatOperand = 3; + } // For destination vector type is the same as first source vector (with mask). // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) class RISCVBinaryAAXMask @@ -360,6 +417,11 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVBinaryAAShiftTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is the same as first source vector (with mask). // The second source operand must match the destination type or be an XLen scalar. // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) @@ -377,6 +439,13 @@ [IntrNoMem]>, RISCVVIntrinsic { let SplatOperand = 2; } + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVBinaryABXTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic { + let SplatOperand = 3; + } // For destination vector type is NOT the same as first source vector (with mask). // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) class RISCVBinaryABXMask @@ -394,6 +463,11 @@ : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVBinaryABShiftTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is NOT the same as first source vector (with mask). // The second source operand must match the destination type or be an XLen scalar. // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta) @@ -413,6 +487,15 @@ [IntrNoMem]>, RISCVVIntrinsic { let SplatOperand = 2; } + // Input: (dest, vector_in, vector_in/scalar_in, V0, vl) + class RISCVBinaryWithV0TU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic { + let SplatOperand = 3; + } // For binary operations with mask type output and V0 as input. // Output: (mask type output) // Input: (vector_in, vector_in/scalar_in, V0, vl) @@ -460,6 +543,11 @@ : Intrinsic<[LLVMVectorOfBitcastsToInt<0>], [llvm_anyvector_ty, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vl) + class RISCVClassifyTU + : Intrinsic<[LLVMVectorOfBitcastsToInt<0>], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For FP classify operations with mask. // Output: (bit mask type output) // Input: (maskedoff, vector_in, mask, vl) @@ -477,6 +565,13 @@ [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { let SplatOperand = 2; } + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVSaturatingBinaryAAXTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { + let SplatOperand = 3; + } // 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, ta) @@ -496,6 +591,11 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVSaturatingBinaryAAShiftTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; // 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. @@ -514,6 +614,11 @@ : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vector_in/scalar_in, vl) + class RISCVSaturatingBinaryABShiftTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, llvm_anyint_ty], + [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; // 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. @@ -599,6 +704,11 @@ : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vl) + class RISCVUnaryABTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is NOT the same as source vector (with mask). // Input: (maskedoff, vector_in, mask, vl, ta) class RISCVUnaryABMask @@ -614,6 +724,11 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vl) + class RISCVUnaryTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For mask unary operations with mask type in/out with mask // Output: (mask type output) // Input: (mask type maskedoff, mask type vector_in, mask, vl) @@ -634,6 +749,11 @@ : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + // Input: (dest, vector_in, vl) + class RISCVConversionTU + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; // For Conversion unary operations with mask. // Input: (maskedoff, vector_in, mask, vl, ta) class RISCVConversionMask @@ -802,18 +922,22 @@ multiclass RISCVUSLoad { def "int_riscv_" # NAME : RISCVUSLoad; + def "int_riscv_" # NAME # "_tu" : RISCVUSLoadTU; def "int_riscv_" # NAME # "_mask" : RISCVUSLoadMask; } multiclass RISCVUSLoadFF { def "int_riscv_" # NAME : RISCVUSLoadFF; + def "int_riscv_" # NAME # "_tu" : RISCVUSLoadFFTU; def "int_riscv_" # NAME # "_mask" : RISCVUSLoadFFMask; } multiclass RISCVSLoad { def "int_riscv_" # NAME : RISCVSLoad; + def "int_riscv_" # NAME # "_tu" : RISCVSLoadTU; def "int_riscv_" # NAME # "_mask" : RISCVSLoadMask; } multiclass RISCVILoad { def "int_riscv_" # NAME : RISCVILoad; + def "int_riscv_" # NAME # "_tu" : RISCVILoadTU; def "int_riscv_" # NAME # "_mask" : RISCVILoadMask; } multiclass RISCVUSStore { @@ -831,50 +955,60 @@ } multiclass RISCVUnaryAA { def "int_riscv_" # NAME : RISCVUnaryAANoMask; + def "int_riscv_" # NAME # "_tu" : RISCVUnaryAATU; def "int_riscv_" # NAME # "_mask" : RISCVUnaryAAMask; } multiclass RISCVUnaryAB { def "int_riscv_" # NAME : RISCVUnaryABNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVUnaryABTU; def "int_riscv_" # NAME # "_mask" : RISCVUnaryABMask; } // AAX means the destination type(A) is the same as the first source // type(A). X means any type for the second source operand. multiclass RISCVBinaryAAX { def "int_riscv_" # NAME : RISCVBinaryAAXNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVBinaryAAXTU; def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAXMask; } // Like RISCVBinaryAAX, but the second operand is used a shift amount so it // must be a vector or an XLen scalar. multiclass RISCVBinaryAAShift { def "int_riscv_" # NAME : RISCVBinaryAAShiftNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVBinaryAAShiftTU; def "int_riscv_" # NAME # "_mask" : RISCVBinaryAAShiftMask; } multiclass RISCVRGatherVV { def "int_riscv_" # NAME : RISCVRGatherVVNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVRGatherVVTU; def "int_riscv_" # NAME # "_mask" : RISCVRGatherVVMask; } multiclass RISCVRGatherVX { def "int_riscv_" # NAME : RISCVGatherVXNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVGatherVXTU; def "int_riscv_" # NAME # "_mask" : RISCVGatherVXMask; } multiclass RISCVRGatherEI16VV { def "int_riscv_" # NAME : RISCVRGatherEI16VVNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVRGatherEI16VVTU; def "int_riscv_" # NAME # "_mask" : RISCVRGatherEI16VVMask; } // ABX means the destination type(A) is different from the first source // type(B). X means any type for the second source operand. multiclass RISCVBinaryABX { def "int_riscv_" # NAME : RISCVBinaryABXNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVBinaryABXTU; def "int_riscv_" # NAME # "_mask" : RISCVBinaryABXMask; } // Like RISCVBinaryABX, but the second operand is used a shift amount so it // must be a vector or an XLen scalar. multiclass RISCVBinaryABShift { def "int_riscv_" # NAME : RISCVBinaryABShiftNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVBinaryABShiftTU; def "int_riscv_" # NAME # "_mask" : RISCVBinaryABShiftMask; } multiclass RISCVBinaryWithV0 { def "int_riscv_" # NAME : RISCVBinaryWithV0; + def "int_riscv_" # NAME # "_tu" : RISCVBinaryWithV0TU; } multiclass RISCVBinaryMaskOutWithV0 { def "int_riscv_" # NAME : RISCVBinaryMOutWithV0; @@ -884,22 +1018,27 @@ } multiclass RISCVSaturatingBinaryAAX { def "int_riscv_" # NAME : RISCVSaturatingBinaryAAXNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVSaturatingBinaryAAXTU; def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAXMask; } multiclass RISCVSaturatingBinaryAAShift { def "int_riscv_" # NAME : RISCVSaturatingBinaryAAShiftNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVSaturatingBinaryAAShiftTU; def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryAAShiftMask; } multiclass RISCVSaturatingBinaryABShift { def "int_riscv_" # NAME : RISCVSaturatingBinaryABShiftNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVSaturatingBinaryABShiftTU; def "int_riscv_" # NAME # "_mask" : RISCVSaturatingBinaryABShiftMask; } multiclass RISCVTernaryAAAX { def "int_riscv_" # NAME : RISCVTernaryAAAXNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVTernaryAAAXNoMask; def "int_riscv_" # NAME # "_mask" : RISCVTernaryAAAXMask; } multiclass RISCVTernaryAAXA { def "int_riscv_" # NAME : RISCVTernaryAAXANoMask; + def "int_riscv_" # NAME # "_tu" : RISCVTernaryAAXANoMask; def "int_riscv_" # NAME # "_mask" : RISCVTernaryAAXAMask; } multiclass RISCVCompare { @@ -908,14 +1047,17 @@ } multiclass RISCVClassify { def "int_riscv_" # NAME : RISCVClassifyNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVClassifyTU; def "int_riscv_" # NAME # "_mask" : RISCVClassifyMask; } multiclass RISCVTernaryWide { def "int_riscv_" # NAME : RISCVTernaryWideNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVTernaryWideNoMask; def "int_riscv_" # NAME # "_mask" : RISCVTernaryWideMask; } multiclass RISCVReduction { def "int_riscv_" # NAME : RISCVReductionNoMask; + def "int_riscv_" # NAME # "_tu" : RISCVReductionNoMask; def "int_riscv_" # NAME # "_mask" : RISCVReductionMask; } multiclass RISCVMaskUnarySOut { @@ -928,6 +1070,7 @@ } multiclass RISCVConversion { def "int_riscv_" #NAME :RISCVConversionNoMask; + def "int_riscv_" #NAME # "_tu" :RISCVConversionTU; def "int_riscv_" # NAME # "_mask" : RISCVConversionMask; } multiclass RISCVAMO { @@ -1080,12 +1223,24 @@ def int_riscv_vmv_v_v : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + def int_riscv_vmv_v_v_tu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; def int_riscv_vmv_v_x : Intrinsic<[llvm_anyint_ty], [LLVMVectorElementType<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + def int_riscv_vmv_v_x_tu : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMVectorElementType<0>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; def int_riscv_vfmv_v_f : Intrinsic<[llvm_anyfloat_ty], [LLVMVectorElementType<0>, llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; + def int_riscv_vfmv_v_f_tu : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMVectorElementType<0>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; def int_riscv_vmv_x_s : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyint_ty], @@ -1151,6 +1306,7 @@ defm vrgatherei16_vv : RISCVRGatherEI16VV; def "int_riscv_vcompress" : RISCVUnaryAAMaskNoTA; + def "int_riscv_vcompress_tu" : RISCVUnaryAAMaskNoTA; defm vaaddu : RISCVSaturatingBinaryAAX; defm vaadd : RISCVSaturatingBinaryAAX; @@ -1240,6 +1396,13 @@ llvm_anyint_ty], [IntrNoMem]>, RISCVVIntrinsic; // Output: (vector) + // Input: (dest, mask type input, vl) + def int_riscv_viota_tu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; + // Output: (vector) // Input: (maskedoff, mask type vector_in, mask, vl) def int_riscv_viota_mask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, @@ -1251,6 +1414,13 @@ // Input: (vl) def int_riscv_vid : RISCVNullaryIntrinsic; + // Output: (vector) + // Input: (dest, vl) + def int_riscv_vid_tu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + llvm_anyint_ty], + [IntrNoMem]>, RISCVVIntrinsic; + // Output: (vector) // Input: (maskedoff, mask, vl) def int_riscv_vid_mask : Intrinsic<[llvm_anyvector_ty], diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -582,11 +582,12 @@ !subst("_B32", "", !subst("_B64", "", !subst("_MASK", "", + !subst("_TU", "", !subst("_TIED", "", !subst("F16", "F", !subst("F32", "F", !subst("F64", "F", - !subst("Pseudo", "", PseudoInst)))))))))))))))))))); + !subst("Pseudo", "", PseudoInst))))))))))))))))))))); } // The destination vector register group for a masked vector instruction cannot @@ -642,6 +643,22 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoUSLoadTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, GPR:$rs1, AVL:$vl, ixlenimm:$sew),[]>, + RISCVVPseudo, + RISCVVLE.val, VLMul> { + let mayLoad = 1; + let mayStore = 0; + let hasSideEffects = 0; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasDummyMask = 1; + let HasMergeOp = 1; + let Constraints = "$rd = $dest"; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoUSLoadMask : Pseudo<(outs GetVRegNoV0.R:$rd), (ins GetVRegNoV0.R:$merge, @@ -674,6 +691,22 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoSLoadTU: + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, GPR:$rs1, GPR:$rs2, AVL:$vl, ixlenimm:$sew),[]>, + RISCVVPseudo, + RISCVVLE.val, VLMul> { + let mayLoad = 1; + let mayStore = 0; + let hasSideEffects = 0; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasDummyMask = 1; + let HasMergeOp = 1; + let Constraints = "$rd = $dest"; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoSLoadMask: Pseudo<(outs GetVRegNoV0.R:$rd), (ins GetVRegNoV0.R:$merge, @@ -708,6 +741,23 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoILoadTU LMUL, + bit Ordered, bit EarlyClobber>: + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, GPR:$rs1, IdxClass:$rs2, AVL:$vl, ixlenimm:$sew),[]>, + RISCVVPseudo, + RISCVVLX.val, VLMul, LMUL> { + let mayLoad = 1; + let mayStore = 0; + let hasSideEffects = 0; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasDummyMask = 1; + let Constraints = !if(!eq(EarlyClobber, 1), "@earlyclobber $rd, $rd = $dest", "$rd = $dest"); + let HasMergeOp = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoILoadMask LMUL, bit Ordered, bit EarlyClobber>: Pseudo<(outs GetVRegNoV0.R:$rd), @@ -795,6 +845,21 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoUnaryNoDummyMaskTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, Op2Class:$rs1, AVL:$vl, ixlenimm:$sew), []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let Constraints = "$rd = $dest"; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoNullaryNoMask: Pseudo<(outs RegClass:$rd), (ins AVL:$vl, ixlenimm:$sew), @@ -808,6 +873,21 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoNullaryNoMaskTU: + Pseudo<(outs RegClass:$rd), + (ins RegClass:$dest, AVL:$vl, ixlenimm:$sew), + []>, RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasDummyMask = 1; + let HasMergeOp = 1; + let Constraints = "$rd = $dest"; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoNullaryMask: Pseudo<(outs GetVRegNoV0.R:$rd), (ins GetVRegNoV0.R:$merge, VMaskOp:$vm, AVL:$vl, @@ -852,6 +932,21 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoUnaryNoMaskTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, OpClass:$rs2, AVL:$vl, ixlenimm:$sew), []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = Join<[Constraint, "$rd = $dest"], ",">.ret; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasDummyMask = 1; + let HasMergeOp = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoUnaryMask : Pseudo<(outs GetVRegNoV0.R:$rd), (ins GetVRegNoV0.R:$merge, OpClass:$rs2, @@ -915,6 +1010,24 @@ let BaseInstr = !cast(PseudoToVInst.VInst); } +class VPseudoUnaryAnyMaskTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$merge, + Op1Class:$rs2, + VR:$vm, AVL:$vl, ixlenimm:$sew), + []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = "@earlyclobber $rd, $rd = $merge"; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoBinaryNoMask(PseudoToVInst.VInst); } +class VPseudoBinaryTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$dest, Op1Class:$rs2, Op2Class:$rs1, AVL:$vl, ixlenimm:$sew), []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = Join<[Constraint, "$rd = $dest"], ",">.ret; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let HasDummyMask = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoTiedBinaryNoMask : @@ -1083,6 +1214,29 @@ let VLMul = MInfo.value; } +class VPseudoBinaryCarryInTU : + Pseudo<(outs RetClass:$rd), + !if(CarryIn, + (ins RetClass:$dest, Op1Class:$rs2, Op2Class:$rs1, VMV0:$carry, AVL:$vl, + ixlenimm:$sew), + (ins RetClass:$dest, Op1Class:$rs2, Op2Class:$rs1, AVL:$vl, ixlenimm:$sew)), []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = Join<[Constraint, "$rd = $dest"], ",">.ret; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); + let VLMul = MInfo.value; +} + class VPseudoTernaryNoMask(PseudoToVInst.VInst); } +class VPseudoTernaryNoMaskTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$rs3, Op1Class:$rs1, Op2Class:$rs2, + AVL:$vl, ixlenimm:$sew), + []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = Join<[Constraint, "$rd = $rs3"], ",">.ret; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let HasDummyMask = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoTernaryNoMaskWithPolicy(PseudoToVInst.VInst); } +class VPseudoTernaryTU : + Pseudo<(outs RetClass:$rd), + (ins RetClass:$rs3, Op1Class:$rs1, Op2Class:$rs2, + AVL:$vl, ixlenimm:$sew), + []>, + RISCVVPseudo { + let mayLoad = 0; + let mayStore = 0; + let hasSideEffects = 0; + let Constraints = Join<[Constraint, "$rd = $rs3"], ",">.ret; + let HasVLOp = 1; + let HasSEWOp = 1; + let HasMergeOp = 1; + let HasDummyMask = 1; + let BaseInstr = !cast(PseudoToVInst.VInst); +} + class VPseudoAMOWDNoMask : Pseudo<(outs GetVRegNoV0.R:$vd_wd), @@ -1385,6 +1579,8 @@ let VLMul = lmul.value in { def "E" # eew # FFStr # "_V_" # LInfo : VPseudoUSLoadNoMask; + def "E" # eew # FFStr # "_V_" # LInfo # "_TU" : + VPseudoUSLoadTU; def "E" # eew # FFStr # "_V_" # LInfo # "_MASK" : VPseudoUSLoadMask; } @@ -1407,6 +1603,7 @@ defvar vreg = lmul.vrclass; let VLMul = lmul.value in { def "E" # eew # "_V_" # LInfo : VPseudoSLoadNoMask; + def "E" # eew # "_V_" # LInfo # "_TU" : VPseudoSLoadTU; def "E" # eew # "_V_" # LInfo # "_MASK" : VPseudoSLoadMask; } } @@ -1430,6 +1627,8 @@ let VLMul = lmul.value in { def "EI" # eew # "_V_" # IdxLInfo # "_" # LInfo : VPseudoILoadNoMask; + def "EI" # eew # "_V_" # IdxLInfo # "_" # LInfo # "_TU" : + VPseudoILoadTU; def "EI" # eew # "_V_" # IdxLInfo # "_" # LInfo # "_MASK" : VPseudoILoadMask; } @@ -1523,6 +1722,7 @@ foreach m = MxList.m in { let VLMul = m.value in { def "_V_" # m.MX : VPseudoNullaryNoMask; + def "_V_" # m.MX # "_TU" : VPseudoNullaryNoMaskTU; def "_V_" # m.MX # "_MASK" : VPseudoNullaryMask; } } @@ -1541,6 +1741,7 @@ foreach m = MxList.m in { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask; + def "_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_" # m.MX # "_MASK" : VPseudoUnaryMask; } } @@ -1550,6 +1751,7 @@ foreach m = MxList.m in { let VLMul = m.value in def _VM # "_" # m.MX : VPseudoUnaryAnyMask; + def _VM # "_" # m.MX # "_TU" : VPseudoUnaryAnyMaskTU; } } @@ -1561,6 +1763,8 @@ let VLMul = MInfo.value in { def "_" # MInfo.MX : VPseudoBinaryNoMask; + def "_" # MInfo.MX # "_TU" : VPseudoBinaryTU; def "_" # MInfo.MX # "_MASK" : VPseudoBinaryMaskTA; } @@ -1589,6 +1793,8 @@ let VLMul = lmul.value in { def "_" # lmul.MX # "_" # emul.MX : VPseudoBinaryNoMask; + def "_" # lmul.MX # "_" # emul.MX # "_TU" : VPseudoBinaryTU; def "_" # lmul.MX # "_" # emul.MX # "_MASK" : VPseudoBinaryMaskTA; } @@ -1734,6 +1940,22 @@ m.vrclass, m.vrclass, m, CarryIn, Constraint>; } +multiclass VPseudoBinaryV_VM_WithTU { + foreach m = MxList.m in { + def "_VV" # !if(CarryIn, "M", "") # "_" # m.MX : + VPseudoBinaryCarryIn.R, m.vrclass)), + m.vrclass, m.vrclass, m, CarryIn, Constraint>; + def "_VV" # !if(CarryIn, "M", "") # "_" # m.MX # "_TU" : + VPseudoBinaryCarryInTU.R, m.vrclass)), + m.vrclass, m.vrclass, m, CarryIn, Constraint>; + } +} + multiclass VPseudoBinaryV_XM { foreach m = MxList.m in @@ -1744,12 +1966,32 @@ m.vrclass, GPR, m, CarryIn, Constraint>; } +multiclass VPseudoBinaryV_XM_WithTU { + foreach m = MxList.m in { + def "_VX" # !if(CarryIn, "M", "") # "_" # m.MX : + VPseudoBinaryCarryIn.R, m.vrclass)), + m.vrclass, GPR, m, CarryIn, Constraint>; + def "_VX" # !if(CarryIn, "M", "") # "_" # m.MX # "_TU" : + VPseudoBinaryCarryInTU.R, m.vrclass)), + m.vrclass, GPR, m, CarryIn, Constraint>; + } +} + multiclass VPseudoBinaryV_FM { foreach m = MxList.m in - foreach f = FPList.fpinfo in + foreach f = FPList.fpinfo in { def "_V" # f.FX # "M_" # m.MX : VPseudoBinaryCarryIn.R, m.vrclass, f.fprclass, m, /*CarryIn=*/1, "">; + def "_V" # f.FX # "M_" # m.MX # "_TU" : + VPseudoBinaryCarryInTU.R, + m.vrclass, f.fprclass, m, /*CarryIn=*/1, "">; + } } multiclass VPseudoBinaryV_IM; } +multiclass VPseudoBinaryV_IM_WithTU { + foreach m = MxList.m in { + def "_VI" # !if(CarryIn, "M", "") # "_" # m.MX : + VPseudoBinaryCarryIn.R, m.vrclass)), + m.vrclass, simm5, m, CarryIn, Constraint>; + def "_VI" # !if(CarryIn, "M", "") # "_" # m.MX # "_TU" : + VPseudoBinaryCarryInTU.R, m.vrclass)), + m.vrclass, simm5, m, CarryIn, Constraint>; + } +} + multiclass VPseudoUnaryV_V_X_I_NoDummyMask { foreach m = MxList.m in { let VLMul = m.value in { def "_V_" # m.MX : VPseudoUnaryNoDummyMask; + def "_V_" # m.MX # "_TU" : VPseudoUnaryNoDummyMaskTU; def "_X_" # m.MX : VPseudoUnaryNoDummyMask; + def "_X_" # m.MX # "_TU" : VPseudoUnaryNoDummyMaskTU; def "_I_" # m.MX : VPseudoUnaryNoDummyMask; + def "_I_" # m.MX # "_TU" : VPseudoUnaryNoDummyMaskTU; } } } @@ -1777,6 +2038,8 @@ foreach f = FPList.fpinfo in { let VLMul = m.value in { def "_" # f.FX # "_" # m.MX : VPseudoUnaryNoDummyMask; + def "_" # f.FX # "_" # m.MX # "_TU" : + VPseudoUnaryNoDummyMaskTU; } } } @@ -1786,6 +2049,7 @@ foreach m = MxList.m in { let VLMul = m.value in { def "_V_" # m.MX : VPseudoUnaryNoMask; + def "_V_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_V_" # m.MX # "_MASK" : VPseudoUnaryMaskTA; } } @@ -1795,6 +2059,7 @@ foreach m = MxList.m in { let VLMul = m.value in { def "_V_" # m.MX : VPseudoUnaryNoMask; + def "_V_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_V_" # m.MX # "_MASK" : VPseudoUnaryMask; } } @@ -1806,6 +2071,7 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask; + def "_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA; } @@ -1818,6 +2084,7 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask; + def "_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA; } @@ -1830,6 +2097,7 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask; + def "_" # m.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA; } @@ -1916,14 +2184,14 @@ } multiclass VPseudoBinaryV_VM_XM_IM { - defm "" : VPseudoBinaryV_VM; - defm "" : VPseudoBinaryV_XM; - defm "" : VPseudoBinaryV_IM; + defm "" : VPseudoBinaryV_VM_WithTU; + defm "" : VPseudoBinaryV_XM_WithTU; + defm "" : VPseudoBinaryV_IM_WithTU; } multiclass VPseudoBinaryV_VM_XM { - defm "" : VPseudoBinaryV_VM; - defm "" : VPseudoBinaryV_XM; + defm "" : VPseudoBinaryV_VM_WithTU; + defm "" : VPseudoBinaryV_XM_WithTU; } multiclass VPseudoBinaryM_VM_XM_IM { @@ -1961,6 +2229,7 @@ string Constraint = ""> { let VLMul = MInfo.value in { def "_" # MInfo.MX : VPseudoTernaryNoMask; + def "_" # MInfo.MX # "_TU" : VPseudoTernaryNoMaskTU; def "_" # MInfo.MX # "_MASK" : VPseudoBinaryMask; } } @@ -1974,6 +2243,7 @@ let VLMul = MInfo.value in { let isCommutable = Commutable in def "_" # MInfo.MX : VPseudoTernaryNoMaskWithPolicy; + def "_" # MInfo.MX # "_TU" : VPseudoTernaryTU; def "_" # MInfo.MX # "_MASK" : VPseudoBinaryMask; } } @@ -2089,6 +2359,7 @@ string Constraint = ""> { let VLMul = MInfo.value in { def "_" # MInfo.MX : VPseudoUnaryNoMask; + def "_" # MInfo.MX # "_TU" : VPseudoUnaryNoMaskTU; def "_" # MInfo.MX # "_MASK" : VPseudoUnaryMaskTA; } @@ -2253,6 +2524,24 @@ (op2_type op2_reg_class:$rs2), GPR:$vl, sew)>; +class VPatUnaryNoMaskTU : + Pat<(result_type (!cast(intrinsic_name#"_tu") + (result_type result_reg_class:$dest), + (op2_type op2_reg_class:$rs2), + VLOpFrag)), + (!cast(inst#"_"#kind#"_"#vlmul.MX#"_TU") + (result_type result_reg_class:$dest), + (op2_type op2_reg_class:$rs2), + GPR:$vl, sew)>; + class VPatUnaryMask; +class VPatUnaryAnyMaskTU : + Pat<(result_type (!cast(intrinsic#"_tu") + (result_type result_reg_class:$merge), + (op1_type op1_reg_class:$rs1), + (mask_type VR:$rs2), + VLOpFrag)), + (!cast(inst#"_"#kind#"_"#vlmul.MX#"_TU") + (result_type result_reg_class:$merge), + (op1_type op1_reg_class:$rs1), + (mask_type VR:$rs2), + GPR:$vl, sew)>; + class VPatBinaryNoMask; +class VPatBinaryTU : + Pat<(result_type (!cast(intrinsic_name#"_tu") + (result_type result_reg_class:$dest), + (op1_type op1_reg_class:$rs1), + (op2_type op2_kind:$rs2), + VLOpFrag)), + (!cast(inst#"_TU") + (result_type result_reg_class:$dest), + (op1_type op1_reg_class:$rs1), + (op2_type op2_kind:$rs2), + GPR:$vl, sew)>; + // Same as above but source operands are swapped. class VPatBinaryNoMaskSwapped; +class VPatTernaryNoMaskTU : + Pat<(result_type (!cast(intrinsic#"_tu") + (result_type result_reg_class:$rs3), + (op1_type op1_reg_class:$rs1), + (op2_type op2_kind:$rs2), + VLOpFrag)), + (!cast(inst#"_"#kind#"_"#vlmul.MX#"_TU") + result_reg_class:$rs3, + (op1_type op1_reg_class:$rs1), + op2_kind:$rs2, + GPR:$vl, sew)>; + class VPatTernaryMask; + def : VPatUnaryAnyMaskTU; } } @@ -2618,6 +2974,8 @@ foreach vti = AllIntegerVectors in { def : VPatUnaryNoMask; + def : VPatUnaryNoMaskTU; def : VPatUnaryMask; } @@ -2633,6 +2991,9 @@ def : VPatUnaryNoMask; + def : VPatUnaryNoMaskTU; def : VPatUnaryMaskTA; @@ -2645,6 +3006,9 @@ def : VPatUnaryNoMask; + def : VPatUnaryNoMaskTU; def : VPatUnaryMaskTA; @@ -2658,6 +3022,12 @@ VLOpFrag)), (!cast(instruction#"_V_" # vti.LMul.MX) GPR:$vl, vti.Log2SEW)>; + def : Pat<(vti.Vector (!cast(intrinsic # "_tu") + (vti.Vector vti.RegClass:$dest), + VLOpFrag)), + (!cast(instruction#"_V_" # vti.LMul.MX # "_TU") + vti.RegClass:$dest, + GPR:$vl, vti.Log2SEW)>; def : Pat<(vti.Vector (!cast(intrinsic # "_mask") (vti.Vector vti.RegClass:$merge), (vti.Mask V0), VLOpFrag)), @@ -2706,6 +3076,8 @@ { def : VPatBinaryNoMask; + def : VPatBinaryTU; def : VPatBinaryMaskTA; @@ -2752,6 +3124,32 @@ (mask_type V0), GPR:$vl, sew)>; } +multiclass VPatBinaryCarryInTU +{ + def : Pat<(result_type (!cast(intrinsic#"_tu") + (result_type result_reg_class:$dest), + (op1_type op1_reg_class:$rs1), + (op2_type op2_kind:$rs2), + (mask_type V0), + VLOpFrag)), + (!cast(inst#"_"#kind#"_"#vlmul.MX#"_TU") + (result_type result_reg_class:$dest), + (op1_type op1_reg_class:$rs1), + (op2_type op2_kind:$rs2), + (mask_type V0), GPR:$vl, sew)>; +} + multiclass VPatBinaryMaskOut; + def : VPatUnaryNoMaskTU; def : VPatUnaryMask; } @@ -2803,6 +3203,8 @@ { def : VPatUnaryNoMask; + def : VPatUnaryNoMaskTU; def : VPatUnaryMaskTA; } @@ -2915,6 +3317,9 @@ def : VPatTiedBinaryNoMask; + def : VPatBinaryTU; let AddedComplexity = 1 in def : VPatTiedBinaryMask; } +multiclass VPatBinaryV_VM_WithTU vtilist = AllIntegerVectors> { + foreach vti = vtilist in { + defm : VPatBinaryCarryIn; + defm : VPatBinaryCarryInTU; + } +} + multiclass VPatBinaryV_XM vtilist = AllIntegerVectors> { @@ -2999,6 +3421,25 @@ vti.RegClass, vti.ScalarRegClass>; } +multiclass VPatBinaryV_XM_WithTU vtilist = AllIntegerVectors> { + foreach vti = vtilist in { + defm : VPatBinaryCarryIn; + defm : VPatBinaryCarryInTU; + } +} + multiclass VPatBinaryV_IM { foreach vti = AllIntegerVectors in @@ -3009,6 +3450,22 @@ vti.RegClass, simm5>; } +multiclass VPatBinaryV_IM_WithTU { + foreach vti = AllIntegerVectors in { + defm : VPatBinaryCarryIn; + defm : VPatBinaryCarryInTU; + } +} + multiclass VPatBinaryV_V { foreach vti = AllIntegerVectors in defm : VPatBinaryMaskOut; multiclass VPatBinaryV_VM_XM_IM - : VPatBinaryV_VM, - VPatBinaryV_XM, - VPatBinaryV_IM; + : VPatBinaryV_VM_WithTU, + VPatBinaryV_XM_WithTU, + VPatBinaryV_IM_WithTU; multiclass VPatBinaryM_VM_XM_IM : VPatBinaryV_VM, @@ -3119,8 +3576,8 @@ VPatBinaryV_I; multiclass VPatBinaryV_VM_XM - : VPatBinaryV_VM, - VPatBinaryV_XM; + : VPatBinaryV_VM_WithTU, + VPatBinaryV_XM_WithTU; multiclass VPatBinaryM_VM_XM : VPatBinaryV_VM, @@ -3145,6 +3602,9 @@ def : VPatTernaryNoMask; + def : VPatTernaryNoMaskTU; def : VPatTernaryMask; @@ -3165,6 +3625,9 @@ def : VPatTernaryNoMaskWithPolicy; + def : VPatTernaryNoMaskTU; def : VPatTernaryMask; @@ -3615,6 +4078,16 @@ vti.RegClass:$rs2, GPR:$vl, vti.Log2SEW)>; + def : Pat<(vti.Vector (int_riscv_vrsub_tu (vti.Vector vti.RegClass:$dest), + (vti.Vector vti.RegClass:$rs2), + (vti.Vector vti.RegClass:$rs1), + VLOpFrag)), + (!cast("PseudoVSUB_VV_"#vti.LMul.MX#"_TU") + vti.RegClass:$dest, + vti.RegClass:$rs1, + vti.RegClass:$rs2, + GPR:$vl, + vti.Log2SEW)>; def : Pat<(vti.Vector (int_riscv_vrsub_mask (vti.Vector vti.RegClass:$merge), (vti.Vector vti.RegClass:$rs2), (vti.Vector vti.RegClass:$rs1), @@ -3638,6 +4111,16 @@ (NegImm simm5_plus1:$rs2), GPR:$vl, vti.Log2SEW)>; + def : Pat<(vti.Vector (int_riscv_vsub_tu (vti.Vector vti.RegClass:$dest), + (vti.Vector vti.RegClass:$rs1), + (vti.Scalar simm5_plus1:$rs2), + VLOpFrag)), + (!cast("PseudoVADD_VI_"#vti.LMul.MX#"_TU") + vti.RegClass:$dest, + vti.RegClass:$rs1, + (NegImm simm5_plus1:$rs2), + GPR:$vl, + vti.Log2SEW)>; def : Pat<(vti.Vector (int_riscv_vsub_mask (vti.Vector vti.RegClass:$merge), (vti.Vector vti.RegClass:$rs1), (vti.Scalar simm5_plus1:$rs2), @@ -4436,6 +4919,11 @@ VLOpFrag)), (!cast("PseudoVMV_V_V_"#vti.LMul.MX) $rs1, GPR:$vl, vti.Log2SEW)>; + def : Pat<(vti.Vector (int_riscv_vmv_v_v_tu (vti.Vector vti.RegClass:$dest), + (vti.Vector vti.RegClass:$rs1), + VLOpFrag)), + (!cast("PseudoVMV_V_V_"#vti.LMul.MX#"_TU") + $dest, $rs1, GPR:$vl, vti.Log2SEW)>; // vmv.v.x/vmv.v.i are handled in RISCInstrVInstrInfoVVLPatterns.td } @@ -4574,10 +5062,10 @@ // 14.15. Vector Floating-Point Merge Instruction //===----------------------------------------------------------------------===// // We can use vmerge.vvm to support vector-vector vfmerge. -defm : VPatBinaryV_VM<"int_riscv_vfmerge", "PseudoVMERGE", - /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; -defm : VPatBinaryV_XM<"int_riscv_vfmerge", "PseudoVFMERGE", - /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; +defm : VPatBinaryV_VM_WithTU<"int_riscv_vfmerge", "PseudoVMERGE", + /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; +defm : VPatBinaryV_XM_WithTU<"int_riscv_vfmerge", "PseudoVFMERGE", + /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; foreach fvti = AllFloatVectors in { defvar instr = !cast("PseudoVMERGE_VIM_"#fvti.LMul.MX); diff --git a/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll b/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs \ +; RUN: < %s | FileCheck %s + +declare @llvm.riscv.vadd.nxv1i8.nxv1i8( + , + , + i64); + +declare @llvm.riscv.vadd.tu.nxv1i8.nxv1i8( + , + , + , + i64); + +define @switch_tail_policy( %0, %1, i64 %2) nounwind { +; CHECK-LABEL: switch_tail_policy: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, mu +; CHECK-NEXT: vmv1r.v v25, v8 +; CHECK-NEXT: vadd.vv v25, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e8, mf8, ta, mu +; CHECK-NEXT: vadd.vv v25, v8, v25 +; CHECK-NEXT: vsetvli zero, zero, e8, mf8, tu, mu +; CHECK-NEXT: vadd.vv v8, v8, v25 +; CHECK-NEXT: ret +entry: + %a = call @llvm.riscv.vadd.tu.nxv1i8.nxv1i8( + %0, + %0, + %1, + i64 %2) + + %b = call @llvm.riscv.vadd.nxv1i8.nxv1i8( + %0, + %a, + i64 %2) + + %c = call @llvm.riscv.vadd.tu.nxv1i8.nxv1i8( + %0, + %0, + %b, + i64 %2) + + ret %c +} + +define @intrinsic_vadd_vv_tu_nxv1i8_nxv1i8_nxv1i8( %0, %1, i64 %2) nounwind { +; CHECK-LABEL: intrinsic_vadd_vv_tu_nxv1i8_nxv1i8_nxv1i8: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, mu +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: ret +entry: + %a = call @llvm.riscv.vadd.tu.nxv1i8.nxv1i8( + %0, + %0, + %1, + i64 %2) + + ret %a +}