HsiangKai updated this revision to Diff 358205. HsiangKai added a comment. Add the TA argument to most of the intrinsics with mask.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D105092/new/ https://reviews.llvm.org/D105092 Files: clang/include/clang/Basic/riscv_vector.td clang/test/CodeGen/RISCV/rvv-intrinsics/vadd-policy.c clang/utils/TableGen/RISCVVEmitter.cpp llvm/include/llvm/IR/IntrinsicsRISCV.td llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp llvm/lib/Target/RISCV/RISCVInstrFormats.td llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td llvm/test/CodeGen/RISCV/rvv/vadd-policy.ll
Index: llvm/test/CodeGen/RISCV/rvv/vadd-policy.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/rvv/vadd-policy.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs \ +; RUN: --riscv-no-aliases < %s | FileCheck %s + +declare <vscale x 8 x i8> @llvm.riscv.vadd.nxv8i8.nxv8i8( + <vscale x 8 x i8>, + <vscale x 8 x i8>, + i64); + +define <vscale x 8 x i8> @intrinsic_vadd_vv_nxv8i8_nxv8i8_nxv8i8(<vscale x 8 x i8> %0, <vscale x 8 x i8> %1, i64 %2) nounwind { +; CHECK-LABEL: intrinsic_vadd_vv_nxv8i8_nxv8i8_nxv8i8: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli zero, a0, e8, m1, ta, mu +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: jalr zero, 0(ra) +entry: + %a = call <vscale x 8 x i8> @llvm.riscv.vadd.nxv8i8.nxv8i8( + <vscale x 8 x i8> %0, + <vscale x 8 x i8> %1, + i64 %2) + + ret <vscale x 8 x i8> %a +} + +declare <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8( + <vscale x 8 x i8>, + <vscale x 8 x i8>, + <vscale x 8 x i8>, + <vscale x 8 x i1>, + i64, i64); + +define <vscale x 8 x i8> @intrinsic_vadd_mask_tu(<vscale x 8 x i8> %0, <vscale x 8 x i8> %1, <vscale x 8 x i8> %2, <vscale x 8 x i1> %3, i64 %4) nounwind { +; CHECK-LABEL: intrinsic_vadd_mask_tu: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 3, e8, m1, tu, mu +; CHECK-NEXT: vadd.vv v8, v9, v10, v0.t +; CHECK-NEXT: jalr zero, 0(ra) +entry: + %a = call <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8( + <vscale x 8 x i8> %0, + <vscale x 8 x i8> %1, + <vscale x 8 x i8> %2, + <vscale x 8 x i1> %3, + i64 %4, i64 0) + + ret <vscale x 8 x i8> %a +} + +define <vscale x 8 x i8> @intrinsic_vadd_mask_ta(<vscale x 8 x i8> %0, <vscale x 8 x i8> %1, <vscale x 8 x i8> %2, <vscale x 8 x i1> %3, i64 %4) nounwind { +; CHECK-LABEL: intrinsic_vadd_mask_ta: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 3, e8, m1, ta, mu +; CHECK-NEXT: vadd.vv v8, v9, v10, v0.t +; CHECK-NEXT: jalr zero, 0(ra) +entry: + %a = call <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8( + <vscale x 8 x i8> %0, + <vscale x 8 x i8> %1, + <vscale x 8 x i8> %2, + <vscale x 8 x i1> %3, + i64 %4, i64 1) + + ret <vscale x 8 x i8> %a +} + Index: llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -22,6 +22,9 @@ // Helpers to define the VL patterns. //===----------------------------------------------------------------------===// +defvar TAIL_AGNOSTIC = 0; +defvar TAIL_UNDISTURBED = 1; + def SDT_RISCVVLE_VL : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVT<2, XLenVT>]>; def SDT_RISCVVSE_VL : SDTypeProfile<0, 3, [SDTCisVec<0>, SDTCisPtrTy<1>, @@ -266,7 +269,7 @@ (result_type (IMPLICIT_DEF)), op_reg_class:$rs1, op_reg_class:$rs2, - VMV0:$vm, GPR:$vl, sew)>; + VMV0:$vm, GPR:$vl, sew, TAIL_AGNOSTIC)>; } multiclass VPatBinaryVL_XI<SDNode vop, @@ -299,7 +302,7 @@ (result_type (IMPLICIT_DEF)), vop_reg_class:$rs1, xop_kind:$rs2, - VMV0:$vm, GPR:$vl, sew)>; + VMV0:$vm, GPR:$vl, sew, TAIL_AGNOSTIC)>; } multiclass VPatBinaryVL_VV_VX<SDNode vop, string instruction_name> { @@ -604,7 +607,7 @@ VLOpFrag), (!cast<Instruction>("PseudoVRSUB_VX_"# vti.LMul.MX#"_MASK") (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs1, GPR:$rs2, - VMV0:$vm, GPR:$vl, vti.Log2SEW)>; + VMV0:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; def : Pat<(riscv_sub_vl (vti.Vector (SplatPat_simm5 simm5:$rs2)), (vti.Vector vti.RegClass:$rs1), (vti.Mask true_mask), VLOpFrag), @@ -615,7 +618,7 @@ VLOpFrag), (!cast<Instruction>("PseudoVRSUB_VI_"# vti.LMul.MX#"_MASK") (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs1, simm5:$rs2, - VMV0:$vm, GPR:$vl, vti.Log2SEW)>; + VMV0:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; } // 12.3. Vector Integer Extension @@ -1210,7 +1213,7 @@ VLOpFrag)), (!cast<Instruction>("PseudoVRGATHER_VV_"# vti.LMul.MX#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs2, vti.RegClass:$rs1, - vti.Mask:$vm, GPR:$vl, vti.Log2SEW)>; + vti.Mask:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; // emul = lmul * 16 / sew defvar vlmul = vti.LMul; @@ -1237,7 +1240,7 @@ VLOpFrag)), (!cast<Instruction>(inst#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs2, ivti.RegClass:$rs1, - vti.Mask:$vm, GPR:$vl, vti.Log2SEW)>; + vti.Mask:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; } } @@ -1281,7 +1284,7 @@ VLOpFrag)), (!cast<Instruction>("PseudoVRGATHER_VV_"# vti.LMul.MX#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs2, vti.RegClass:$rs1, - vti.Mask:$vm, GPR:$vl, vti.Log2SEW)>; + vti.Mask:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; defvar vlmul = vti.LMul; defvar octuple_lmul = vlmul.octuple; @@ -1307,7 +1310,7 @@ VLOpFrag)), (!cast<Instruction>(inst#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs2, ivti.RegClass:$rs1, - vti.Mask:$vm, GPR:$vl, vti.Log2SEW)>; + vti.Mask:$vm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>; } } Index: llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -642,7 +642,7 @@ Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd), (ins GetVRegNoV0<RetClass>.R:$merge, GPR:$rs1, - VMaskOp:$vm, AVL:$vl, ixlenimm:$sew),[]>, + VMaskOp:$vm, AVL:$vl, ixlenimm:$sew, uimm5:$policy),[]>, RISCVVPseudo, RISCVVLE</*Masked*/1, /*Strided*/0, /*FF*/isFF, log2<EEW>.val, VLMul> { let mayLoad = 1; @@ -652,6 +652,7 @@ let HasVLOp = 1; let HasSEWOp = 1; let HasMergeOp = 1; + let HasPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } @@ -673,7 +674,7 @@ Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd), (ins GetVRegNoV0<RetClass>.R:$merge, GPR:$rs1, GPR:$rs2, - VMaskOp:$vm, AVL:$vl, ixlenimm:$sew),[]>, + VMaskOp:$vm, AVL:$vl, ixlenimm:$sew, uimm5:$policy),[]>, RISCVVPseudo, RISCVVLE</*Masked*/1, /*Strided*/1, /*FF*/0, log2<EEW>.val, VLMul> { let mayLoad = 1; @@ -683,6 +684,7 @@ let HasVLOp = 1; let HasSEWOp = 1; let HasMergeOp = 1; + let HasPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } @@ -707,7 +709,7 @@ Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd), (ins GetVRegNoV0<RetClass>.R:$merge, GPR:$rs1, IdxClass:$rs2, - VMaskOp:$vm, AVL:$vl, ixlenimm:$sew),[]>, + VMaskOp:$vm, AVL:$vl, ixlenimm:$sew, uimm5:$policy),[]>, RISCVVPseudo, RISCVVLX</*Masked*/1, Ordered, log2<EEW>.val, VLMul, LMUL> { let mayLoad = 1; @@ -717,6 +719,7 @@ let HasVLOp = 1; let HasSEWOp = 1; let HasMergeOp = 1; + let HasPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } @@ -860,6 +863,22 @@ let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } +class VPseudoUnaryMaskTA<VReg RetClass, VReg OpClass, string Constraint = ""> : + Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd), + (ins GetVRegNoV0<RetClass>.R:$merge, OpClass:$rs2, + VMaskOp:$vm, AVL:$vl, ixlenimm:$sew, uimm5:$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 HasPolicyOp = 1; + let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); +} + // mask unary operation without maskedoff class VPseudoMaskUnarySOutMask: Pseudo<(outs GPR:$rd), @@ -975,6 +994,26 @@ let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } +class VPseudoBinaryMaskTA<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, AVL:$vl, ixlenimm:$sew, uimm5:$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 HasPolicyOp = 1; + let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); +} + // Like VPseudoBinaryMask, but output can be V0. class VPseudoBinaryMOutMask<VReg RetClass, RegisterClass Op1Class, @@ -1004,7 +1043,7 @@ Pseudo<(outs GetVRegNoV0<RetClass>.R:$rd), (ins GetVRegNoV0<RetClass>.R:$merge, Op2Class:$rs1, - VMaskOp:$vm, AVL:$vl, ixlenimm:$sew), []>, + VMaskOp:$vm, AVL:$vl, ixlenimm:$sew, uimm5:$policy), []>, RISCVVPseudo { let mayLoad = 0; let mayStore = 0; @@ -1013,6 +1052,7 @@ let HasVLOp = 1; let HasSEWOp = 1; let HasMergeOp = 0; // Merge is also rs2. + let HasPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } @@ -1491,8 +1531,8 @@ let VLMul = MInfo.value in { def "_" # MInfo.MX : VPseudoBinaryNoMask<RetClass, Op1Class, Op2Class, Constraint>; - def "_" # MInfo.MX # "_MASK" : VPseudoBinaryMask<RetClass, Op1Class, Op2Class, - Constraint>; + def "_" # MInfo.MX # "_MASK" : VPseudoBinaryMaskTA<RetClass, Op1Class, Op2Class, + Constraint>; } } @@ -1519,8 +1559,8 @@ let VLMul = lmul.value in { def "_" # lmul.MX # "_" # emul.MX : VPseudoBinaryNoMask<RetClass, Op1Class, Op2Class, Constraint>; - def "_" # lmul.MX # "_" # emul.MX # "_MASK" : VPseudoBinaryMask<RetClass, Op1Class, Op2Class, - Constraint>; + def "_" # lmul.MX # "_" # emul.MX # "_MASK" : VPseudoBinaryMaskTA<RetClass, Op1Class, Op2Class, + Constraint>; } } @@ -1712,6 +1752,15 @@ } } +multiclass VPseudoUnaryTAV_V { + foreach m = MxList.m in { + let VLMul = m.value in { + def "_V_" # m.MX : VPseudoUnaryNoMask<m.vrclass, m.vrclass>; + def "_V_" # m.MX # "_MASK" : VPseudoUnaryMaskTA<m.vrclass, m.vrclass>; + } + } +} + multiclass VPseudoUnaryV_V { foreach m = MxList.m in { let VLMul = m.value in { @@ -1727,8 +1776,8 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask<m.vrclass, m.f2vrclass, constraints>; - def "_" # m.MX # "_MASK" : VPseudoUnaryMask<m.vrclass, m.f2vrclass, - constraints>; + def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA<m.vrclass, m.f2vrclass, + constraints>; } } } @@ -1739,8 +1788,8 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask<m.vrclass, m.f4vrclass, constraints>; - def "_" # m.MX # "_MASK" : VPseudoUnaryMask<m.vrclass, m.f4vrclass, - constraints>; + def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA<m.vrclass, m.f4vrclass, + constraints>; } } } @@ -1751,8 +1800,8 @@ { let VLMul = m.value in { def "_" # m.MX : VPseudoUnaryNoMask<m.vrclass, m.f8vrclass, constraints>; - def "_" # m.MX # "_MASK" : VPseudoUnaryMask<m.vrclass, m.f8vrclass, - constraints>; + def "_" # m.MX # "_MASK" : VPseudoUnaryMaskTA<m.vrclass, m.f8vrclass, + constraints>; } } } @@ -2024,8 +2073,8 @@ string Constraint = ""> { let VLMul = MInfo.value in { def "_" # MInfo.MX : VPseudoUnaryNoMask<RetClass, Op1Class, Constraint>; - def "_" # MInfo.MX # "_MASK" : VPseudoUnaryMask<RetClass, Op1Class, - Constraint>; + def "_" # MInfo.MX # "_MASK" : VPseudoUnaryMaskTA<RetClass, Op1Class, + Constraint>; } } @@ -2208,6 +2257,26 @@ (op2_type op2_reg_class:$rs2), (mask_type V0), GPR:$vl, sew)>; +class VPatUnaryMaskTA<string intrinsic_name, + string inst, + string kind, + ValueType result_type, + ValueType op2_type, + ValueType mask_type, + int sew, + LMULInfo vlmul, + VReg result_reg_class, + VReg op2_reg_class> : + Pat<(result_type (!cast<Intrinsic>(intrinsic_name#"_mask") + (result_type result_reg_class:$merge), + (op2_type op2_reg_class:$rs2), + (mask_type V0), + VLOpFrag, (XLenVT uimm5:$policy))), + (!cast<Instruction>(inst#"_"#kind#"_"#vlmul.MX#"_MASK") + (result_type result_reg_class:$merge), + (op2_type op2_reg_class:$rs2), + (mask_type V0), GPR:$vl, sew, (XLenVT uimm5:$policy))>; + class VPatMaskUnaryNoMask<string intrinsic_name, string inst, MTypeInfo mti> : @@ -2309,6 +2378,28 @@ (op2_type op2_kind:$rs2), (mask_type V0), GPR:$vl, sew)>; +class VPatBinaryMaskTA<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), + VLOpFrag, (XLenVT uimm5:$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), GPR:$vl, sew, (XLenVT uimm5:$policy))>; + // Same as above but source operands are swapped. class VPatBinaryMaskSwapped<string intrinsic_name, string inst, @@ -2361,11 +2452,11 @@ (result_type result_reg_class:$merge), (op2_type op2_kind:$rs2), (mask_type V0), - VLOpFrag)), + VLOpFrag, (XLenVT uimm5:$policy))), (!cast<Instruction>(inst#"_MASK_TIED") (result_type result_reg_class:$merge), (op2_type op2_kind:$rs2), - (mask_type V0), GPR:$vl, sew)>; + (mask_type V0), GPR:$vl, sew, (XLenVT uimm5:$policy))>; class VPatTernaryNoMask<string intrinsic, string inst, @@ -2505,9 +2596,9 @@ def : VPatUnaryNoMask<intrinsic, instruction, suffix, vti.Vector, fti.Vector, vti.Log2SEW, vti.LMul, fti.RegClass>; - def : VPatUnaryMask<intrinsic, instruction, suffix, - vti.Vector, fti.Vector, vti.Mask, - vti.Log2SEW, vti.LMul, vti.RegClass, fti.RegClass>; + def : VPatUnaryMaskTA<intrinsic, instruction, suffix, + vti.Vector, fti.Vector, vti.Mask, + vti.Log2SEW, vti.LMul, vti.RegClass, fti.RegClass>; } } @@ -2517,9 +2608,9 @@ def : VPatUnaryNoMask<intrinsic, instruction, "V", vti.Vector, vti.Vector, vti.Log2SEW, vti.LMul, vti.RegClass>; - def : VPatUnaryMask<intrinsic, instruction, "V", - vti.Vector, vti.Vector, vti.Mask, - vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass>; + def : VPatUnaryMaskTA<intrinsic, instruction, "V", + vti.Vector, vti.Vector, vti.Mask, + vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass>; } } @@ -2565,6 +2656,24 @@ op2_kind>; } +multiclass VPatBinaryTA<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 : VPatBinaryNoMask<intrinsic, inst, result_type, op1_type, op2_type, + sew, op1_reg_class, op2_kind>; + def : VPatBinaryMaskTA<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, @@ -2644,23 +2753,40 @@ mask_type, sew, vlmul, result_reg_class, op1_reg_class>; } +multiclass VPatConversionTA<string intrinsic, + string inst, + string kind, + ValueType result_type, + ValueType op1_type, + ValueType mask_type, + int sew, + LMULInfo vlmul, + VReg result_reg_class, + VReg op1_reg_class> +{ + def : VPatUnaryNoMask<intrinsic, inst, kind, result_type, op1_type, + sew, vlmul, op1_reg_class>; + def : VPatUnaryMaskTA<intrinsic, inst, kind, result_type, op1_type, + mask_type, sew, vlmul, result_reg_class, op1_reg_class>; +} + multiclass VPatBinaryV_VV<string intrinsic, string instruction, list<VTypeInfo> vtilist> { foreach vti = vtilist in - defm : VPatBinary<intrinsic, instruction # "_VV_" # vti.LMul.MX, - vti.Vector, vti.Vector, vti.Vector,vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, vti.RegClass>; + defm : VPatBinaryTA<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 { defvar ivti = GetIntVTypeInfo<vti>.Vti; - defm : VPatBinary<intrinsic, instruction # "_VV_" # vti.LMul.MX, - vti.Vector, vti.Vector, ivti.Vector, vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, vti.RegClass>; + defm : VPatBinaryTA<intrinsic, instruction # "_VV_" # vti.LMul.MX, + vti.Vector, vti.Vector, ivti.Vector, vti.Mask, + vti.Log2SEW, vti.RegClass, + vti.RegClass, vti.RegClass>; } } @@ -2675,10 +2801,10 @@ defvar emul_str = octuple_to_str<octuple_emul>.ret; defvar ivti = !cast<VTypeInfo>("VI" # eew # emul_str); defvar inst = instruction # "_VV_" # vti.LMul.MX # "_" # emul_str; - defm : VPatBinary<intrinsic, inst, - vti.Vector, vti.Vector, ivti.Vector, vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, ivti.RegClass>; + defm : VPatBinaryTA<intrinsic, inst, + vti.Vector, vti.Vector, ivti.Vector, vti.Mask, + vti.Log2SEW, vti.RegClass, + vti.RegClass, ivti.RegClass>; } } } @@ -2687,29 +2813,29 @@ list<VTypeInfo> vtilist> { foreach vti = vtilist in { defvar kind = "V"#vti.ScalarSuffix; - defm : VPatBinary<intrinsic, instruction#"_"#kind#"_"#vti.LMul.MX, - vti.Vector, vti.Vector, vti.Scalar, vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, vti.ScalarRegClass>; + defm : VPatBinaryTA<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 - defm : VPatBinary<intrinsic, instruction # "_VX_" # vti.LMul.MX, - vti.Vector, vti.Vector, XLenVT, vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, GPR>; + defm : VPatBinaryTA<intrinsic, instruction # "_VX_" # vti.LMul.MX, + vti.Vector, vti.Vector, XLenVT, vti.Mask, + vti.Log2SEW, vti.RegClass, + vti.RegClass, GPR>; } multiclass VPatBinaryV_VI<string intrinsic, string instruction, list<VTypeInfo> vtilist, Operand imm_type> { foreach vti = vtilist in - defm : VPatBinary<intrinsic, instruction # "_VI_" # vti.LMul.MX, - vti.Vector, vti.Vector, XLenVT, vti.Mask, - vti.Log2SEW, vti.RegClass, - vti.RegClass, imm_type>; + defm : VPatBinaryTA<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> { @@ -2724,10 +2850,10 @@ foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; - defm : VPatBinary<intrinsic, instruction # "_VV_" # Vti.LMul.MX, - Wti.Vector, Vti.Vector, Vti.Vector, Vti.Mask, - Vti.Log2SEW, Wti.RegClass, - Vti.RegClass, Vti.RegClass>; + defm : VPatBinaryTA<intrinsic, instruction # "_VV_" # Vti.LMul.MX, + Wti.Vector, Vti.Vector, Vti.Vector, Vti.Mask, + Vti.Log2SEW, Wti.RegClass, + Vti.RegClass, Vti.RegClass>; } } @@ -2737,10 +2863,10 @@ defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; defvar kind = "V"#Vti.ScalarSuffix; - defm : VPatBinary<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, - Wti.Vector, Vti.Vector, Vti.Scalar, Vti.Mask, - Vti.Log2SEW, Wti.RegClass, - Vti.RegClass, Vti.ScalarRegClass>; + defm : VPatBinaryTA<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, + Wti.Vector, Vti.Vector, Vti.Scalar, Vti.Mask, + Vti.Log2SEW, Wti.RegClass, + Vti.RegClass, Vti.ScalarRegClass>; } } @@ -2756,10 +2882,10 @@ def : VPatTiedBinaryMask<intrinsic, instruction # "_WV_" # Vti.LMul.MX, Wti.Vector, Vti.Vector, Vti.Mask, Vti.Log2SEW, Wti.RegClass, Vti.RegClass>; - def : VPatBinaryMask<intrinsic, instruction # "_WV_" # Vti.LMul.MX, - Wti.Vector, Wti.Vector, Vti.Vector, Vti.Mask, - Vti.Log2SEW, Wti.RegClass, - Wti.RegClass, Vti.RegClass>; + def : VPatBinaryMaskTA<intrinsic, instruction # "_WV_" # Vti.LMul.MX, + Wti.Vector, Wti.Vector, Vti.Vector, Vti.Mask, + Vti.Log2SEW, Wti.RegClass, + Wti.RegClass, Vti.RegClass>; } } @@ -2769,10 +2895,10 @@ defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; defvar kind = "W"#Vti.ScalarSuffix; - defm : VPatBinary<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, - Wti.Vector, Wti.Vector, Vti.Scalar, Vti.Mask, - Vti.Log2SEW, Wti.RegClass, - Wti.RegClass, Vti.ScalarRegClass>; + defm : VPatBinaryTA<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, + Wti.Vector, Wti.Vector, Vti.Scalar, Vti.Mask, + Vti.Log2SEW, Wti.RegClass, + Wti.RegClass, Vti.ScalarRegClass>; } } @@ -2781,10 +2907,10 @@ foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; - defm : VPatBinary<intrinsic, instruction # "_WV_" # Vti.LMul.MX, - Vti.Vector, Wti.Vector, Vti.Vector, Vti.Mask, - Vti.Log2SEW, Vti.RegClass, - Wti.RegClass, Vti.RegClass>; + defm : VPatBinaryTA<intrinsic, instruction # "_WV_" # Vti.LMul.MX, + Vti.Vector, Wti.Vector, Vti.Vector, Vti.Mask, + Vti.Log2SEW, Vti.RegClass, + Wti.RegClass, Vti.RegClass>; } } @@ -2794,10 +2920,10 @@ defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; defvar kind = "W"#Vti.ScalarSuffix; - defm : VPatBinary<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, - Vti.Vector, Wti.Vector, Vti.Scalar, Vti.Mask, - Vti.Log2SEW, Vti.RegClass, - Wti.RegClass, Vti.ScalarRegClass>; + defm : VPatBinaryTA<intrinsic, instruction#"_"#kind#"_"#Vti.LMul.MX, + Vti.Vector, Wti.Vector, Vti.Scalar, Vti.Mask, + Vti.Log2SEW, Vti.RegClass, + Wti.RegClass, Vti.ScalarRegClass>; } } @@ -2806,10 +2932,10 @@ foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; - defm : VPatBinary<intrinsic, instruction # "_WI_" # Vti.LMul.MX, - Vti.Vector, Wti.Vector, XLenVT, Vti.Mask, - Vti.Log2SEW, Vti.RegClass, - Wti.RegClass, uimm5>; + defm : VPatBinaryTA<intrinsic, instruction # "_WI_" # Vti.LMul.MX, + Vti.Vector, Wti.Vector, XLenVT, Vti.Mask, + Vti.Log2SEW, Vti.RegClass, + Wti.RegClass, uimm5>; } } @@ -3122,8 +3248,8 @@ } } -multiclass VPatConversionVI_VF<string intrinsic, - string instruction> +multiclass VPatClassifyVI_VF<string intrinsic, + string instruction> { foreach fvti = AllFloatVectors in { @@ -3135,6 +3261,19 @@ } } +multiclass VPatConversionVI_VF<string intrinsic, + string instruction> +{ + foreach fvti = AllFloatVectors in + { + defvar ivti = GetIntVTypeInfo<fvti>.Vti; + + defm : VPatConversionTA<intrinsic, instruction, "V", + ivti.Vector, fvti.Vector, ivti.Mask, fvti.Log2SEW, + fvti.LMul, ivti.RegClass, fvti.RegClass>; + } +} + multiclass VPatConversionVF_VI<string intrinsic, string instruction> { @@ -3142,9 +3281,9 @@ { defvar ivti = GetIntVTypeInfo<fvti>.Vti; - defm : VPatConversion<intrinsic, instruction, "V", - fvti.Vector, ivti.Vector, fvti.Mask, ivti.Log2SEW, - ivti.LMul, fvti.RegClass, ivti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "V", + fvti.Vector, ivti.Vector, fvti.Mask, ivti.Log2SEW, + ivti.LMul, fvti.RegClass, ivti.RegClass>; } } @@ -3154,9 +3293,9 @@ defvar fvti = fvtiToFWti.Vti; defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti; - defm : VPatConversion<intrinsic, instruction, "V", - iwti.Vector, fvti.Vector, iwti.Mask, fvti.Log2SEW, - fvti.LMul, iwti.RegClass, fvti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "V", + iwti.Vector, fvti.Vector, iwti.Mask, fvti.Log2SEW, + fvti.LMul, iwti.RegClass, fvti.RegClass>; } } @@ -3166,9 +3305,9 @@ defvar vti = vtiToWti.Vti; defvar fwti = vtiToWti.Wti; - defm : VPatConversion<intrinsic, instruction, "V", - fwti.Vector, vti.Vector, fwti.Mask, vti.Log2SEW, - vti.LMul, fwti.RegClass, vti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "V", + fwti.Vector, vti.Vector, fwti.Mask, vti.Log2SEW, + vti.LMul, fwti.RegClass, vti.RegClass>; } } @@ -3178,9 +3317,9 @@ defvar fvti = fvtiToFWti.Vti; defvar fwti = fvtiToFWti.Wti; - defm : VPatConversion<intrinsic, instruction, "V", - fwti.Vector, fvti.Vector, fwti.Mask, fvti.Log2SEW, - fvti.LMul, fwti.RegClass, fvti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "V", + fwti.Vector, fvti.Vector, fwti.Mask, fvti.Log2SEW, + fvti.LMul, fwti.RegClass, fvti.RegClass>; } } @@ -3190,9 +3329,9 @@ defvar vti = vtiToWti.Vti; defvar fwti = vtiToWti.Wti; - defm : VPatConversion<intrinsic, instruction, "W", - vti.Vector, fwti.Vector, vti.Mask, vti.Log2SEW, - vti.LMul, vti.RegClass, fwti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "W", + vti.Vector, fwti.Vector, vti.Mask, vti.Log2SEW, + vti.LMul, vti.RegClass, fwti.RegClass>; } } @@ -3202,9 +3341,9 @@ defvar fvti = fvtiToFWti.Vti; defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti; - defm : VPatConversion<intrinsic, instruction, "W", - fvti.Vector, iwti.Vector, fvti.Mask, fvti.Log2SEW, - fvti.LMul, fvti.RegClass, iwti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "W", + fvti.Vector, iwti.Vector, fvti.Mask, fvti.Log2SEW, + fvti.LMul, fvti.RegClass, iwti.RegClass>; } } @@ -3214,9 +3353,9 @@ defvar fvti = fvtiToFWti.Vti; defvar fwti = fvtiToFWti.Wti; - defm : VPatConversion<intrinsic, instruction, "W", - fvti.Vector, fwti.Vector, fvti.Mask, fvti.Log2SEW, - fvti.LMul, fvti.RegClass, fwti.RegClass>; + defm : VPatConversionTA<intrinsic, instruction, "W", + fvti.Vector, fwti.Vector, fvti.Mask, fvti.Log2SEW, + fvti.LMul, fvti.RegClass, fwti.RegClass>; } } @@ -3418,14 +3557,16 @@ (vti.Vector vti.RegClass:$rs2), (vti.Vector vti.RegClass:$rs1), (vti.Mask V0), - VLOpFrag)), + VLOpFrag, + (XLenVT uimm5:$policy))), (!cast<Instruction>("PseudoVSUB_VV_"#vti.LMul.MX#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs1, vti.RegClass:$rs2, (vti.Mask V0), GPR:$vl, - vti.Log2SEW)>; + vti.Log2SEW, + (XLenVT uimm5:$policy))>; // Match VSUB with a small immediate to vadd.vi by negating the immediate. def : Pat<(vti.Vector (int_riscv_vsub (vti.Vector vti.RegClass:$rs1), @@ -3439,14 +3580,16 @@ (vti.Vector vti.RegClass:$rs1), (vti.Scalar simm5_plus1:$rs2), (vti.Mask V0), - VLOpFrag)), + VLOpFrag, + (XLenVT uimm5:$policy))), (!cast<Instruction>("PseudoVADD_VI_"#vti.LMul.MX#"_MASK") vti.RegClass:$merge, vti.RegClass:$rs1, (NegImm simm5_plus1:$rs2), (vti.Mask V0), GPR:$vl, - vti.Log2SEW)>; + vti.Log2SEW, + (XLenVT uimm5:$policy))>; } //===----------------------------------------------------------------------===// @@ -3667,17 +3810,17 @@ //===----------------------------------------------------------------------===// // 14.8. Vector Floating-Point Square-Root Instruction //===----------------------------------------------------------------------===// -defm PseudoVFSQRT : VPseudoUnaryV_V; +defm PseudoVFSQRT : VPseudoUnaryTAV_V; //===----------------------------------------------------------------------===// // 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction //===----------------------------------------------------------------------===// -defm PseudoVFRSQRT7 : VPseudoUnaryV_V; +defm PseudoVFRSQRT7 : VPseudoUnaryTAV_V; //===----------------------------------------------------------------------===// // 14.10. Vector Floating-Point Reciprocal Estimate Instruction //===----------------------------------------------------------------------===// -defm PseudoVFREC7 : VPseudoUnaryV_V; +defm PseudoVFREC7 : VPseudoUnaryTAV_V; //===----------------------------------------------------------------------===// // 14.11. Vector Floating-Point Min/Max Instructions @@ -4363,7 +4506,7 @@ //===----------------------------------------------------------------------===// // 14.14. Vector Floating-Point Classify Instruction //===----------------------------------------------------------------------===// -defm : VPatConversionVI_VF<"int_riscv_vfclass", "PseudoVFCLASS">; +defm : VPatClassifyVI_VF<"int_riscv_vfclass", "PseudoVFCLASS">; //===----------------------------------------------------------------------===// // 14.15. Vector Floating-Point Merge Instruction Index: llvm/lib/Target/RISCV/RISCVInstrFormats.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrFormats.td +++ llvm/lib/Target/RISCV/RISCVInstrFormats.td @@ -178,6 +178,9 @@ bit HasVLOp = 0; let TSFlags{15} = HasVLOp; + + bit HasPolicyOp = false; + let TSFlags{16} = HasPolicyOp; } // Pseudo instructions Index: llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -365,7 +365,9 @@ RISCVII::VLMUL VLMul = RISCVII::getLMul(TSFlags); - unsigned Log2SEW = MI.getOperand(NumOperands - 1).getImm(); + unsigned Log2SEWIndex = + RISCVII::hasPolicyOp(TSFlags) ? NumOperands - 2 : NumOperands - 1; + unsigned Log2SEW = MI.getOperand(Log2SEWIndex).getImm(); // A Log2SEW of 0 is an operation on mask registers only. bool MaskRegOp = Log2SEW == 0; unsigned SEW = Log2SEW ? 1 << Log2SEW : 8; @@ -393,6 +395,12 @@ } } + // If the instruction has policy argument, use the argument. + if (RISCVII::hasPolicyOp(TSFlags)) { + const MachineOperand &Op = MI.getOperand(NumOperands - 1); + TailAgnostic = Op.getImm() & 0x1; + } + if (RISCVII::hasVLOp(TSFlags)) { const MachineOperand &VLOp = MI.getOperand(MI.getNumExplicitOperands() - 2); if (VLOp.isImm()) Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -76,6 +76,9 @@ // explicit operand. Used by RVV Pseudos. HasVLOpShift = HasSEWOpShift + 1, HasVLOpMask = 1 << HasVLOpShift, + + HasPolicyOpShift = HasVLOpShift + 1, + HasPolicyOpMask = 1 << HasPolicyOpShift, }; // Match with the definitions in RISCVInstrFormatsV.td @@ -132,6 +135,10 @@ return TSFlags & HasVLOpMask; } +static inline bool hasPolicyOp(uint64_t TSFlags) { + return TSFlags & HasPolicyOpMask; +} + // RISC-V Specific Machine Operand Flags enum { MO_None = 0, Index: llvm/include/llvm/IR/IntrinsicsRISCV.td =================================================================== --- llvm/include/llvm/IR/IntrinsicsRISCV.td +++ llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -267,6 +267,12 @@ // For destination vector type is the same as first source vector (with mask). // Input: (vector_in, mask, vl) class RISCVUnaryAAMask + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<1>], + [IntrNoMem]>, RISCVVIntrinsic; + class RISCVUnaryAAMaskNoTA : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], @@ -288,7 +294,8 @@ class RISCVRGatherVVMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMVectorOfBitcastsToInt<0>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<1>], [IntrNoMem]>, RISCVVIntrinsic; // Input: (vector_in, int16_vector_in, vl) class RISCVRGatherEI16VVNoMask @@ -302,7 +309,8 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i16_ty>, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<1>], [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is the same as first source vector, and the // second operand is XLen. @@ -318,7 +326,8 @@ class RISCVGatherVXMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<1>, + LLVMMatchType<1>], [IntrNoMem]>, RISCVVIntrinsic { } // For destination vector type is the same as first source vector. @@ -334,7 +343,8 @@ class RISCVBinaryAAXMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<2>], [IntrNoMem]>, RISCVVIntrinsic { let SplatOperand = 3; } @@ -351,7 +361,8 @@ class RISCVBinaryAAShiftMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<2>], [IntrNoMem]>, RISCVVIntrinsic; // For destination vector type is NOT the same as first source vector. // Input: (vector_in, vector_in/scalar_in, vl) @@ -366,7 +377,8 @@ class RISCVBinaryABXMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<3>], [IntrNoMem]>, RISCVVIntrinsic { let SplatOperand = 3; } @@ -383,7 +395,8 @@ class RISCVBinaryABShiftMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<3>], [IntrNoMem]>, RISCVVIntrinsic; // For binary operations with V0 as input. // Input: (vector_in, vector_in/scalar_in, V0, vl) @@ -465,7 +478,8 @@ class RISCVSaturatingBinaryAAXMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<2>], [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic { let SplatOperand = 3; } @@ -484,7 +498,8 @@ class RISCVSaturatingBinaryAAShiftMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<2>], [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; // For Saturating binary operations. // The destination vector type is NOT the same as first source vector. @@ -501,7 +516,8 @@ class RISCVSaturatingBinaryABShiftMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<3>], [IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic; class RISCVTernaryAAAXNoMask : Intrinsic<[llvm_anyvector_ty], @@ -584,7 +600,7 @@ : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>, - llvm_anyint_ty], + llvm_anyint_ty, LLVMMatchType<2>], [IntrNoMem]>, RISCVVIntrinsic; // For unary operations with the same vector type in/out without mask // Output: (vector) @@ -618,7 +634,8 @@ class RISCVConversionMask : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, - LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty, + LLVMMatchType<2>], [IntrNoMem]>, RISCVVIntrinsic; // For atomic operations without mask // Input: (base, index, value, vl) @@ -1124,7 +1141,7 @@ defm vrgather_vx : RISCVRGatherVX; defm vrgatherei16_vv : RISCVRGatherEI16VV; - def "int_riscv_vcompress" : RISCVUnaryAAMask; + def "int_riscv_vcompress" : RISCVUnaryAAMaskNoTA; defm vaaddu : RISCVSaturatingBinaryAAX; defm vaadd : RISCVSaturatingBinaryAAX; Index: clang/utils/TableGen/RISCVVEmitter.cpp =================================================================== --- clang/utils/TableGen/RISCVVEmitter.cpp +++ clang/utils/TableGen/RISCVVEmitter.cpp @@ -156,6 +156,7 @@ bool IsMask; bool HasMaskedOffOperand; bool HasVL; + bool HasPolicy; bool HasNoMaskedOverloaded; bool HasAutoDef; // There is automiatic definition in header std::string ManualCodegen; @@ -169,8 +170,9 @@ public: RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName, StringRef IRName, bool HasSideEffects, bool IsMask, - bool HasMaskedOffOperand, bool HasVL, bool HasNoMaskedOverloaded, - bool HasAutoDef, StringRef ManualCodegen, const RVVTypes &Types, + bool HasMaskedOffOperand, bool HasVL, bool HasPolicy, + bool HasNoMaskedOverloaded, bool HasAutoDef, + StringRef ManualCodegen, const RVVTypes &Types, const std::vector<int64_t> &IntrinsicTypes, StringRef RequiredExtension); ~RVVIntrinsic() = default; @@ -180,6 +182,7 @@ bool hasSideEffects() const { return HasSideEffects; } bool hasMaskedOffOperand() const { return HasMaskedOffOperand; } bool hasVL() const { return HasVL; } + bool hasPolicy() const { return HasPolicy; } bool hasNoMaskedOverloaded() const { return HasNoMaskedOverloaded; } bool hasManualCodegen() const { return !ManualCodegen.empty(); } bool hasAutoDef() const { return HasAutoDef; } @@ -195,6 +198,9 @@ // init the RVVIntrinsic ID and IntrinsicTypes. void emitCodeGenSwitchBody(raw_ostream &o) const; + // Emit the define macors for mask intrinsics using _mt intrinsics. + void emitIntrinsicMaskMacro(raw_ostream &o) const; + // Emit the macros for mapping C/C++ intrinsic function to builtin functions. void emitIntrinsicMacro(raw_ostream &o) const; @@ -227,6 +233,8 @@ private: /// Create all intrinsics and add them to \p Out void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out); + /// Create Headers and add them to \p Out + void createRVVHeaders(raw_ostream &OS); /// Compute output and input types by applying different config (basic type /// and LMUL with type transformers). It also record result of type in legal /// or illegal set to avoid compute the same config again. The result maybe @@ -631,7 +639,7 @@ ScalarType = ScalarTypeKind::SignedLong; break; default: - PrintFatalError("Illegal primitive type transformers!"); + PrintFatalError("Illegal primitive type transformers: " + PType); } Transformer = Transformer.drop_back(); @@ -745,15 +753,15 @@ RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix, StringRef NewMangledName, StringRef IRName, bool HasSideEffects, bool IsMask, - bool HasMaskedOffOperand, bool HasVL, + bool HasMaskedOffOperand, bool HasVL, bool HasPolicy, bool HasNoMaskedOverloaded, bool HasAutoDef, StringRef ManualCodegen, const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes, StringRef RequiredExtension) : IRName(IRName), HasSideEffects(HasSideEffects), IsMask(IsMask), HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), - HasNoMaskedOverloaded(HasNoMaskedOverloaded), HasAutoDef(HasAutoDef), - ManualCodegen(ManualCodegen.str()) { + HasPolicy(HasPolicy), HasNoMaskedOverloaded(HasNoMaskedOverloaded), + HasAutoDef(HasAutoDef), ManualCodegen(ManualCodegen.str()) { // Init Name and MangledName Name = NewName.str(); @@ -765,6 +773,8 @@ Name += "_" + Suffix.str(); if (IsMask) { Name += "_m"; + if (HasPolicy) + Name += "t"; } // Init RISC-V extensions for (const auto &T : OutInTypes) { @@ -813,7 +823,10 @@ if (isMask()) { if (hasVL()) { - OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n"; + if (hasPolicy()) + OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);\n"; + else + OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n"; } else { OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n"; } @@ -853,6 +866,24 @@ OS << ")\n"; } +void RVVIntrinsic::emitIntrinsicMaskMacro(raw_ostream &OS) const { + OS << "#define " << getName().drop_back() << "("; + if (!InputTypes.empty()) { + ListSeparator LS; + for (unsigned i = 0, e = InputTypes.size() - 1; i != e; ++i) + OS << LS << "op" << i; + } + OS << ") \\\n"; + OS << "__builtin_rvv_" << getName() << "("; + ListSeparator LS; + if (!InputTypes.empty()) { + for (unsigned i = 0, e = InputTypes.size() - 1; i != e; ++i) + OS << LS << "(" << InputTypes[i]->getTypeStr() << ")(op" << i << ")"; + } + OS << LS << "(size_t)VE_TAIL_AGNOSTIC"; + OS << ")\n"; +} + void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const { OS << "__attribute__((clang_builtin_alias("; OS << "__builtin_rvv_" << getName() << ")))\n"; @@ -898,6 +929,8 @@ OS << "extern \"C\" {\n"; OS << "#endif\n\n"; + createRVVHeaders(OS); + std::vector<std::unique_ptr<RVVIntrinsic>> Defs; createRVVIntrinsics(Defs); @@ -965,6 +998,12 @@ Inst.emitIntrinsicMacro(OS); }); + // Use _mt to implement _m intrinsics. + emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) { + if (Inst.isMask() && Inst.hasPolicy()) + Inst.emitIntrinsicMaskMacro(OS); + }); + OS << "#define __riscv_v_intrinsic_overloading 1\n"; // Print Overloaded APIs @@ -1066,6 +1105,7 @@ bool HasMask = R->getValueAsBit("HasMask"); bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand"); bool HasVL = R->getValueAsBit("HasVL"); + bool HasPolicy = R->getValueAsBit("HasPolicy"); bool HasNoMaskedOverloaded = R->getValueAsBit("HasNoMaskedOverloaded"); bool HasSideEffects = R->getValueAsBit("HasSideEffects"); std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL"); @@ -1104,6 +1144,10 @@ ProtoMaskSeq.push_back("z"); } + if (HasPolicy) { + ProtoMaskSeq.push_back("Kz"); + } + // Create Intrinsics for each type and LMUL. for (char I : TypeRange) { for (int Log2LMUL : Log2LMULList) { @@ -1116,7 +1160,7 @@ // Create a non-mask intrinsic Out.push_back(std::make_unique<RVVIntrinsic>( Name, SuffixStr, MangledName, IRName, HasSideEffects, - /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, + /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasPolicy, HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, Types.getValue(), IntrinsicTypes, RequiredExtension)); if (HasMask) { @@ -1125,7 +1169,7 @@ computeTypes(I, Log2LMUL, ProtoMaskSeq); Out.push_back(std::make_unique<RVVIntrinsic>( Name, SuffixStr, MangledName, IRNameMask, HasSideEffects, - /*IsMask=*/true, HasMaskedOffOperand, HasVL, + /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasPolicy, HasNoMaskedOverloaded, HasAutoDef, ManualCodegenMask, MaskTypes.getValue(), IntrinsicTypes, RequiredExtension)); } @@ -1134,6 +1178,15 @@ } } +void RVVEmitter::createRVVHeaders(raw_ostream &OS) { + std::vector<Record *> RVVHeaders = + Records.getAllDerivedDefinitions("RVVHeader"); + for (auto *R : RVVHeaders) { + StringRef HeaderCodeStr = R->getValueAsString("HeaderCode"); + OS << HeaderCodeStr.str(); + } +} + Optional<RVVTypes> RVVEmitter::computeTypes(BasicType BT, int Log2LMUL, ArrayRef<std::string> PrototypeSeq) { Index: clang/test/CodeGen/RISCV/rvv-intrinsics/vadd-policy.c =================================================================== --- /dev/null +++ clang/test/CodeGen/RISCV/rvv-intrinsics/vadd-policy.c @@ -0,0 +1,44 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v \ +// RUN: -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg \ +// RUN: | FileCheck --check-prefix=CHECK-RV64 %s + +#include <riscv_vector.h> + + +// CHECK-RV64-LABEL: @test_vadd_vv_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i8> @llvm.riscv.vadd.nxv8i8.nxv8i8.i64(<vscale x 8 x i8> [[OP1:%.*]], <vscale x 8 x i8> [[OP2:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: ret <vscale x 8 x i8> [[TMP0]] +// +vint8m1_t test_vadd_vv_i8m1 (vint8m1_t op1, vint8m1_t op2, size_t vl) { + return vadd_vv_i8m1(op1, op2, vl); +} + +// CHECK-RV64-LABEL: @test_vadd_vv_i8m1_m( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8.i64(<vscale x 8 x i8> [[MASKEDOFF:%.*]], <vscale x 8 x i8> [[OP1:%.*]], <vscale x 8 x i8> [[OP2:%.*]], <vscale x 8 x i1> [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: ret <vscale x 8 x i8> [[TMP0]] +// +vint8m1_t test_vadd_vv_i8m1_m (vbool8_t mask, vint8m1_t maskedoff, vint8m1_t op1, vint8m1_t op2, size_t vl) { + return vadd_vv_i8m1_m(mask, maskedoff, op1, op2, vl); +} + +// CHECK-RV64-LABEL: @test_vadd_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8.i64(<vscale x 8 x i8> [[MASKEDOFF:%.*]], <vscale x 8 x i8> [[OP1:%.*]], <vscale x 8 x i8> [[OP2:%.*]], <vscale x 8 x i1> [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret <vscale x 8 x i8> [[TMP0]] +// +vint8m1_t test_vadd_tu (vbool8_t mask, vint8m1_t maskedoff, vint8m1_t op1, vint8m1_t op2, size_t vl) { + return vadd_vv_i8m1_mt(mask, maskedoff, op1, op2, vl, VE_TAIL_UNDISTURBED); +} + +// CHECK-RV64-LABEL: @test_vadd_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x i8> @llvm.riscv.vadd.mask.nxv8i8.nxv8i8.i64(<vscale x 8 x i8> [[MASKEDOFF:%.*]], <vscale x 8 x i8> [[OP1:%.*]], <vscale x 8 x i8> [[OP2:%.*]], <vscale x 8 x i1> [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: ret <vscale x 8 x i8> [[TMP0]] +// +vint8m1_t test_vadd_ta (vbool8_t mask, vint8m1_t maskedoff, vint8m1_t op1, vint8m1_t op2, size_t vl) { + return vadd_vv_i8m1_mt(mask, maskedoff, op1, op2, vl, VE_TAIL_AGNOSTIC); +} Index: clang/include/clang/Basic/riscv_vector.td =================================================================== --- clang/include/clang/Basic/riscv_vector.td +++ clang/include/clang/Basic/riscv_vector.td @@ -169,6 +169,13 @@ // This builtin has a granted vector length parameter in the last position. bit HasVL = true; + // Normally, intrinsics have the policy argument if it is masked and + // have no policy argument if it is unmasked. When HasPolicy is false, it + // means the intrinsic has no policy argument regardless masked or unmasked. + // For example, when the output result is mask type or scalar type, there is + // no need to specify the policy. + bit HasPolicy = true; + // This builtin supports non-masked function overloading api. // All masked operations support overloading api. bit HasNoMaskedOverloaded = true; @@ -400,6 +407,7 @@ class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> { let Name = NAME # "_m"; + let HasPolicy = false; } class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> { @@ -978,6 +986,7 @@ let HasVL = false, HasMask = false, HasSideEffects = true, + HasPolicy = false, Log2LMUL = [0], ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type { @@ -1138,7 +1147,7 @@ } // 12.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions -let HasMask = false in { +let HasMask = false, HasPolicy = false in { defm vadc : RVVCarryinBuiltinSet; defm vmadc : RVVCarryOutInBuiltinSet<"vmadc_carry_in">; defm vmadc : RVVIntMaskOutBuiltinSet; @@ -1166,6 +1175,7 @@ ["Uv", "UvUw"]]>; // 12.8. Vector Integer Comparison Instructions +let HasPolicy = false in { defm vmseq : RVVIntMaskOutBuiltinSet; defm vmsne : RVVIntMaskOutBuiltinSet; defm vmsltu : RVVUnsignedMaskOutBuiltinSet; @@ -1176,6 +1186,7 @@ defm vmsgt : RVVSignedMaskOutBuiltinSet; defm vmsgeu : RVVUnsignedMaskOutBuiltinSet; defm vmsge : RVVSignedMaskOutBuiltinSet; +} // 12.9. Vector Integer Min/Max Instructions defm vminu : RVVUnsignedBinBuiltinSet; @@ -1234,7 +1245,7 @@ // 12.15. Vector Integer Merge Instructions // C/C++ Operand: (mask, op1, op2, vl), Intrinsic: (op1, op2, mask, vl) -let HasMask = false, +let HasMask = false, HasPolicy = false, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()}; @@ -1247,7 +1258,7 @@ } // 12.16. Vector Integer Move Instructions -let HasMask = false in { +let HasMask = false, HasPolicy = false in { let MangledName = "vmv_v" in { defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csil", [["v", "Uv", "UvUv"]]>; @@ -1347,20 +1358,22 @@ defm vfabs_v : RVVPseudoVFUnaryBuiltin<"vfsgnjx", "fd">; // 14.13. Vector Floating-Point Compare Instructions +let HasPolicy = false in { defm vmfeq : RVVFloatingMaskOutBuiltinSet; defm vmfne : RVVFloatingMaskOutBuiltinSet; defm vmflt : RVVFloatingMaskOutBuiltinSet; defm vmfle : RVVFloatingMaskOutBuiltinSet; defm vmfgt : RVVFloatingMaskOutBuiltinSet; defm vmfge : RVVFloatingMaskOutBuiltinSet; +} // 14.14. Vector Floating-Point Classify Instruction -let Name = "vfclass_v" in +let Name = "vfclass_v", HasPolicy = false in def vfclass : RVVOp0Builtin<"Uv", "Uvv", "fd">; // 14.15. Vector Floating-Point Merge Instructio // C/C++ Operand: (mask, op1, op2, vl), Builtin: (op1, op2, mask, vl) -let HasMask = false, +let HasMask = false, HasPolicy = false, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()}; @@ -1468,7 +1481,7 @@ // 16.6. vmsof.m set-only-first mask bit def vmsof : RVVMaskUnaryBuiltin; -let HasNoMaskedOverloaded = false in { +let HasNoMaskedOverloaded = false, HasPolicy = false in { // 16.8. Vector Iota Instruction defm viota : RVVOutBuiltinSet<"viota", "csil", [["m", "Uv", "Uvm"]]>; @@ -1479,7 +1492,7 @@ // 17. Vector Permutation Instructions // 17.1. Integer Scalar Move Instructions -let HasMask = false in { +let HasMask = false, HasPolicy = false in { let HasVL = false, MangledName = "vmv_x" in defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil", [["s", "ve", "ev"], @@ -1491,7 +1504,7 @@ } // 17.2. Floating-Point Scalar Move Instructions -let HasMask = false in { +let HasMask = false, HasPolicy = false in { let HasVL = false, MangledName = "vfmv_f" in defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "fd", [["s", "ve", "ev"]]>; @@ -1532,7 +1545,7 @@ [["vv", "Uv", "UvUv(Log2EEW:4)Uv"]]>; // 17.5. Vector Compress Instruction -let HasMask = false, +let HasMask = false, HasPolicy = false, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[3]->getType()}; @@ -1548,7 +1561,7 @@ // Miscellaneous let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false, IRName = "" in { - let Name = "vreinterpret_v", + let Name = "vreinterpret_v", HasPolicy = false, ManualCodegen = [{ return Builder.CreateBitCast(Ops[0], ResultType); }] in { @@ -1568,7 +1581,7 @@ } } - let Name = "vundefined", + let Name = "vundefined", HasPolicy = false, ManualCodegen = [{ return llvm::UndefValue::get(ResultType); }] in { @@ -1578,7 +1591,7 @@ // LMUL truncation // C/C++ Operand: VecTy, IR Operand: VecTy, Index - let Name = "vlmul_trunc_v", + let Name = "vlmul_trunc_v", HasPolicy = false, ManualCodegen = [{ { ID = Intrinsic::experimental_vector_extract; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -1594,7 +1607,7 @@ // LMUL extension // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index - let Name = "vlmul_ext_v", + let Name = "vlmul_ext_v", HasPolicy = false, ManualCodegen = [{ ID = Intrinsic::experimental_vector_insert; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -1610,7 +1623,7 @@ } } - let Name = "vget_v", + let Name = "vget_v", HasPolicy = false, ManualCodegen = [{ { ID = Intrinsic::experimental_vector_extract; @@ -1628,7 +1641,7 @@ } } - let Name = "vset_v", Log2LMUL = [0, 1, 2], + let Name = "vset_v", Log2LMUL = [0, 1, 2], HasPolicy = false, ManualCodegen = [{ { ID = Intrinsic::experimental_vector_insert; @@ -1647,3 +1660,14 @@ } } } + +class RVVHeader +{ + code HeaderCode; +} + +let HeaderCode = [{ +#define VE_TAIL_UNDISTURBED 0 +#define VE_TAIL_AGNOSTIC 1 +}] in +def policy : RVVHeader;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits