106c3fb27SDimitry Andric//==--- riscv_sifive_vector.td - RISC-V SiFive VCIX function list ---------===//
206c3fb27SDimitry Andric//
306c3fb27SDimitry Andric//  Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric//  See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric//  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric//
706c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric//
906c3fb27SDimitry Andric// This file defines the builtins for RISC-V SiFive VCIX. See:
1006c3fb27SDimitry Andric//
1106c3fb27SDimitry Andric//     https://sifive.cdn.prismic.io/sifive/c3829e36-8552-41f0-a841-79945784241b_vcix-spec-software.pdf
1206c3fb27SDimitry Andric//
1306c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
1406c3fb27SDimitry Andric
1506c3fb27SDimitry Andricinclude "riscv_vector_common.td"
1606c3fb27SDimitry Andric
1706c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
1806c3fb27SDimitry Andric// Instruction definitions
1906c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
2006c3fb27SDimitry Andric
2106c3fb27SDimitry Andricclass VCIXSuffix<string range> {
2206c3fb27SDimitry Andric  list<string> suffix = !cond(!eq(range, "c"): ["8mf8", "8mf4", "8mf2", "8m1", "8m2", "8m4", "8m8"],
2306c3fb27SDimitry Andric                              !eq(range, "s"): ["16mf4", "16mf2", "16m1", "16m2", "16m4", "16m8"],
2406c3fb27SDimitry Andric                              !eq(range, "i"): ["32mf2", "32m1", "32m2", "32m4", "32m8"],
2506c3fb27SDimitry Andric                              !eq(range, "l"): ["64m1", "64m2", "64m4", "64m8"]);
2606c3fb27SDimitry Andric}
2706c3fb27SDimitry Andric
2806c3fb27SDimitry Andricclass VCIXBuiltinSet<string name, string IR_name, string suffix,
2906c3fb27SDimitry Andric                     string prototype, string type_range,
3006c3fb27SDimitry Andric                     list<int> intrinsic_types>
3106c3fb27SDimitry Andric    : RVVBuiltin<suffix, prototype, type_range> {
3206c3fb27SDimitry Andric  let Name = name;
3306c3fb27SDimitry Andric  let OverloadedName = name;
3406c3fb27SDimitry Andric  let IRName = IR_name;
3506c3fb27SDimitry Andric  let HasMasked = false;
3606c3fb27SDimitry Andric  let IntrinsicTypes = intrinsic_types;
3706c3fb27SDimitry Andric}
3806c3fb27SDimitry Andric
3906c3fb27SDimitry Andricmulticlass VCIXBuiltinSet<string name, string IR_name, string suffix,
4006c3fb27SDimitry Andric                          string prototype, string type_range,
4106c3fb27SDimitry Andric                          list<int> intrinsic_types> {
4206c3fb27SDimitry Andric  if !find(prototype, "0") then {
4306c3fb27SDimitry Andric    def : VCIXBuiltinSet<name, IR_name, suffix, prototype, type_range, intrinsic_types>;
4406c3fb27SDimitry Andric  }
4506c3fb27SDimitry Andric  def : VCIXBuiltinSet<name # "_se", IR_name # "_se", suffix, prototype, type_range, intrinsic_types>;
4606c3fb27SDimitry Andric}
4706c3fb27SDimitry Andric
4806c3fb27SDimitry Andricmulticlass RVVVCIXBuiltinSet<list<string> range, string prototype,
4906c3fb27SDimitry Andric                             list<int> intrinsic_types, bit UseGPR> {
5006c3fb27SDimitry Andric  foreach r = range in
5106c3fb27SDimitry Andric    let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")),
5206c3fb27SDimitry Andric                               ["Xsfvcp", "RV64"], ["Xsfvcp"]) in
5306c3fb27SDimitry Andric      defm : VCIXBuiltinSet<NAME, NAME, "Uv", prototype, r, intrinsic_types>;
5406c3fb27SDimitry Andric}
5506c3fb27SDimitry Andric
5606c3fb27SDimitry Andricmulticlass RVVVCIXBuiltinSetWVType<list<string> range, string prototype,
5706c3fb27SDimitry Andric                             list<int> intrinsic_types, bit UseGPR> {
5806c3fb27SDimitry Andric  foreach r = range in
5906c3fb27SDimitry Andric    let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")),
6006c3fb27SDimitry Andric                               ["Xsfvcp", "RV64"], ["Xsfvcp"]) in
6106c3fb27SDimitry Andric      // These intrinsics don't have any vector types in the output and inputs,
6206c3fb27SDimitry Andric      // but we still need to add vetvli for them. So we encode different
6306c3fb27SDimitry Andric      // VTYPE into the intrinsic names, and then will know which vsetvli is
6406c3fb27SDimitry Andric      // correct.
6506c3fb27SDimitry Andric      foreach s = VCIXSuffix<r>.suffix in
6606c3fb27SDimitry Andric        // Since we already encode the Vtype into the name, so just set
6706c3fb27SDimitry Andric        // Log2LMUL to zero.  Otherwise the RISCVVEmitter will expand
6806c3fb27SDimitry Andric        // lots of redundant intrinsic but have same names.
6906c3fb27SDimitry Andric        let Log2LMUL = [0] in
7006c3fb27SDimitry Andric          def : VCIXBuiltinSet<NAME # "_u" # s, NAME # "_e" # s,
7106c3fb27SDimitry Andric                               "", prototype, r, intrinsic_types>;
7206c3fb27SDimitry Andric}
7306c3fb27SDimitry Andric
7406c3fb27SDimitry Andriclet SupportOverloading = false in {
755f757f3fSDimitry Andric  defm sf_vc_x_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzUe", [0, 3], UseGPR=1>;
765f757f3fSDimitry Andric  defm sf_vc_i_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzKz", [2, 3], UseGPR=0>;
775f757f3fSDimitry Andric  defm sf_vc_xv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe",  [0, 2, 3],  UseGPR=1>;
785f757f3fSDimitry Andric  defm sf_vc_iv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz",  [0, 2, 3],  UseGPR=0>;
795f757f3fSDimitry Andric  defm sf_vc_vv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv",  [0, 2, 3],  UseGPR=0>;
805f757f3fSDimitry Andric  defm sf_vc_fv    : RVVVCIXBuiltinSet<["si",  "l"], "0KzKzUvFe",  [0, 2, 3],  UseGPR=0>;
815f757f3fSDimitry Andric  defm sf_vc_xvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe",  [0, 1, 2, 3],  UseGPR=1>;
825f757f3fSDimitry Andric  defm sf_vc_ivv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz",  [0, 1, 2, 3],  UseGPR=0>;
835f757f3fSDimitry Andric  defm sf_vc_vvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv",  [0, 1, 2, 3],  UseGPR=0>;
845f757f3fSDimitry Andric  defm sf_vc_fvv   : RVVVCIXBuiltinSet<["si",  "l"], "0KzUvUvFe",  [0, 1, 2, 3],  UseGPR=0>;
855f757f3fSDimitry Andric  defm sf_vc_v_x   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe",   [-1, 1, 2], UseGPR=1>;
865f757f3fSDimitry Andric  defm sf_vc_v_i   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz",   [-1, 1, 2], UseGPR=0>;
875f757f3fSDimitry Andric  defm sf_vc_v_xv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe",   [-1, 0, 1, 2], UseGPR=1>;
885f757f3fSDimitry Andric  defm sf_vc_v_iv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz",   [-1, 0, 1, 2], UseGPR=0>;
895f757f3fSDimitry Andric  defm sf_vc_v_vv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv",   [-1, 0, 1, 2], UseGPR=0>;
905f757f3fSDimitry Andric  defm sf_vc_v_fv  : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvFe",   [-1, 0, 1, 2], UseGPR=0>;
915f757f3fSDimitry Andric  defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 1, 2, 3], UseGPR=1>;
925f757f3fSDimitry Andric  defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 1, 2, 3], UseGPR=0>;
935f757f3fSDimitry Andric  defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 1, 2, 3], UseGPR=0>;
945f757f3fSDimitry Andric  defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvUvFe", [-1, 0, 1, 2, 3], UseGPR=0>;
9506c3fb27SDimitry Andric  let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
965f757f3fSDimitry Andric    defm sf_vc_xvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe",  [0, 1, 2, 3],  UseGPR=1>;
975f757f3fSDimitry Andric    defm sf_vc_ivw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz",  [0, 1, 2, 3],  UseGPR=0>;
985f757f3fSDimitry Andric    defm sf_vc_vvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv",  [0, 1, 2, 3],  UseGPR=0>;
995f757f3fSDimitry Andric    defm sf_vc_fvw   : RVVVCIXBuiltinSet<["si"],  "0KzUwUvFe",  [0, 1, 2, 3],  UseGPR=0>;
1005f757f3fSDimitry Andric    defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 1, 2, 3], UseGPR=1>;
1015f757f3fSDimitry Andric    defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 1, 2, 3], UseGPR=0>;
1025f757f3fSDimitry Andric    defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 1, 2, 3], UseGPR=0>;
1035f757f3fSDimitry Andric    defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"],  "UwKzUwUvFe", [-1, 0, 1, 2, 3], UseGPR=0>;
1045f757f3fSDimitry Andric  }
1055f757f3fSDimitry Andric}
1065f757f3fSDimitry Andric
1075f757f3fSDimitry Andricmulticlass RVVVFWMACCBuiltinSet<list<list<string>> suffixes_prototypes> {
1085f757f3fSDimitry Andric  let OverloadedName = NAME,
1095f757f3fSDimitry Andric      Name = NAME,
1105f757f3fSDimitry Andric      HasMasked = false,
1115f757f3fSDimitry Andric      Log2LMUL = [-2, -1, 0, 1, 2] in
112*647cbc5dSDimitry Andric    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "y", suffixes_prototypes>;
1135f757f3fSDimitry Andric}
1145f757f3fSDimitry Andric
115*647cbc5dSDimitry Andricmulticlass RVVVQMACCDODBuiltinSet<list<list<string>> suffixes_prototypes> {
1165f757f3fSDimitry Andric  let OverloadedName = NAME,
1175f757f3fSDimitry Andric      Name = NAME,
1185f757f3fSDimitry Andric      HasMasked = false,
1195f757f3fSDimitry Andric      Log2LMUL = [0, 1, 2, 3] in
1205f757f3fSDimitry Andric    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "i", suffixes_prototypes>;
1215f757f3fSDimitry Andric}
1225f757f3fSDimitry Andric
123*647cbc5dSDimitry Andricmulticlass RVVVQMACCQOQBuiltinSet<list<list<string>> suffixes_prototypes> {
124*647cbc5dSDimitry Andric  let OverloadedName = NAME,
125*647cbc5dSDimitry Andric      Name = NAME,
126*647cbc5dSDimitry Andric      HasMasked = false,
127*647cbc5dSDimitry Andric      Log2LMUL = [-1, 0, 1, 2] in
128*647cbc5dSDimitry Andric    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "s", suffixes_prototypes>;
129*647cbc5dSDimitry Andric}
130*647cbc5dSDimitry Andric
1315f757f3fSDimitry Andricmulticlass RVVVFNRCLIPBuiltinSet<string suffix, string prototype, string type_range> {
1325f757f3fSDimitry Andric  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
1335f757f3fSDimitry Andric      Name = NAME,
1345f757f3fSDimitry Andric      IRName = NAME,
1355f757f3fSDimitry Andric      MaskedIRName = NAME # "_mask" in
1365f757f3fSDimitry Andric  def : RVVConvBuiltin<suffix, prototype, type_range, NAME>;
1375f757f3fSDimitry Andric}
1385f757f3fSDimitry Andric
1395f757f3fSDimitry Andriclet UnMaskedPolicyScheme = HasPolicyOperand in
1405f757f3fSDimitry Andric  let RequiredFeatures = ["Xsfvqmaccdod"] in {
141*647cbc5dSDimitry Andric    defm sf_vqmaccu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>;
142*647cbc5dSDimitry Andric    defm sf_vqmacc_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)v"]]>;
143*647cbc5dSDimitry Andric    defm sf_vqmaccus_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)v"]]>;
144*647cbc5dSDimitry Andric    defm sf_vqmaccsu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>;
1455f757f3fSDimitry Andric  }
1465f757f3fSDimitry Andric
1475f757f3fSDimitry Andriclet UnMaskedPolicyScheme = HasPolicyOperand in
1485f757f3fSDimitry Andric  let RequiredFeatures = ["Xsfvqmaccqoq"] in {
149*647cbc5dSDimitry Andric    defm sf_vqmaccu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>;
150*647cbc5dSDimitry Andric    defm sf_vqmacc_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)v"]]>;
151*647cbc5dSDimitry Andric    defm sf_vqmaccus_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)v"]]>;
152*647cbc5dSDimitry Andric    defm sf_vqmaccsu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>;
1535f757f3fSDimitry Andric  }
1545f757f3fSDimitry Andric
1555f757f3fSDimitry Andriclet UnMaskedPolicyScheme = HasPolicyOperand in
1565f757f3fSDimitry Andric  let RequiredFeatures = ["Xsfvfwmaccqqq"] in
1575f757f3fSDimitry Andric    defm sf_vfwmacc_4x4x4 : RVVVFWMACCBuiltinSet<[["", "Fw", "FwFwSvv"]]>;
1585f757f3fSDimitry Andric
1595f757f3fSDimitry Andriclet UnMaskedPolicyScheme = HasPassthruOperand, RequiredFeatures = ["Xsfvfnrclipxfqf"] in {
1605f757f3fSDimitry Andriclet ManualCodegen = [{
1615f757f3fSDimitry Andric  {
1625f757f3fSDimitry Andric    // LLVM intrinsic
1635f757f3fSDimitry Andric    // Unmasked: (passthru, vector_in, scalar_in, frm, vl)
1645f757f3fSDimitry Andric    // Masked:   (passthru, vector_in, scalar_in, mask, frm, vl, policy)
1655f757f3fSDimitry Andric
1665f757f3fSDimitry Andric    SmallVector<llvm::Value*, 7> Operands;
1675f757f3fSDimitry Andric    bool HasMaskedOff = !(
1685f757f3fSDimitry Andric        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
1695f757f3fSDimitry Andric        (!IsMasked && PolicyAttrs & RVV_VTA));
1705f757f3fSDimitry Andric    bool HasRoundModeOp = IsMasked ?
1715f757f3fSDimitry Andric      (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) :
1725f757f3fSDimitry Andric      (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
1735f757f3fSDimitry Andric
1745f757f3fSDimitry Andric    unsigned Offset = IsMasked ?
1755f757f3fSDimitry Andric        (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0);
1765f757f3fSDimitry Andric
1775f757f3fSDimitry Andric    if (!HasMaskedOff)
1785f757f3fSDimitry Andric      Operands.push_back(llvm::PoisonValue::get(ResultType));
1795f757f3fSDimitry Andric    else
1805f757f3fSDimitry Andric      Operands.push_back(Ops[IsMasked ? 1 : 0]);
1815f757f3fSDimitry Andric
1825f757f3fSDimitry Andric    Operands.push_back(Ops[Offset]); // op0
1835f757f3fSDimitry Andric    Operands.push_back(Ops[Offset + 1]); // op1
1845f757f3fSDimitry Andric
1855f757f3fSDimitry Andric    if (IsMasked)
1865f757f3fSDimitry Andric      Operands.push_back(Ops[0]); // mask
1875f757f3fSDimitry Andric
1885f757f3fSDimitry Andric    if (HasRoundModeOp) {
1895f757f3fSDimitry Andric      Operands.push_back(Ops[Offset + 2]); // frm
1905f757f3fSDimitry Andric      Operands.push_back(Ops[Offset + 3]); // vl
1915f757f3fSDimitry Andric    } else {
1925f757f3fSDimitry Andric      Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm
1935f757f3fSDimitry Andric      Operands.push_back(Ops[Offset + 2]); // vl
1945f757f3fSDimitry Andric    }
1955f757f3fSDimitry Andric
1965f757f3fSDimitry Andric    if (IsMasked)
1975f757f3fSDimitry Andric      Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
1985f757f3fSDimitry Andric
1995f757f3fSDimitry Andric    IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Operands.back()->getType()};
2005f757f3fSDimitry Andric    llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
2015f757f3fSDimitry Andric    return Builder.CreateCall(F, Operands, "");
2025f757f3fSDimitry Andric  }
2035f757f3fSDimitry Andric}] in {
2045f757f3fSDimitry Andric  let HasFRMRoundModeOp = true in {
2055f757f3fSDimitry Andric    defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqfu", "c">;
2065f757f3fSDimitry Andric    defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqfu", "c">;
2075f757f3fSDimitry Andric  }
2085f757f3fSDimitry Andric  defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqf", "c">;
2095f757f3fSDimitry Andric  defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqf", "c">;
21006c3fb27SDimitry Andric}
21106c3fb27SDimitry Andric}
212