[Clang][RISCV] Implement vlseg and vlsegff.

Differential Revision: https://reviews.llvm.org/D103527
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 7cdec14..495e5ef 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -203,6 +203,8 @@
   // Sub extension of vector spec. Currently only support Zvamo or Zvlsseg.
   string RequiredExtension = "";
 
+  // Number of fields for Zvlsseg.
+  int NF = 1;
 }
 
 //===----------------------------------------------------------------------===//
@@ -768,6 +770,163 @@
   }
 }
 
+defvar NFList = [2, 3, 4, 5, 6, 7, 8];
+
+class PVString<int nf, bit signed> {
+  string S =
+    !cond(!eq(nf, 2): !if(signed, "PvPv", "PUvPUv"),
+          !eq(nf, 3): !if(signed, "PvPvPv", "PUvPUvPUv"),
+          !eq(nf, 4): !if(signed, "PvPvPvPv", "PUvPUvPUvPUv"),
+          !eq(nf, 5): !if(signed, "PvPvPvPvPv", "PUvPUvPUvPUvPUv"),
+          !eq(nf, 6): !if(signed, "PvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUv"),
+          !eq(nf, 7): !if(signed, "PvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUv"),
+          !eq(nf, 8): !if(signed, "PvPvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUvPUv"));
+}
+
+multiclass RVVUnitStridedSegLoad<string op> {
+  foreach type = TypeList in {
+    defvar eew = !cond(!eq(type, "c") : "8",
+                       !eq(type, "s") : "16",
+                       !eq(type, "i") : "32",
+                       !eq(type, "l") : "64",
+                       !eq(type, "h") : "16",
+                       !eq(type, "f") : "32",
+                       !eq(type, "d") : "64");
+      foreach nf = NFList in {
+        let Name = op # nf # "e" # eew # "_v",
+            IRName = op # nf,
+            IRNameMask = op # nf # "_mask",
+            NF = nf,
+            HasNoMaskedOverloaded = false,
+            ManualCodegen = [{
+    {
+      // builtin: (val0 address, val1 address, ..., ptr, vl)
+      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
+                        Ops[NF + 1]->getType()};
+      // intrinsic: (ptr, vl)
+      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1]};
+      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
+      clang::CharUnits Align =
+          CGM.getNaturalTypeAlignment(getContext().getSizeType());
+      llvm::Value *V;
+      for (unsigned I = 0; I < NF; ++I) {
+        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
+                                Address(Ops[I], Align));
+      }
+      return V;
+    }
+            }],
+            ManualCodegenMask = [{
+    {
+      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, vl)
+      // intrinsic: (maskedoff0, ..., ptr, mask, vl)
+      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
+                        Ops[2 * NF + 2]->getType()};
+      SmallVector<llvm::Value*, 12> Operands;
+      for (unsigned I = 0; I < NF; ++I)
+        Operands.push_back(Ops[NF + I + 1]);
+      Operands.push_back(Ops[2 * NF + 1]);
+      Operands.push_back(Ops[NF]);
+      Operands.push_back(Ops[2 * NF + 2]);
+      assert(Operands.size() == NF + 3);
+      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
+      clang::CharUnits Align =
+          CGM.getNaturalTypeAlignment(getContext().getSizeType());
+      llvm::Value *V;
+      for (unsigned I = 0; I < NF; ++I) {
+        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
+                                Address(Ops[I], Align));
+      }
+      return V;
+    }
+            }] in {
+          defvar PV = PVString<nf, /*signed=*/true>.S;
+          defvar PUV = PVString<nf, /*signed=*/false>.S;
+          def : RVVBuiltin<"v", "0" # PV # "PCe", type>;
+          if !not(IsFloat<type>.val) then {
+            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe", type>;
+        }
+      }
+    }
+  }
+}
+
+multiclass RVVUnitStridedSegLoadFF<string op> {
+  foreach type = TypeList in {
+    defvar eew = !cond(!eq(type, "c") : "8",
+                       !eq(type, "s") : "16",
+                       !eq(type, "i") : "32",
+                       !eq(type, "l") : "64",
+                       !eq(type, "h") : "16",
+                       !eq(type, "f") : "32",
+                       !eq(type, "d") : "64");
+      foreach nf = NFList in {
+        let Name = op # nf # "e" # eew # "ff_v",
+            IRName = op # nf # "ff",
+            IRNameMask = op # nf # "ff_mask",
+            NF = nf,
+            HasNoMaskedOverloaded = false,
+            ManualCodegen = [{
+    {
+      // builtin: (val0 address, val1 address, ..., ptr, new_vl, vl)
+      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
+                        Ops[NF + 2]->getType()};
+      // intrinsic: (ptr, vl)
+      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 2]};
+      Value *NewVL = Ops[NF + 1];
+      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
+      clang::CharUnits Align =
+          CGM.getNaturalTypeAlignment(getContext().getSizeType());
+      for (unsigned I = 0; I < NF; ++I) {
+        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
+                            Address(Ops[I], Align));
+      }
+      // Store new_vl.
+      return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
+                                 Address(NewVL, Align));
+    }
+            }],
+            ManualCodegenMask = [{
+    {
+      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, new_vl, vl)
+      // intrinsic: (maskedoff0, ..., ptr, mask, vl)
+      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
+                        Ops[2 * NF + 3]->getType()};
+      SmallVector<llvm::Value*, 12> Operands;
+      for (unsigned I = 0; I < NF; ++I)
+        Operands.push_back(Ops[NF + I + 1]);
+      Operands.push_back(Ops[2 * NF + 1]);
+      Operands.push_back(Ops[NF]);
+      Operands.push_back(Ops[2 * NF + 3]);
+      Value *NewVL = Ops[2 * NF + 2];
+      assert(Operands.size() == NF + 3);
+      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
+      clang::CharUnits Align =
+          CGM.getNaturalTypeAlignment(getContext().getSizeType());
+      for (unsigned I = 0; I < NF; ++I) {
+        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
+                            Address(Ops[I], Align));
+      }
+      // Store new_vl.
+      return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
+                                 Address(NewVL, Align));
+    }
+            }] in {
+          defvar PV = PVString<nf, /*signed=*/true>.S;
+          defvar PUV = PVString<nf, /*signed=*/false>.S;
+          def : RVVBuiltin<"v", "0" # PV # "PCe" # "Pz", type>;
+          if !not(IsFloat<type>.val) then {
+            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "Pz", type>;
+        }
+      }
+    }
+  }
+}
+
 multiclass RVVAMOBuiltinSet<bit has_signed = false, bit has_unsigned = false,
                             bit has_fp = false> {
   defvar type_list = !if(has_fp, ["i","l","f","d"], ["i","l"]);
@@ -1083,6 +1242,12 @@
 defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
 defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
 
+// 7.8 Vector Load/Store Segment Instructions
+let RequiredExtension = "Zvlsseg" in {
+defm : RVVUnitStridedSegLoad<"vlseg">;
+defm : RVVUnitStridedSegLoadFF<"vlseg">;
+}
+
 // 8. Vector AMO Operations
 let RequiredExtension = "Zvamo" in {
 defm vamoswap : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true, /* hasFP */ true>;