[clang] [llvm] [RISCV][VLS] Support RISCV VLS calling convention (PR #100346)

Brandon Wu via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 17 03:17:16 PST 2025


https://github.com/4vtomat updated https://github.com/llvm/llvm-project/pull/100346

>From b838b5a6ca2cdf5d41fa96ee84ba3ef8757c9a67 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Sun, 21 Jul 2024 09:49:11 -0700
Subject: [PATCH 01/10] [RISCV][VLS] Support RISCV VLS calling convention

This patch adds a function attribute `riscv_vls_cc` for RISCV VLS calling
convention which takes 0 or 1 argument, the argument is the `ABI_VLEN`
which is the `VLEN` for passing the fixed-vector arguments, it wraps the
argument as a scalable vector(VLA) using the `ABI_VLEN` and uses the
corresponding mechanism to handle it. The range of `ABI_VLEN` is [32, 65536],
if not specified, the default value is 128.

Here is an example of VLS argument passing:
Non-VLS call:
```
  void original_call(__attribute__((vector_size(16))) int arg) {}
=>
  define void @original_call(i128 noundef %arg) {
  entry:
    ...
    ret void
  }
```
VLS call:
```
  void __attribute__((riscv_vls_cc(256))) vls_call(__attribute__((vector_size(16))) int arg) {}
=>
  define riscv_vls_cc void @vls_call(<vscale x 1 x i32> %arg) {
  entry:
    ...
    ret void
  }
}
```

The first Non-VLS call passes generic vector argument of 16 bytes by
flattened integer.
On the contrary, the VLS call uses `ABI_VLEN=256` which wraps the
vector to <vscale x 1 x i32> where the number of scalable vector elements
is calaulated by: `ORIG_ELTS * RVV_BITS_PER_BLOCK / ABI_VLEN`.
Note: ORIG_ELTS = Vector Size / Type Size = 128 / 32 = 4.
---
 clang/include/clang-c/Index.h                 |  1 +
 clang/include/clang/AST/Type.h                | 26 +++++-
 clang/include/clang/AST/TypeProperties.td     |  7 +-
 clang/include/clang/Basic/Attr.td             |  8 ++
 clang/include/clang/Basic/AttrDocs.td         | 11 +++
 clang/include/clang/Basic/CodeGenOptions.def  |  3 +
 clang/include/clang/Basic/Specifiers.h        |  1 +
 clang/include/clang/CodeGen/CGFunctionInfo.h  |  9 +-
 clang/include/clang/Driver/Options.td         |  5 +-
 clang/lib/AST/ASTContext.cpp                  |  2 +
 clang/lib/AST/ItaniumMangle.cpp               |  1 +
 clang/lib/AST/Type.cpp                        |  2 +
 clang/lib/AST/TypePrinter.cpp                 |  6 ++
 clang/lib/Basic/Targets/RISCV.cpp             |  1 +
 clang/lib/CodeGen/CGCall.cpp                  |  5 +
 clang/lib/CodeGen/CGDebugInfo.cpp             |  2 +
 clang/lib/CodeGen/CodeGenModule.cpp           |  3 +-
 clang/lib/CodeGen/TargetInfo.h                |  2 +-
 clang/lib/CodeGen/Targets/RISCV.cpp           | 91 +++++++++++++------
 clang/lib/Driver/ToolChains/Arch/RISCV.cpp    |  4 +
 clang/lib/Driver/ToolChains/Clang.cpp         | 15 +++
 clang/lib/Sema/SemaDeclAttr.cpp               | 40 +++++++-
 clang/lib/Sema/SemaType.cpp                   | 26 +++++-
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 40 ++++++++
 .../riscv-vector-callingconv-llvm-ir.cpp      | 22 +++++
 .../CodeGen/RISCV/riscv-vector-callingconv.c  | 18 ++++
 .../RISCV/riscv-vector-callingconv.cpp        | 18 ++++
 clang/tools/libclang/CXType.cpp               |  1 +
 llvm/include/llvm/AsmParser/LLToken.h         |  1 +
 llvm/include/llvm/BinaryFormat/Dwarf.def      |  1 +
 llvm/include/llvm/IR/CallingConv.h            |  3 +
 llvm/lib/AsmParser/LLLexer.cpp                |  1 +
 llvm/lib/AsmParser/LLParser.cpp               |  4 +
 llvm/lib/IR/AsmWriter.cpp                     |  3 +
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  1 +
 llvm/test/Assembler/riscv_vls_cc.ll           | 12 +++
 llvm/test/Bitcode/compatibility.ll            |  4 +
 37 files changed, 358 insertions(+), 42 deletions(-)
 create mode 100644 llvm/test/Assembler/riscv_vls_cc.ll

diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index aac5d1fa8aa2e0..21a4863203b6ec 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3053,6 +3053,7 @@ enum CXCallingConv {
   CXCallingConv_M68kRTD = 19,
   CXCallingConv_PreserveNone = 20,
   CXCallingConv_RISCVVectorCall = 21,
+  CXCallingConv_RISCVVLSCall = 22,
 
   CXCallingConv_Invalid = 100,
   CXCallingConv_Unexposed = 200
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index f0fbacccc97bb3..ccdcbfe14ff24b 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1946,7 +1946,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
     /// Extra information which affects how the function is called, like
     /// regparm and the calling convention.
     LLVM_PREFERRED_TYPE(CallingConv)
-    unsigned ExtInfo : 13;
+    unsigned ExtInfo : 18;
 
     /// The ref-qualifier associated with a \c FunctionProtoType.
     ///
@@ -4438,6 +4438,8 @@ class FunctionType : public Type {
 
     // |  CC  |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
     // |0 .. 4|   5    |    6   |       7         |8 .. 10|    11   |    12    |
+    // |RISCV-ABI-VLEN|
+    // |13    ..    17|
     //
     // regparm is either 0 (no regparm attribute) or the regparm value+1.
     enum { CallConvMask = 0x1F };
@@ -4450,23 +4452,25 @@ class FunctionType : public Type {
     };
     enum { NoCfCheckMask = 0x800 };
     enum { CmseNSCallMask = 0x1000 };
-    uint16_t Bits = CC_C;
+    enum { Log2RISCVABIVLenMask = 0x3E000, Log2RISCVABIVLenOffset = 13 };
+    uint32_t Bits = CC_C;
 
-    ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
+    ExtInfo(unsigned Bits) : Bits(static_cast<uint32_t>(Bits)) {}
 
   public:
     // Constructor with no defaults. Use this when you know that you
     // have all the elements (when reading an AST file for example).
     ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
             bool producesResult, bool noCallerSavedRegs, bool NoCfCheck,
-            bool cmseNSCall) {
+            bool cmseNSCall, unsigned Log2RISCVABIVLen) {
       assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
       Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
              (producesResult ? ProducesResultMask : 0) |
              (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
              (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
              (NoCfCheck ? NoCfCheckMask : 0) |
-             (cmseNSCall ? CmseNSCallMask : 0);
+             (cmseNSCall ? CmseNSCallMask : 0) |
+             (Log2RISCVABIVLen << Log2RISCVABIVLenOffset);
     }
 
     // Constructor with all defaults. Use when for example creating a
@@ -4493,6 +4497,10 @@ class FunctionType : public Type {
 
     CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
 
+    unsigned getLog2RISCVABIVLen() const {
+      return (Bits & Log2RISCVABIVLenMask) >> Log2RISCVABIVLenOffset;
+    }
+
     bool operator==(ExtInfo Other) const {
       return Bits == Other.Bits;
     }
@@ -4548,6 +4556,11 @@ class FunctionType : public Type {
       return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
     }
 
+    ExtInfo withLog2RISCVABIVLen(unsigned Log2RISCVABIVLen) const {
+      return ExtInfo((Bits & ~Log2RISCVABIVLenMask) |
+                     (Log2RISCVABIVLen << Log2RISCVABIVLenOffset));
+    }
+
     void Profile(llvm::FoldingSetNodeID &ID) const {
       ID.AddInteger(Bits);
     }
@@ -4657,6 +4670,9 @@ class FunctionType : public Type {
 
   bool getCmseNSCallAttr() const { return getExtInfo().getCmseNSCall(); }
   CallingConv getCallConv() const { return getExtInfo().getCC(); }
+  unsigned getLog2RISCVABIVLen() const {
+    return getExtInfo().getLog2RISCVABIVLen();
+  }
   ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
 
   static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 6f1a76bd18fb50..d5f653013a9b8b 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -313,6 +313,9 @@ let Class = FunctionType in {
   def : Property<"cmseNSCall", Bool> {
     let Read = [{ node->getExtInfo().getCmseNSCall() }];
   }
+  def : Property<"Log2RISCVABIVLen", UInt32> {
+    let Read = [{ node->getExtInfo().getLog2RISCVABIVLen() }];
+  }
 }
 
 let Class = FunctionNoProtoType in {
@@ -320,7 +323,7 @@ let Class = FunctionNoProtoType in {
     auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
                                          callingConvention, producesResult,
                                          noCallerSavedRegs, noCfCheck,
-                                         cmseNSCall);
+                                         cmseNSCall, Log2RISCVABIVLen);
     return ctx.getFunctionNoProtoType(returnType, extInfo);
   }]>;
 }
@@ -363,7 +366,7 @@ let Class = FunctionProtoType in {
     auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
                                          callingConvention, producesResult,
                                          noCallerSavedRegs, noCfCheck,
-                                         cmseNSCall);
+                                         cmseNSCall, Log2RISCVABIVLen);
     FunctionProtoType::ExtProtoInfo epi;
     epi.ExtInfo = extInfo;
     epi.Variadic = variadic;
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 408d3adf370c85..be307b346620f2 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3285,6 +3285,14 @@ def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
  let Documentation = [RISCVVectorCCDocs];
 }
 
+def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [CXX11<"riscv", "vls_cc">,
+                  C23<"riscv", "vls_cc">,
+                  Clang<"riscv_vls_cc">];
+ let Args = [UnsignedArgument<"VectorWidth", /*opt*/1>];
+ let Documentation = [RISCVVLSCCDocs];
+}
+
 def Target : InheritableAttr {
   let Spellings = [GCC<"target">];
   let Args = [StringArgument<"featuresStr">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5e66e752512d0d..1c98eb7c899d7d 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6061,6 +6061,17 @@ them if they use them.
  }];
 }
 
+def RISCVVLSCCDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Heading = "riscv::vls_cc, riscv_vls_cc, clang::riscv_vls_cc";
+ let Content = [{
+The ``riscv_vls_cc`` attribute can be applied to a function. Functions
+declared with this attribute will utilize the standard fixed-length vector
+calling convention variant instead of the default calling convention defined by
+the ABI. This variant aims to pass fixed-length vectors via vector registers,
+if possible, rather than through general-purpose registers.}];
+}
+
 def PreferredNameDocs : Documentation {
   let Category = DocCatDecl;
   let Content = [{
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 0f4ed13d5f3d8c..1c14400e699f52 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -465,6 +465,9 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
 /// non-deleting destructors. (No effect on Microsoft ABI.)
 CODEGENOPT(CtorDtorReturnThis, 1, 0)
 
+/// Specify the VLEN for VLS calling convention.
+CODEGENOPT(RISCVABIVLen, 17, 0)
+
 /// FIXME: Make DebugOptions its own top-level .def file.
 #include "DebugOptions.def"
 
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 9c089908fdc130..d2df5a24da143e 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -300,6 +300,7 @@ namespace clang {
     CC_M68kRTD,           // __attribute__((m68k_rtd))
     CC_PreserveNone,      // __attribute__((preserve_none))
     CC_RISCVVectorCall,   // __attribute__((riscv_vector_cc))
+    CC_RISCVVLSCall,      // __attribute__((riscv_vls_cc))
   };
 
   /// Checks whether the given calling convention supports variadic
diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 9d785d878b61dc..44ae2755a2ab04 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -625,6 +625,9 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
+  /// Log2 of ABI_VLEN used in RISCV VLS calling convention.
+  unsigned Log2RISCVABIVLen : 5;
+
   RequiredArgs Required;
 
   /// The struct representing all arguments passed in memory.  Only used when
@@ -735,11 +738,13 @@ class CGFunctionInfo final
   bool getHasRegParm() const { return HasRegParm; }
   unsigned getRegParm() const { return RegParm; }
 
+  unsigned getLog2RISCVABIVLen() const { return Log2RISCVABIVLen; }
+
   FunctionType::ExtInfo getExtInfo() const {
     return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
                                  getASTCallingConvention(), isReturnsRetained(),
                                  isNoCallerSavedRegs(), isNoCfCheck(),
-                                 isCmseNSCall());
+                                 isCmseNSCall(), getLog2RISCVABIVLen());
   }
 
   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -793,6 +798,7 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
+    ID.AddInteger(Log2RISCVABIVLen);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -820,6 +826,7 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
+    ID.AddInteger(info.getLog2RISCVABIVLen());
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 2721c1b5d8dc55..e1c4741a9ea6da 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4992,7 +4992,10 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
       !eq(GlobalDocumentation.Program, "Flang") : "",
       true: " The value will be reflected in __riscv_v_fixed_vlen preprocessor define"),
     " (RISC-V only)")>;
-
+def mriscv_abi_vlen_EQ : Joined<["-"], "mriscv-abi-vlen=">, Group<m_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Specify the VLEN for VLS calling convention.">,
+  MarshallingInfoInt<CodeGenOpts<"RISCVABIVLen">>;
 def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
   HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
 def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index be1dd29d462788..7d043068fa095c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11108,6 +11108,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
     return {};
   if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
     return {};
+  if (lbaseInfo.getLog2RISCVABIVLen() != rbaseInfo.getLog2RISCVABIVLen())
+    return {};
 
   // When merging declarations, it's common for supplemental information like
   // attributes to only be present in one of the declarations, and we generally
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 1dd936cf4fb518..a63556c647af42 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3489,6 +3489,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
   case CC_M68kRTD:
   case CC_PreserveNone:
   case CC_RISCVVectorCall:
+  case CC_RISCVVLSCall:
     // FIXME: we should be mangling all of the above.
     return "";
 
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index caa0ac858a1bea..3472972f6f1065 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3561,6 +3561,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   case CC_PreserveNone: return "preserve_none";
     // clang-format off
   case CC_RISCVVectorCall: return "riscv_vector_cc";
+  case CC_RISCVVLSCall: return "riscv_vls_cc";
     // clang-format on
   }
 
@@ -4228,6 +4229,7 @@ bool AttributedType::isCallingConv() const {
   case attr::M68kRTD:
   case attr::PreserveNone:
   case attr::RISCVVectorCC:
+  case attr::RISCVVLSCC:
     return true;
   }
   llvm_unreachable("invalid attr kind");
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index a850410ffc8468..65d3b3108175d2 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1136,6 +1136,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
     case CC_RISCVVectorCall:
       OS << "__attribute__((riscv_vector_cc))";
       break;
+    case CC_RISCVVLSCall:
+      OS << "__attribute__((riscv_vls_cc))";
+      break;
     }
   }
 
@@ -2064,6 +2067,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
   case attr::RISCVVectorCC:
     OS << "riscv_vector_cc";
     break;
+  case attr::RISCVVLSCC:
+    OS << "riscv_vls_cc";
+    break;
   case attr::NoDeref:
     OS << "noderef";
     break;
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index db23b0c2283385..ebced9da22e8c0 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -516,6 +516,7 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
     return CCCR_Warning;
   case CC_C:
   case CC_RISCVVectorCall:
+  case CC_RISCVVLSCall:
     return CCCR_OK;
   }
 }
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index e0cf6ca69f0df2..9e143c26fb47ec 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -76,6 +76,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
     // clang-format off
   case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
+  case CC_RISCVVLSCall: return llvm::CallingConv::RISCV_VLSCall;
     // clang-format on
   }
 }
@@ -266,6 +267,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
   if (D->hasAttr<RISCVVectorCCAttr>())
     return CC_RISCVVectorCall;
 
+  if (D->hasAttr<RISCVVLSCCAttr>())
+    return CC_RISCVVLSCall;
+
   return CC_C;
 }
 
@@ -861,6 +865,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
   FI->HasExtParameterInfos = !paramInfos.empty();
   FI->getArgsBuffer()[0].type = resultType;
   FI->MaxVectorWidth = 0;
+  FI->Log2RISCVABIVLen = info.getLog2RISCVABIVLen();
   for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
     FI->getArgsBuffer()[i + 1].type = argTypes[i];
   for (unsigned i = 0, e = paramInfos.size(); i != e; ++i)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index f9cba414dcfe2c..9d6fa7f98461b7 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1593,6 +1593,8 @@ static unsigned getDwarfCC(CallingConv CC) {
     return llvm::dwarf::DW_CC_LLVM_PreserveNone;
   case CC_RISCVVectorCall:
     return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
+  case CC_RISCVVLSCall:
+    return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
   }
   return 0;
 }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index dfb51b11e1d851..30d455a5d509bc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -231,7 +231,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
     else if (ABIStr.ends_with("d"))
       ABIFLen = 64;
     bool EABI = ABIStr.ends_with("e");
-    return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
+    return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen,
+                                        CodeGenOpts.RISCVABIVLen, EABI);
   }
 
   case llvm::Triple::systemz: {
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index ab3142bdea684e..6dd4085bb5101b 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -551,7 +551,7 @@ createPPC64_SVR4_TargetCodeGenInfo(CodeGenModule &CGM, PPC64_SVR4_ABIKind Kind,
 
 std::unique_ptr<TargetCodeGenInfo>
 createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen,
-                             bool EABI);
+                             unsigned ABIVLen, bool EABI);
 
 std::unique_ptr<TargetCodeGenInfo>
 createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM);
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 2b70f2bd3f38b9..f4c37eee20c21c 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -25,6 +26,7 @@ class RISCVABIInfo : public DefaultABIInfo {
   // ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target
   // with soft float ABI has FLen==0).
   unsigned FLen;
+  unsigned ABIVLen;
   const int NumArgGPRs;
   const int NumArgFPRs;
   const bool EABI;
@@ -36,17 +38,17 @@ class RISCVABIInfo : public DefaultABIInfo {
 
 public:
   RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
-               bool EABI)
-      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
-        NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
+               unsigned ABIVLen, bool EABI)
+      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), ABIVLen(ABIVLen),
+        NumArgGPRs(EABI ? 6 : 8), NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
 
   // DefaultABIInfo's classifyReturnType and classifyArgumentType are
   // non-virtual, but computeInfo is virtual, so we overload it.
   void computeInfo(CGFunctionInfo &FI) const override;
 
   ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &ArgGPRsLeft,
-                                  int &ArgFPRsLeft) const;
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
+                                  int &ArgFPRsLeft, unsigned ArgABIVLen) const;
+  ABIArgInfo classifyReturnType(QualType RetTy, unsigned ArgABIVLen) const;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -62,7 +64,7 @@ class RISCVABIInfo : public DefaultABIInfo {
                                                llvm::Type *Field2Ty,
                                                CharUnits Field2Off) const;
 
-  ABIArgInfo coerceVLSVector(QualType Ty) const;
+  ABIArgInfo coerceVLSVector(QualType Ty, unsigned ArgABIVLen = 0) const;
 
   using ABIInfo::appendAttributeMangling;
   void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
@@ -111,9 +113,13 @@ void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
 }
 
 void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  unsigned ArgABIVLen = 1 << FI.getExtInfo().getLog2RISCVABIVLen();
+  if (ArgABIVLen == 1)
+    ArgABIVLen = ABIVLen;
+
   QualType RetTy = FI.getReturnType();
   if (!getCXXABI().classifyReturnType(FI))
-    FI.getReturnInfo() = classifyReturnType(RetTy);
+    FI.getReturnInfo() = classifyReturnType(RetTy, ArgABIVLen);
 
   // IsRetIndirect is true if classifyArgumentType indicated the value should
   // be passed indirect, or if the type size is a scalar greater than 2*XLen
@@ -139,8 +145,8 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
   int ArgNum = 0;
   for (auto &ArgInfo : FI.arguments()) {
     bool IsFixed = ArgNum < NumFixedArgs;
-    ArgInfo.info =
-        classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft, ArgFPRsLeft);
+    ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft,
+                                        ArgFPRsLeft, ArgABIVLen);
     ArgNum++;
   }
 }
@@ -361,7 +367,8 @@ ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
 
 // Fixed-length RVV vectors are represented as scalable vectors in function
 // args/return and must be coerced from fixed vectors.
-ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty) const {
+ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
+                                         unsigned ArgABIVLen) const {
   assert(Ty->isVectorType() && "expected vector type!");
 
   const auto *VT = Ty->castAs<VectorType>();
@@ -385,23 +392,48 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty) const {
     NumElts *= 8;
     break;
   default:
-    assert(VT->getVectorKind() == VectorKind::RVVFixedLengthData &&
+    assert((VT->getVectorKind() == VectorKind::Generic ||
+            VT->getVectorKind() == VectorKind::RVVFixedLengthData) &&
            "Unexpected vector kind");
     EltType = CGT.ConvertType(VT->getElementType());
   }
 
-  // The MinNumElts is simplified from equation:
-  // NumElts / VScale =
-  //  (EltSize * NumElts / (VScale * RVVBitsPerBlock))
-  //    * (RVVBitsPerBlock / EltSize)
-  llvm::ScalableVectorType *ResType =
-      llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
+  llvm::ScalableVectorType *ResType;
+
+  if (ArgABIVLen == 0) {
+    // The MinNumElts is simplified from equation:
+    // NumElts / VScale =
+    //  (EltSize * NumElts / (VScale * RVVBitsPerBlock))
+    //    * (RVVBitsPerBlock / EltSize)
+    ResType = llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
+  } else {
+    // If the corresponding extension is not supported, just make it an i32
+    // vector.
+    const TargetInfo &TI = getContext().getTargetInfo();
+    if ((EltType->isHalfTy() && !TI.hasFeature("zvfhmin")) ||
+        (EltType->isBFloatTy() && !TI.hasFeature("zvfbfmin")) ||
+        (EltType->isFloatTy() && !TI.hasFeature("zve32f")) ||
+        (EltType->isDoubleTy() && !TI.hasFeature("zve64d")) ||
+        (EltType->isIntegerTy(64) && !TI.hasFeature("zve64x")) ||
+        EltType->isIntegerTy(128)) {
+      NumElts = NumElts * EltType->getScalarSizeInBits() / 32;
+      EltType = llvm::Type::getInt32Ty(getVMContext());
+    }
+
+    // Generic vector
+    // The number of element need to be at least 1.
+    ResType = llvm::ScalableVectorType::get(
+        EltType,
+        llvm::divideCeil(NumElts * llvm::RISCV::RVVBitsPerBlock, ArgABIVLen));
+  }
+
   return ABIArgInfo::getDirect(ResType);
 }
 
 ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
                                               int &ArgGPRsLeft,
-                                              int &ArgFPRsLeft) const {
+                                              int &ArgFPRsLeft,
+                                              unsigned ArgABIVLen) const {
   assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
@@ -498,13 +530,18 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
     return ABIArgInfo::getDirect();
   }
 
-  if (const VectorType *VT = Ty->getAs<VectorType>())
+  if (const VectorType *VT = Ty->getAs<VectorType>()) {
     if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
       return coerceVLSVector(Ty);
+    if (VT->getVectorKind() == VectorKind::Generic && ArgABIVLen != 0)
+      // Generic vector without riscv_vls_cc should fall through and pass by
+      // reference.
+      return coerceVLSVector(Ty, ArgABIVLen);
+  }
 
   // Aggregates which are <= 2*XLen will be passed in registers if possible,
   // so coerce to integers.
@@ -527,7 +564,8 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
   return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
 }
 
-ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const {
+ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
+                                            unsigned ArgABIVLen) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
@@ -536,8 +574,8 @@ ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const {
 
   // The rules for return and argument types are the same, so defer to
   // classifyArgumentType.
-  return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft,
-                              ArgFPRsLeft);
+  return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft, ArgFPRsLeft,
+                              ArgABIVLen);
 }
 
 RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
@@ -576,9 +614,9 @@ namespace {
 class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen,
-                         unsigned FLen, bool EABI)
+                         unsigned FLen, unsigned ABIVLen, bool EABI)
       : TargetCodeGenInfo(
-            std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
+            std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, ABIVLen, EABI)) {
     SwiftInfo =
         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
   }
@@ -610,7 +648,8 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 
 std::unique_ptr<TargetCodeGenInfo>
 CodeGen::createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen,
-                                      unsigned FLen, bool EABI) {
+                                      unsigned FLen, unsigned ABIVLen,
+                                      bool EABI) {
   return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen,
-                                                  EABI);
+                                                  ABIVLen, EABI);
 }
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 6935904a24edbf..18da247b3eab48 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -95,6 +95,10 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
       CPUFastVectorUnaligned = true;
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_mriscv_abi_vlen_EQ))
+    Features.push_back(
+        Args.MakeArgString(Twine("+abi-vlen-") + A->getValue() + "b"));
+
 // Handle features corresponding to "-ffixed-X" options
 #define RESERVE_REG(REG)                                                       \
   if (Args.hasArg(options::OPT_ffixed_##REG))                                  \
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 33f08cf28feca1..3e83192ceebee8 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2225,6 +2225,21 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
           << A->getSpelling() << Val;
     }
   }
+
+  if (Arg *A = Args.getLastArg(options::OPT_mriscv_abi_vlen_EQ)) {
+    StringRef ABIVLenStr = A->getValue();
+    unsigned ABIVLen;
+    const Driver &D = getToolChain().getDriver();
+    if (ABIVLenStr.getAsInteger(10, ABIVLen) || ABIVLen < 32 ||
+        ABIVLen > 65536 || !llvm::isPowerOf2_64(ABIVLen)) {
+      D.Diag(diag::err_drv_invalid_value)
+          << A->getOption().getName() << ABIVLenStr;
+      return;
+    }
+
+    CmdArgs.push_back(
+        Args.MakeArgString(Twine("-mriscv-abi-vlen=") + A->getValue()));
+  }
 }
 
 void Clang::AddSparcTargetArgs(const ArgList &Args,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c2d82b9aa9b321..31fe6e342ed0f5 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5013,6 +5013,25 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   case ParsedAttr::AT_RISCVVectorCC:
     D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL));
     return;
+  case ParsedAttr::AT_RISCVVLSCC: {
+    // If the riscv_abi_vlen doesn't have any argument, default ABI_VLEN is 128.
+    unsigned VectorLength = 128;
+    if (AL.getNumArgs() &&
+        !S.checkUInt32Argument(AL, AL.getArgAsExpr(0), VectorLength))
+      return;
+    if (VectorLength < 32 || VectorLength > 65536) {
+      S.Diag(AL.getLoc(), diag::err_argument_invalid_range)
+          << VectorLength << 32 << 65536;
+      return;
+    }
+    if (!llvm::isPowerOf2_64(VectorLength)) {
+      S.Diag(AL.getLoc(), diag::err_argument_not_power_of_2);
+      return;
+    }
+
+    D->addAttr(::new (S.Context) RISCVVLSCCAttr(S.Context, AL, VectorLength));
+    return;
+  }
   default:
     llvm_unreachable("unexpected attribute kind");
   }
@@ -5132,10 +5151,19 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
     return false;
   }
 
-  unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
-  if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) {
-    Attrs.setInvalid();
-    return true;
+  if (Attrs.getKind() == ParsedAttr::AT_RISCVVLSCC) {
+    // riscv_vls_cc only accept 0 or 1 argument.
+    if (!Attrs.checkAtLeastNumArgs(*this, 0) ||
+        !Attrs.checkAtMostNumArgs(*this, 1)) {
+      Attrs.setInvalid();
+      return true;
+    }
+  } else {
+    unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
+    if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) {
+      Attrs.setInvalid();
+      return true;
+    }
   }
 
   // TODO: diagnose uses of these conventions on the wrong target.
@@ -5220,6 +5248,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
   case ParsedAttr::AT_RISCVVectorCC:
     CC = CC_RISCVVectorCall;
     break;
+  case ParsedAttr::AT_RISCVVLSCC:
+    CC = CC_RISCVVLSCall;
+    break;
   default: llvm_unreachable("unexpected attribute kind");
   }
 
@@ -7075,6 +7106,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_M68kRTD:
   case ParsedAttr::AT_PreserveNone:
   case ParsedAttr::AT_RISCVVectorCC:
+  case ParsedAttr::AT_RISCVVLSCC:
     handleCallConvAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Suppress:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 2ccf5a8e1d6f31..9a58fcc2836bcb 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -143,7 +143,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
   case ParsedAttr::AT_PreserveAll:                                             \
   case ParsedAttr::AT_M68kRTD:                                                 \
   case ParsedAttr::AT_PreserveNone:                                            \
-  case ParsedAttr::AT_RISCVVectorCC
+  case ParsedAttr::AT_RISCVVectorCC:                                           \
+  case ParsedAttr::AT_RISCVVLSCC
 
 // Function type attributes.
 #define FUNCTION_TYPE_ATTRS_CASELIST                                           \
@@ -7617,6 +7618,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
     return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr);
   case ParsedAttr::AT_RISCVVectorCC:
     return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr);
+  case ParsedAttr::AT_RISCVVLSCC:
+    return ::new (Ctx) RISCVVLSCCAttr(Ctx, Attr, /*dummy*/ 0);
   }
   llvm_unreachable("unexpected attribute kind!");
 }
@@ -8103,6 +8106,27 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   CallingConv CCOld = fn->getCallConv();
   Attr *CCAttr = getCCTypeAttr(S.Context, attr);
 
+  if (attr.getKind() == ParsedAttr::AT_RISCVVLSCC) {
+    // If the riscv_abi_vlen doesn't have any argument, default ABI_VLEN is 128.
+    unsigned ABIVLen = 128;
+    if (attr.getNumArgs() &&
+        !S.checkUInt32Argument(attr, attr.getArgAsExpr(0), ABIVLen))
+      return false;
+    if (ABIVLen < 32 || ABIVLen > 65536) {
+      S.Diag(attr.getLoc(), diag::err_argument_invalid_range)
+          << ABIVLen << 32 << 65536;
+      return false;
+    }
+    if (!llvm::isPowerOf2_64(ABIVLen)) {
+      S.Diag(attr.getLoc(), diag::err_argument_not_power_of_2);
+      return false;
+    }
+
+    auto EI = unwrapped.get()->getExtInfo().withLog2RISCVABIVLen(
+        llvm::Log2_64(ABIVLen));
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+  }
+
   if (CCOld != CC) {
     // Error out on when there's already an attribute on the type
     // and the CCs don't match.
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 072d8a863d4570..8c205459db9993 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -3,6 +3,10 @@
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
 // RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
+// RUN: %clang_cc1 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
+// RUN: %clang_cc1 -std=c23 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
 
 #include <riscv_vector.h>
 
@@ -32,3 +36,39 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
   __riscv_vse32_v_i32m1(base, val, vl);
   return ret;
 }
+
+// CHECK-LLVM: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local void @test_vls_no_cc(<vscale x 1 x i32> noundef %arg.coerce)
+void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc(256)]] void test_vls_256_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index c01aeb21f67571..9447e6fae0cea2 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -1,6 +1,8 @@
 // REQUIRES: riscv-registered-target
 // RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
+// RUN: %clang_cc1 -std=c++11 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
 
 #include <riscv_vector.h>
 
@@ -30,3 +32,23 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
   __riscv_vse32_v_i32m1(base, val, vl);
   return ret;
 }
+
+// CHECK-LLVM: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local void @_Z14test_vls_no_ccDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
+void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
index 5c35901799b427..da4819186f4e21 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
@@ -15,3 +15,21 @@ void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-e
 
 void test_no_attribute2(int); // expected-note {{previous declaration is here}}
 [[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}
+
+__attribute__((riscv_vls_cc)) int var_vls; // expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'int'}}
+
+__attribute__((riscv_vls_cc)) void func_vls();
+__attribute__((riscv_vls_cc(1))) void func_vls_invalid(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'void (void)__attribute__((riscv_vls_cc))'}}
+__attribute__((riscv_vls_cc(129))) void func_vls_invalid(); // expected-error {{argument should be a power of 2}} expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'void (void)__attribute__((riscv_vls_cc))'}}
+
+void test_vls_no_attribute(int); // expected-note {{previous declaration is here}}
+void __attribute__((riscv_vls_cc)) test_vls_no_attribute(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
+
+[[riscv::vls_cc]] int var2_vls; // expected-warning {{'vls_cc' only applies to function types; type here is 'int'}}
+
+[[riscv::vls_cc]] void func2_vls();
+[[riscv::vls_cc(1)]] void func_vls_invalid2(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'vls_cc' only applies to function types; type here is 'void (void)'}}
+[[riscv::vls_cc(129)]] void func_vls_invalid2(); // expected-error {{argument should be a power of 2}} expected-warning {{'vls_cc' only applies to function types; type here is 'void (void)'}}
+
+void test_vls_no_attribute2(int); // expected-note {{previous declaration is here}}
+[[riscv::vls_cc]] void test_vls_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
index 264bb7d9ad7c00..5e27c76d5307fc 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
@@ -33,3 +33,21 @@ void test_lambda2() {
   [[riscv::vector_cc]] auto lambda = []() { // expected-warning {{'vector_cc' only applies to function types; type here is 'auto'}}
   };
 }
+
+[[riscv::vls_cc]] int var_vls; // expected-warning {{'vls_cc' only applies to function types; type here is 'int'}}
+
+[[riscv::vls_cc]] void func_vls();
+[[riscv::vls_cc(1)]] void func_invalid_vls(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'vls_cc' only applies to function types; type here is 'void ()'}}
+[[riscv::vls_cc(129)]] void func_invalid_vls(); // expected-error {{argument should be a power of 2}} expected-warning {{'vls_cc' only applies to function types; type here is 'void ()'}}
+
+void test_no_attribute_vls(int); // expected-note {{previous declaration is here}}
+[[riscv::vls_cc]] void test_no_attribute_vls(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
+
+class test_cc_vls {
+  [[riscv::vls_cc]] void member_func();
+};
+
+void test_lambda_vls() {
+  [[riscv::vls_cc]] auto lambda = []() { // expected-warning {{'vls_cc' only applies to function types; type here is 'auto'}}
+  };
+}
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 5da87c6f4aa9c4..65fa6fa2540954 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -701,6 +701,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
       TCALLINGCONV(M68kRTD);
       TCALLINGCONV(PreserveNone);
       TCALLINGCONV(RISCVVectorCall);
+      TCALLINGCONV(RISCVVLSCall);
     case CC_SpirFunction: return CXCallingConv_Unexposed;
     case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed;
     case CC_OpenCLKernel: return CXCallingConv_Unexposed;
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 7b47bc88ddb25f..b079c27b09064a 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -185,6 +185,7 @@ enum Kind {
   kw_m68k_rtdcc,
   kw_graalcc,
   kw_riscv_vector_cc,
+  kw_riscv_vls_cc,
 
   // Attributes:
   kw_attributes,
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2bb84fbc864d8e..a756bb88f8ef1a 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -1120,6 +1120,7 @@ HANDLE_DW_CC(0xcc, LLVM_M68kRTD)
 HANDLE_DW_CC(0xcd, LLVM_PreserveNone)
 HANDLE_DW_CC(0xce, LLVM_RISCVVectorCall)
 HANDLE_DW_CC(0xcf, LLVM_SwiftTail)
+HANDLE_DW_CC(0xd0, LLVM_RISCVVLSCall)
 // From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
 // generated by any toolchain.  It is used internally to GDB to indicate OpenCL
 // C functions that have been compiled with the IBM XL C for OpenCL compiler and
diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h
index 55e32028e3ed08..bc3a75f2fe6656 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -270,6 +270,9 @@ namespace CallingConv {
     /// Preserve X1-X15, X19-X29, SP, Z0-Z31, P0-P15.
     AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 = 111,
 
+    /// Calling convention used for RISC-V V-extension fixed vectors.
+    RISCV_VLSCall = 112,
+
     /// The highest possible ID. Must be some 2^k - 1.
     MaxID = 1023
   };
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5ea507c009bdc6..f5468fdcb60b2e 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -683,6 +683,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(m68k_rtdcc);
   KEYWORD(graalcc);
   KEYWORD(riscv_vector_cc);
+  KEYWORD(riscv_vls_cc);
 
   KEYWORD(cc);
   KEYWORD(c);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 81d048b32e139b..abf98f76b6a610 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2207,6 +2207,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
 ///   ::= 'm68k_rtdcc'
 ///   ::= 'graalcc'
 ///   ::= 'riscv_vector_cc'
+///   ::= 'riscv_vls_cc'
 ///   ::= 'cc' UINT
 ///
 bool LLParser::parseOptionalCallingConv(unsigned &CC) {
@@ -2283,6 +2284,9 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
   case lltok::kw_riscv_vector_cc:
     CC = CallingConv::RISCV_VectorCall;
     break;
+  case lltok::kw_riscv_vls_cc:
+    CC = CallingConv::RISCV_VLSCall;
+    break;
   case lltok::kw_cc: {
       Lex.Lex();
       return parseUInt32(CC);
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index a37a8901489cf7..67a8e6260f1e39 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -368,6 +368,9 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   case CallingConv::RISCV_VectorCall:
     Out << "riscv_vector_cc";
     break;
+  case CallingConv::RISCV_VLSCall:
+    Out << "riscv_vls_cc";
+    break;
   }
 }
 
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b25cb128bce9fb..96f51580d6ace9 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19901,6 +19901,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
   case CallingConv::SPIR_KERNEL:
   case CallingConv::GRAAL:
   case CallingConv::RISCV_VectorCall:
+  case CallingConv::RISCV_VLSCall:
     break;
   case CallingConv::GHC:
     if (Subtarget.hasStdExtE())
diff --git a/llvm/test/Assembler/riscv_vls_cc.ll b/llvm/test/Assembler/riscv_vls_cc.ll
new file mode 100644
index 00000000000000..cc63e61ed6a1f7
--- /dev/null
+++ b/llvm/test/Assembler/riscv_vls_cc.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+; CHECK: define riscv_vls_cc void @no_args() {
+define riscv_vls_cc void @no_args() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc void @byval_arg(ptr byval(i32) %0) {
+define riscv_vls_cc void @byval_arg(ptr byval(i32)) {
+  ret void
+}
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index a28156cdaa2797..485508ca0013ad 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -516,6 +516,10 @@ declare cc96 void @f.cc96()
 ; CHECK: declare amdgpu_es void @f.cc96()
 declare amdgpu_es void @f.amdgpu_es()
 ; CHECK: declare amdgpu_es void @f.amdgpu_es()
+declare cc112 void @f.cc112()
+; CHECK: declare riscv_vls_cc void @f.cc112()
+declare riscv_vls_cc void @riscv_vls_cc()
+; CHECK: declare riscv_vls_cc void @riscv_vls_cc()
 declare cc1023 void @f.cc1023()
 ; CHECK: declare cc1023 void @f.cc1023()
 

>From 35039565c4e204ec1c6aa39834b46b72ea99cdaa Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Sat, 9 Nov 2024 18:58:14 -0800
Subject: [PATCH 02/10] fixup! [RISCV][VLS] Support RISCV VLS calling
 convention

---
 clang/lib/CodeGen/Targets/RISCV.cpp | 2 +-
 clang/lib/Sema/SemaDeclAttr.cpp     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index f4c37eee20c21c..4762d82e982fda 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -421,7 +421,7 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
     }
 
     // Generic vector
-    // The number of element need to be at least 1.
+    // The number of elements needs to be at least 1.
     ResType = llvm::ScalableVectorType::get(
         EltType,
         llvm::divideCeil(NumElts * llvm::RISCV::RVVBitsPerBlock, ArgABIVLen));
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 31fe6e342ed0f5..4645c47f85b597 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5152,7 +5152,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
   }
 
   if (Attrs.getKind() == ParsedAttr::AT_RISCVVLSCC) {
-    // riscv_vls_cc only accept 0 or 1 argument.
+    // riscv_vls_cc only accepts 0 or 1 argument.
     if (!Attrs.checkAtLeastNumArgs(*this, 0) ||
         !Attrs.checkAtMostNumArgs(*this, 1)) {
       Attrs.setInvalid();

>From a19954741b3ffd726d40ba430400002b99fae14b Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Tue, 3 Dec 2024 23:28:32 -0800
Subject: [PATCH 03/10] fixup! [RISCV][VLS] Support RISCV VLS calling
 convention

---
 clang/lib/CodeGen/Targets/RISCV.cpp           | 13 +++++++---
 clang/lib/Sema/SemaType.cpp                   |  7 ++---
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 26 ++++++++++++++-----
 .../riscv-vector-callingconv-llvm-ir.cpp      | 16 +++++++++---
 4 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 4762d82e982fda..6c96e6338cda23 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -114,8 +114,13 @@ void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
 
 void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
   unsigned ArgABIVLen = 1 << FI.getExtInfo().getLog2RISCVABIVLen();
-  if (ArgABIVLen == 1)
+  // If ArgABIVLen is default value(2), try to set it to the value passed by
+  // option if any, otherwise, set it to default value 128.
+  // Note that ArgABIVLen == 1 means vector_cc is not enabled.
+  if (ArgABIVLen == 2 && ABIVLen)
     ArgABIVLen = ABIVLen;
+  else if (ArgABIVLen == 2)
+    ArgABIVLen = 128;
 
   QualType RetTy = FI.getReturnType();
   if (!getCXXABI().classifyReturnType(FI))
@@ -416,8 +421,8 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
         (EltType->isDoubleTy() && !TI.hasFeature("zve64d")) ||
         (EltType->isIntegerTy(64) && !TI.hasFeature("zve64x")) ||
         EltType->isIntegerTy(128)) {
-      NumElts = NumElts * EltType->getScalarSizeInBits() / 32;
-      EltType = llvm::Type::getInt32Ty(getVMContext());
+      EltType =
+          llvm::Type::getIntNTy(getVMContext(), EltType->getScalarSizeInBits());
     }
 
     // Generic vector
@@ -537,7 +542,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
       return coerceVLSVector(Ty);
-    if (VT->getVectorKind() == VectorKind::Generic && ArgABIVLen != 0)
+    if (VT->getVectorKind() == VectorKind::Generic && ArgABIVLen != 1)
       // Generic vector without riscv_vls_cc should fall through and pass by
       // reference.
       return coerceVLSVector(Ty, ArgABIVLen);
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 9a58fcc2836bcb..f25b732b026f97 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8107,12 +8107,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   Attr *CCAttr = getCCTypeAttr(S.Context, attr);
 
   if (attr.getKind() == ParsedAttr::AT_RISCVVLSCC) {
-    // If the riscv_abi_vlen doesn't have any argument, default ABI_VLEN is 128.
-    unsigned ABIVLen = 128;
+    // If the riscv_abi_vlen doesn't have any argument, we set set it to 2 to
+    // differentiate from functions without attribute.
+    unsigned ABIVLen = 2;
     if (attr.getNumArgs() &&
         !S.checkUInt32Argument(attr, attr.getArgAsExpr(0), ABIVLen))
       return false;
-    if (ABIVLen < 32 || ABIVLen > 65536) {
+    if (ABIVLen != 2 && (ABIVLen < 32 || ABIVLen > 65536)) {
       S.Diag(attr.getLoc(), diag::err_argument_invalid_range)
           << ABIVLen << 32 << 65536;
       return false;
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 8c205459db9993..0b06bede29dc76 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -1,10 +1,14 @@
 // REQUIRES: riscv-registered-target
 // RUN: %clang_cc1 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve32x \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ZVE32X %s
 // RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
 // RUN: %clang_cc1 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
+// RUN: %clang_cc1 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +zve32x \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN-ZVE32X %s
 // RUN: %clang_cc1 -std=c23 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
 
@@ -38,25 +42,33 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 }
 
 // CHECK-LLVM: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local void @test_vls_no_cc(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i16> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 1 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
+
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
+
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 // CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index 9447e6fae0cea2..0b91f8b3877eb2 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -1,8 +1,12 @@
 // REQUIRES: riscv-registered-target
 // RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
+// RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +zve32x \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ZVE32X %s
 // RUN: %clang_cc1 -std=c++11 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
+// RUN: %clang_cc1 -std=c++11 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +zve32x \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN-ZVE32X %s
 
 #include <riscv_vector.h>
 
@@ -34,17 +38,21 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 }
 
 // CHECK-LLVM: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local void @_Z14test_vls_no_ccDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 1 x i32> noundef %arg.coerce)
+[[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
+
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 // CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}

>From 8c8ef947c40ef35643c64b17d7b4b2a4d1c3fef1 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Mon, 9 Dec 2024 10:04:07 -0800
Subject: [PATCH 04/10] fixup! [RISCV][VLS] Support RISCV VLS calling
 convention

---
 clang/lib/Sema/SemaType.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f25b732b026f97..f6f7cbb278f5d5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8113,7 +8113,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
     if (attr.getNumArgs() &&
         !S.checkUInt32Argument(attr, attr.getArgAsExpr(0), ABIVLen))
       return false;
-    if (ABIVLen != 2 && (ABIVLen < 32 || ABIVLen > 65536)) {
+    if (attr.getNumArgs() && (ABIVLen < 32 || ABIVLen > 65536)) {
       S.Diag(attr.getLoc(), diag::err_argument_invalid_range)
           << ABIVLen << 32 << 65536;
       return false;

>From 5190e0fae4f782c5744825d3dab9ae41647a2ed6 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Sun, 22 Dec 2024 23:10:58 -0800
Subject: [PATCH 05/10] fixup! Remove command line option

---
 clang/include/clang/Basic/CodeGenOptions.def  |  3 --
 clang/include/clang/Driver/Options.td         |  4 --
 clang/lib/CodeGen/CodeGenModule.cpp           |  3 +-
 clang/lib/CodeGen/TargetInfo.h                |  2 +-
 clang/lib/CodeGen/Targets/RISCV.cpp           | 50 ++++++++-----------
 clang/lib/Driver/ToolChains/Arch/RISCV.cpp    |  4 --
 clang/lib/Driver/ToolChains/Clang.cpp         | 15 ------
 clang/lib/Sema/SemaType.cpp                   |  6 +--
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 17 -------
 .../riscv-vector-callingconv-llvm-ir.cpp      | 10 ----
 10 files changed, 25 insertions(+), 89 deletions(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 1c14400e699f52..0f4ed13d5f3d8c 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -465,9 +465,6 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
 /// non-deleting destructors. (No effect on Microsoft ABI.)
 CODEGENOPT(CtorDtorReturnThis, 1, 0)
 
-/// Specify the VLEN for VLS calling convention.
-CODEGENOPT(RISCVABIVLen, 17, 0)
-
 /// FIXME: Make DebugOptions its own top-level .def file.
 #include "DebugOptions.def"
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e1c4741a9ea6da..4a4900a0e3b6ea 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4992,10 +4992,6 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
       !eq(GlobalDocumentation.Program, "Flang") : "",
       true: " The value will be reflected in __riscv_v_fixed_vlen preprocessor define"),
     " (RISC-V only)")>;
-def mriscv_abi_vlen_EQ : Joined<["-"], "mriscv-abi-vlen=">, Group<m_Group>,
-  Visibility<[ClangOption, CC1Option]>,
-  HelpText<"Specify the VLEN for VLS calling convention.">,
-  MarshallingInfoInt<CodeGenOpts<"RISCVABIVLen">>;
 def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
   HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
 def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 30d455a5d509bc..dfb51b11e1d851 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -231,8 +231,7 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
     else if (ABIStr.ends_with("d"))
       ABIFLen = 64;
     bool EABI = ABIStr.ends_with("e");
-    return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen,
-                                        CodeGenOpts.RISCVABIVLen, EABI);
+    return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
   }
 
   case llvm::Triple::systemz: {
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index 6dd4085bb5101b..ab3142bdea684e 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -551,7 +551,7 @@ createPPC64_SVR4_TargetCodeGenInfo(CodeGenModule &CGM, PPC64_SVR4_ABIKind Kind,
 
 std::unique_ptr<TargetCodeGenInfo>
 createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen,
-                             unsigned ABIVLen, bool EABI);
+                             bool EABI);
 
 std::unique_ptr<TargetCodeGenInfo>
 createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM);
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 6c96e6338cda23..cff3f3c87214d7 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -26,7 +26,6 @@ class RISCVABIInfo : public DefaultABIInfo {
   // ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target
   // with soft float ABI has FLen==0).
   unsigned FLen;
-  unsigned ABIVLen;
   const int NumArgGPRs;
   const int NumArgFPRs;
   const bool EABI;
@@ -38,8 +37,8 @@ class RISCVABIInfo : public DefaultABIInfo {
 
 public:
   RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
-               unsigned ABIVLen, bool EABI)
-      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), ABIVLen(ABIVLen),
+               bool EABI)
+      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen),
         NumArgGPRs(EABI ? 6 : 8), NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
 
   // DefaultABIInfo's classifyReturnType and classifyArgumentType are
@@ -47,8 +46,8 @@ class RISCVABIInfo : public DefaultABIInfo {
   void computeInfo(CGFunctionInfo &FI) const override;
 
   ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &ArgGPRsLeft,
-                                  int &ArgFPRsLeft, unsigned ArgABIVLen) const;
-  ABIArgInfo classifyReturnType(QualType RetTy, unsigned ArgABIVLen) const;
+                                  int &ArgFPRsLeft, unsigned ABIVLen) const;
+  ABIArgInfo classifyReturnType(QualType RetTy, unsigned ABIVLen) const;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -64,7 +63,7 @@ class RISCVABIInfo : public DefaultABIInfo {
                                                llvm::Type *Field2Ty,
                                                CharUnits Field2Off) const;
 
-  ABIArgInfo coerceVLSVector(QualType Ty, unsigned ArgABIVLen = 0) const;
+  ABIArgInfo coerceVLSVector(QualType Ty, unsigned ABIVLen = 0) const;
 
   using ABIInfo::appendAttributeMangling;
   void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
@@ -113,18 +112,10 @@ void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
 }
 
 void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  unsigned ArgABIVLen = 1 << FI.getExtInfo().getLog2RISCVABIVLen();
-  // If ArgABIVLen is default value(2), try to set it to the value passed by
-  // option if any, otherwise, set it to default value 128.
-  // Note that ArgABIVLen == 1 means vector_cc is not enabled.
-  if (ArgABIVLen == 2 && ABIVLen)
-    ArgABIVLen = ABIVLen;
-  else if (ArgABIVLen == 2)
-    ArgABIVLen = 128;
-
+  unsigned ABIVLen = 1 << FI.getExtInfo().getLog2RISCVABIVLen();
   QualType RetTy = FI.getReturnType();
   if (!getCXXABI().classifyReturnType(FI))
-    FI.getReturnInfo() = classifyReturnType(RetTy, ArgABIVLen);
+    FI.getReturnInfo() = classifyReturnType(RetTy, ABIVLen);
 
   // IsRetIndirect is true if classifyArgumentType indicated the value should
   // be passed indirect, or if the type size is a scalar greater than 2*XLen
@@ -151,7 +142,7 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
   for (auto &ArgInfo : FI.arguments()) {
     bool IsFixed = ArgNum < NumFixedArgs;
     ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft,
-                                        ArgFPRsLeft, ArgABIVLen);
+                                        ArgFPRsLeft, ABIVLen);
     ArgNum++;
   }
 }
@@ -373,7 +364,7 @@ ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
 // Fixed-length RVV vectors are represented as scalable vectors in function
 // args/return and must be coerced from fixed vectors.
 ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
-                                         unsigned ArgABIVLen) const {
+                                         unsigned ABIVLen) const {
   assert(Ty->isVectorType() && "expected vector type!");
 
   const auto *VT = Ty->castAs<VectorType>();
@@ -405,7 +396,7 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
 
   llvm::ScalableVectorType *ResType;
 
-  if (ArgABIVLen == 0) {
+  if (ABIVLen == 0) {
     // The MinNumElts is simplified from equation:
     // NumElts / VScale =
     //  (EltSize * NumElts / (VScale * RVVBitsPerBlock))
@@ -429,7 +420,7 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
     // The number of elements needs to be at least 1.
     ResType = llvm::ScalableVectorType::get(
         EltType,
-        llvm::divideCeil(NumElts * llvm::RISCV::RVVBitsPerBlock, ArgABIVLen));
+        llvm::divideCeil(NumElts * llvm::RISCV::RVVBitsPerBlock, ABIVLen));
   }
 
   return ABIArgInfo::getDirect(ResType);
@@ -438,7 +429,7 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
 ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
                                               int &ArgGPRsLeft,
                                               int &ArgFPRsLeft,
-                                              unsigned ArgABIVLen) const {
+                                              unsigned ABIVLen) const {
   assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
@@ -542,10 +533,10 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
       return coerceVLSVector(Ty);
-    if (VT->getVectorKind() == VectorKind::Generic && ArgABIVLen != 1)
+    if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 1)
       // Generic vector without riscv_vls_cc should fall through and pass by
       // reference.
-      return coerceVLSVector(Ty, ArgABIVLen);
+      return coerceVLSVector(Ty, ABIVLen);
   }
 
   // Aggregates which are <= 2*XLen will be passed in registers if possible,
@@ -570,7 +561,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
 }
 
 ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
-                                            unsigned ArgABIVLen) const {
+                                            unsigned ABIVLen) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
@@ -580,7 +571,7 @@ ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
   // The rules for return and argument types are the same, so defer to
   // classifyArgumentType.
   return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft, ArgFPRsLeft,
-                              ArgABIVLen);
+                              ABIVLen);
 }
 
 RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
@@ -619,9 +610,9 @@ namespace {
 class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen,
-                         unsigned FLen, unsigned ABIVLen, bool EABI)
+                         unsigned FLen, bool EABI)
       : TargetCodeGenInfo(
-            std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, ABIVLen, EABI)) {
+            std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
     SwiftInfo =
         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
   }
@@ -653,8 +644,7 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 
 std::unique_ptr<TargetCodeGenInfo>
 CodeGen::createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen,
-                                      unsigned FLen, unsigned ABIVLen,
-                                      bool EABI) {
+                                      unsigned FLen, bool EABI) {
   return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen,
-                                                  ABIVLen, EABI);
+                                                  EABI);
 }
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 18da247b3eab48..6935904a24edbf 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -95,10 +95,6 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
       CPUFastVectorUnaligned = true;
   }
 
-  if (Arg *A = Args.getLastArg(options::OPT_mriscv_abi_vlen_EQ))
-    Features.push_back(
-        Args.MakeArgString(Twine("+abi-vlen-") + A->getValue() + "b"));
-
 // Handle features corresponding to "-ffixed-X" options
 #define RESERVE_REG(REG)                                                       \
   if (Args.hasArg(options::OPT_ffixed_##REG))                                  \
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 3e83192ceebee8..33f08cf28feca1 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2225,21 +2225,6 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
           << A->getSpelling() << Val;
     }
   }
-
-  if (Arg *A = Args.getLastArg(options::OPT_mriscv_abi_vlen_EQ)) {
-    StringRef ABIVLenStr = A->getValue();
-    unsigned ABIVLen;
-    const Driver &D = getToolChain().getDriver();
-    if (ABIVLenStr.getAsInteger(10, ABIVLen) || ABIVLen < 32 ||
-        ABIVLen > 65536 || !llvm::isPowerOf2_64(ABIVLen)) {
-      D.Diag(diag::err_drv_invalid_value)
-          << A->getOption().getName() << ABIVLenStr;
-      return;
-    }
-
-    CmdArgs.push_back(
-        Args.MakeArgString(Twine("-mriscv-abi-vlen=") + A->getValue()));
-  }
 }
 
 void Clang::AddSparcTargetArgs(const ArgList &Args,
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f6f7cbb278f5d5..88e47fd5f82499 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8107,9 +8107,9 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   Attr *CCAttr = getCCTypeAttr(S.Context, attr);
 
   if (attr.getKind() == ParsedAttr::AT_RISCVVLSCC) {
-    // If the riscv_abi_vlen doesn't have any argument, we set set it to 2 to
-    // differentiate from functions without attribute.
-    unsigned ABIVLen = 2;
+    // If the riscv_abi_vlen doesn't have any argument, we set set it to default
+    // value 128.
+    unsigned ABIVLen = 128;
     if (attr.getNumArgs() &&
         !S.checkUInt32Argument(attr, attr.getArgAsExpr(0), ABIVLen))
       return false;
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 0b06bede29dc76..3cb1fa0407d8a8 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -5,12 +5,6 @@
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ZVE32X %s
 // RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
-// RUN: %clang_cc1 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
-// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
-// RUN: %clang_cc1 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +zve32x \
-// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN-ZVE32X %s
-// RUN: %clang_cc1 -std=c23 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
-// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
 
 #include <riscv_vector.h>
 
@@ -42,45 +36,34 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 }
 
 // CHECK-LLVM: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 2 x i16> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 2 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
 // CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
 // CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index 0b91f8b3877eb2..4265e129c2fdb8 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -3,10 +3,6 @@
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
 // RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +zve32x \
 // RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ZVE32X %s
-// RUN: %clang_cc1 -std=c++11 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +v \
-// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN %s
-// RUN: %clang_cc1 -std=c++11 -triple riscv64 -mriscv-abi-vlen=256 -target-feature +zve32x \
-// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ABI-VLEN-ZVE32X %s
 
 #include <riscv_vector.h>
 
@@ -38,25 +34,19 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 }
 
 // CHECK-LLVM: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 4 x i16> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 2 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
 // CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN-ZVE32X: define dso_local riscv_vls_cc void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
-// CHECK-LLVM-ABI-VLEN: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {}

>From 9d1f138f14291d9040d5e41d6a8917ed7fa0b099 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Sun, 5 Jan 2025 22:25:17 -0800
Subject: [PATCH 06/10] fixup! handle struct and minor fixup

---
 clang/lib/CodeGen/CGCall.cpp                  |  11 ++
 clang/lib/CodeGen/Targets/RISCV.cpp           | 160 +++++++++++++++++-
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 108 ++++++++++++
 .../riscv-vector-callingconv-llvm-ir.cpp      | 108 ++++++++++++
 4 files changed, 384 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 9e143c26fb47ec..e2364cf3b303c8 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -3240,6 +3240,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
         }
       }
 
+      // Struct of fixed-length vectors and struct of array of fixed-length
+      // vector in VLS calling convention are coerced to vector tuple
+      // type(represented as TargetExtType) and scalable vector type
+      // respectively, they're no longer handled as struct.
+      if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
+          (isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
+           isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
+        ArgVals.push_back(ParamValue::forDirect(AI));
+        break;
+      }
+
       llvm::StructType *STy =
           dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
       Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index cff3f3c87214d7..80e09ec6c455fe 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -35,6 +35,9 @@ class RISCVABIInfo : public DefaultABIInfo {
                                       llvm::Type *&Field2Ty,
                                       CharUnits &Field2Off) const;
 
+  bool detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
+                                 llvm::Type *&VLSType) const;
+
 public:
   RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
                bool EABI)
@@ -361,6 +364,149 @@ ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
   return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType);
 }
 
+bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
+                                             llvm::Type *&VLSType) const {
+  // No riscv_vls_cc attribute.
+  if (ABIVLen == 1)
+    return false;
+
+  // Legal struct for VLS calling convention should fulfill following rules:
+  // 1. Struct element should be either "homogeneous fixed-length vectors" or "a
+  //    fixed-length vector array".
+  // 2. Number of struct elements or array elements should be power of 2.
+  // 3. Total number of vector registers needed should not exceed 8.
+  //
+  // Examples: Assume ABI_VLEN = 128.
+  // These are legal structs:
+  //   a. Structs with 1, 2, 4 or 8 "same" fixed-length vectors, e.g.
+  //   struct {
+  //     __attribute__((vector_size(16))) int a;
+  //     __attribute__((vector_size(16))) int b;
+  //   }
+  //
+  //   b. Structs with "single" fixed-length vector array with lengh 1, 2, 4
+  //   or 8, e.g.
+  //   struct {
+  //     __attribute__((vector_size(16))) int a[2];
+  //   }
+  // These are illegal structs:
+  //   a. Structs with 3 fixed-length vectors, e.g.
+  //   struct {
+  //     __attribute__((vector_size(16))) int a;
+  //     __attribute__((vector_size(16))) int b;
+  //     __attribute__((vector_size(16))) int c;
+  //   }
+  //
+  //   b. Structs with "multiple" fixed-length vector array, e.g.
+  //   struct {
+  //     __attribute__((vector_size(16))) int a[2];
+  //     __attribute__((vector_size(16))) int b[2];
+  //   }
+  //
+  //   c. Vector registers needed exceeds 8, e.g.
+  //   struct {
+  //     // Registers needed for single fixed-length element:
+  //     // 64 * 8 / ABI_VLEN = 4
+  //     __attribute__((vector_size(64))) int a;
+  //     __attribute__((vector_size(64))) int b;
+  //     __attribute__((vector_size(64))) int c;
+  //     __attribute__((vector_size(64))) int d;
+  //   }
+  //
+  // Struct of 1 fixed-length vector is passed as a scalable vector.
+  // Struct of >1 fixed-length vectors are passed as vector tuple.
+  // Struct of 1 array of fixed-length vectors is passed as a scalable vector.
+  // Otherwise, pass the struct indirectly.
+
+  if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty))) {
+    int NumElts = STy->getStructNumElements();
+    if (NumElts > 8 || !llvm::isPowerOf2_32(NumElts))
+      return false;
+
+    auto *FirstEltTy = STy->getElementType(0);
+    if (!STy->containsHomogeneousTypes())
+      return false;
+
+    // Check structure of fixed-length vectors and turn them into vector tuple
+    // type if legal.
+    if (auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy)) {
+      if (NumElts == 1) {
+        // Handle single fixed-length vector.
+        VLSType = llvm::ScalableVectorType::get(
+            FixedVecTy->getElementType(),
+            llvm::divideCeil(FixedVecTy->getNumElements() *
+                                 llvm::RISCV::RVVBitsPerBlock,
+                             ABIVLen));
+        // Check registers needed <= 8.
+        return llvm::divideCeil(
+                   FixedVecTy->getNumElements() *
+                       FixedVecTy->getElementType()->getScalarSizeInBits(),
+                   ABIVLen) <= 8;
+      }
+      // LMUL
+      // = fixed-length vector size / ABIVLen
+      // = 8 * I8EltCount / RVVBitsPerBlock
+      // =>
+      // I8EltCount
+      // = (fixed-length vector size * RVVBitsPerBlock) / (ABIVLen * 8)
+      unsigned I8EltCount = llvm::divideCeil(
+          FixedVecTy->getNumElements() *
+              FixedVecTy->getElementType()->getScalarSizeInBits() *
+              llvm::RISCV::RVVBitsPerBlock,
+          ABIVLen * 8);
+      VLSType = llvm::TargetExtType::get(
+          getVMContext(), "riscv.vector.tuple",
+          llvm::ScalableVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
+                                        I8EltCount),
+          NumElts);
+      // Check registers needed <= 8.
+      return NumElts *
+                 llvm::divideCeil(
+                     FixedVecTy->getNumElements() *
+                         FixedVecTy->getElementType()->getScalarSizeInBits(),
+                     ABIVLen) <=
+             8;
+    }
+
+    // If elements are not fixed-length vectors, it should be an array.
+    if (NumElts != 1)
+      return false;
+
+    // Check array of fixed-length vector and turn it into scalable vector type
+    // if legal.
+    if (auto *ArrTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
+      int NumArrElt = ArrTy->getNumElements();
+      if (NumArrElt > 8 || !llvm::isPowerOf2_32(NumArrElt))
+        return false;
+
+      auto *ArrEltTy = dyn_cast<llvm::FixedVectorType>(ArrTy->getElementType());
+      if (!ArrEltTy)
+        return false;
+
+      // LMUL
+      // = NumArrElt * fixed-length vector size / ABIVLen
+      // = fixed-length vector elt size * ScalVecNumElts / RVVBitsPerBlock
+      // =>
+      // ScalVecNumElts
+      // = (NumArrElt * fixed-length vector size * RVVBitsPerBlock) /
+      //   (ABIVLen * fixed-length vector elt size)
+      // = NumArrElt * num fixed-length vector elt * RVVBitsPerBlock /
+      //   ABIVLen
+      unsigned ScalVecNumElts = llvm::divideCeil(
+          NumArrElt * ArrEltTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
+          ABIVLen);
+      VLSType = llvm::ScalableVectorType::get(ArrEltTy->getElementType(),
+                                              ScalVecNumElts);
+      // Check registers needed <= 8.
+      return llvm::divideCeil(
+                 ScalVecNumElts *
+                     ArrEltTy->getElementType()->getScalarSizeInBits(),
+                 llvm::RISCV::RVVBitsPerBlock) <= 8;
+    }
+  }
+  return false;
+}
+
 // Fixed-length RVV vectors are represented as scalable vectors in function
 // args/return and must be coerced from fixed vectors.
 ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
@@ -410,11 +556,13 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
         (EltType->isBFloatTy() && !TI.hasFeature("zvfbfmin")) ||
         (EltType->isFloatTy() && !TI.hasFeature("zve32f")) ||
         (EltType->isDoubleTy() && !TI.hasFeature("zve64d")) ||
-        (EltType->isIntegerTy(64) && !TI.hasFeature("zve64x")) ||
-        EltType->isIntegerTy(128)) {
+        EltType->isIntegerTy(128))
       EltType =
           llvm::Type::getIntNTy(getVMContext(), EltType->getScalarSizeInBits());
-    }
+
+    // Check registers needed <= 8.
+    if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
+      return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
 
     // Generic vector
     // The number of elements needs to be at least 1.
@@ -485,6 +633,12 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
     }
   }
 
+  if (IsFixed && Ty->isStructureOrClassType()) {
+    llvm::Type *VLSType = nullptr;
+    if (detectVLSCCEligibleStruct(Ty, ABIVLen, VLSType))
+      return ABIArgInfo::getDirect(VLSType);
+  }
+
   uint64_t NeededAlign = getContext().getTypeAlign(Ty);
   // Determine the number of GPRs needed to pass the current argument
   // according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 3cb1fa0407d8a8..78e1ed37727894 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -67,3 +67,111 @@ void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((v
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}
+
+
+struct st_i32x4{
+    __attribute__((vector_size(16))) int i32;
+};
+
+struct st_i32x4_arr1{
+    __attribute__((vector_size(16))) int i32[1];
+};
+
+struct st_i32x4_arr4{
+    __attribute__((vector_size(16))) int i32[4];
+};
+
+struct st_i32x4_arr8{
+    __attribute__((vector_size(16))) int i32[8];
+};
+
+
+struct st_i32x4x2{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+};
+
+struct st_i32x8x2{
+    __attribute__((vector_size(32))) int i32_1;
+    __attribute__((vector_size(32))) int i32_2;
+};
+
+struct st_i32x64x2{
+    __attribute__((vector_size(256))) int i32_1;
+    __attribute__((vector_size(256))) int i32_2;
+};
+
+struct st_i32x4x8{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+    __attribute__((vector_size(16))) int i32_4;
+    __attribute__((vector_size(16))) int i32_5;
+    __attribute__((vector_size(16))) int i32_6;
+    __attribute__((vector_size(16))) int i32_7;
+    __attribute__((vector_size(16))) int i32_8;
+};
+
+struct st_i32x4x9{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+    __attribute__((vector_size(16))) int i32_4;
+    __attribute__((vector_size(16))) int i32_5;
+    __attribute__((vector_size(16))) int i32_6;
+    __attribute__((vector_size(16))) int i32_7;
+    __attribute__((vector_size(16))) int i32_8;
+    __attribute__((vector_size(16))) int i32_9;
+};
+
+typedef int __attribute__((vector_size(256))) int32x64_t;
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_too_large(ptr noundef %0)
+void __attribute__((riscv_vls_cc)) test_too_large(int32x64_t arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_too_large_256(<vscale x 16 x i32> noundef %arg.coerce)
+void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4(<vscale x 2 x i32> %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_256(<vscale x 1 x i32> %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr1(<vscale x 2 x i32> %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr1_256(<vscale x 1 x i32> %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr4(<vscale x 8 x i32> %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr4_256(<vscale x 4 x i32> %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr8(<vscale x 16 x i32> %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr8_256(<vscale x 8 x i32> %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x2_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x8x2_256(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x64x2(ptr noundef %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x64x2(struct st_i32x64x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x64x2_256(ptr noundef %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struct st_i32x4x8 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4x8_256(struct st_i32x4x8 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x9(ptr noundef %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4x9(struct st_i32x4x9 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x9_256(ptr noundef %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4x9_256(struct st_i32x4x9 arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index 4265e129c2fdb8..6281b640c4df06 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -50,3 +50,111 @@ void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
 // CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
+
+
+struct st_i32x4{
+    __attribute__((vector_size(16))) int i32;
+};
+
+struct st_i32x4_arr1{
+    __attribute__((vector_size(16))) int i32[1];
+};
+
+struct st_i32x4_arr4{
+    __attribute__((vector_size(16))) int i32[4];
+};
+
+struct st_i32x4_arr8{
+    __attribute__((vector_size(16))) int i32[8];
+};
+
+
+struct st_i32x4x2{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+};
+
+struct st_i32x8x2{
+    __attribute__((vector_size(32))) int i32_1;
+    __attribute__((vector_size(32))) int i32_2;
+};
+
+struct st_i32x64x2{
+    __attribute__((vector_size(256))) int i32_1;
+    __attribute__((vector_size(256))) int i32_2;
+};
+
+struct st_i32x4x8{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+    __attribute__((vector_size(16))) int i32_4;
+    __attribute__((vector_size(16))) int i32_5;
+    __attribute__((vector_size(16))) int i32_6;
+    __attribute__((vector_size(16))) int i32_7;
+    __attribute__((vector_size(16))) int i32_8;
+};
+
+struct st_i32x4x9{
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+    __attribute__((vector_size(16))) int i32_4;
+    __attribute__((vector_size(16))) int i32_5;
+    __attribute__((vector_size(16))) int i32_6;
+    __attribute__((vector_size(16))) int i32_7;
+    __attribute__((vector_size(16))) int i32_8;
+    __attribute__((vector_size(16))) int i32_9;
+};
+
+typedef int __attribute__((vector_size(256))) int32x64_t;
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z14test_too_largeDv64_i(ptr noundef %0)
+[[riscv::vls_cc]] void test_too_large(int32x64_t arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_too_large_256Dv64_i(<vscale x 16 x i32> noundef %arg.coerce)
+[[riscv::vls_cc(256)]] void test_too_large_256(int32x64_t arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z13test_st_i32x48st_i32x4(<vscale x 2 x i32> %arg)
+[[riscv::vls_cc]] void test_st_i32x4(struct st_i32x4 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z17test_st_i32x4_2568st_i32x4(<vscale x 1 x i32> %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4_256(struct st_i32x4 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr113st_i32x4_arr1(<vscale x 2 x i32> %arg)
+[[riscv::vls_cc]] void test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr1_25613st_i32x4_arr1(<vscale x 1 x i32> %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr413st_i32x4_arr4(<vscale x 8 x i32> %arg)
+[[riscv::vls_cc]] void test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr4_25613st_i32x4_arr4(<vscale x 4 x i32> %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr813st_i32x4_arr8(<vscale x 16 x i32> %arg)
+[[riscv::vls_cc]] void test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr8_25613st_i32x4_arr8(<vscale x 8 x i32> %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x210st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+[[riscv::vls_cc]] void test_st_i32x4x2(struct st_i32x4x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x2_25610st_i32x4x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4x2_256(struct st_i32x4x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x8x210st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
+[[riscv::vls_cc]] void test_st_i32x8x2(struct st_i32x8x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x8x2_25610st_i32x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x8x2_256(struct st_i32x8x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z16test_st_i32x64x211st_i32x64x2(ptr noundef %arg)
+[[riscv::vls_cc]] void test_st_i32x64x2(struct st_i32x64x2 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
+[[riscv::vls_cc]] void test_st_i32x4x8(struct st_i32x4x8 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4x8_256(struct st_i32x4x8 arg) {}
+
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x910st_i32x4x9(ptr noundef %arg)
+[[riscv::vls_cc]] void test_st_i32x4x9(struct st_i32x4x9 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr noundef %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4x9_256(struct st_i32x4x9 arg) {}

>From 22a5b0e03e561cfabf3d6be605afe6f04aab3c61 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Tue, 14 Jan 2025 02:31:59 -0800
Subject: [PATCH 07/10] fixup! Add all 32-65536 calling conventions and remove
 log2ABIVLen

---
 clang/include/clang-c/Index.h                 |  13 +-
 clang/include/clang/AST/Type.h                |  44 +++----
 clang/include/clang/AST/TypeProperties.td     |   7 +-
 clang/include/clang/Basic/Specifiers.h        |  62 +++++----
 clang/include/clang/CodeGen/CGFunctionInfo.h  |   9 +-
 clang/lib/AST/ASTContext.cpp                  |   2 -
 clang/lib/AST/ItaniumMangle.cpp               |  15 ++-
 clang/lib/AST/Type.cpp                        |  16 ++-
 clang/lib/AST/TypePrinter.cpp                 |  20 ++-
 clang/lib/Basic/Targets/RISCV.cpp             |  13 +-
 clang/lib/CodeGen/CGCall.cpp                  |  42 ++++++-
 clang/lib/CodeGen/CGDebugInfo.cpp             |  17 ++-
 clang/lib/CodeGen/Targets/RISCV.cpp           |  43 ++++++-
 clang/lib/Sema/SemaDeclAttr.cpp               |  25 +++-
 clang/lib/Sema/SemaType.cpp                   |  38 +++---
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  |  60 ++++-----
 .../riscv-vector-callingconv-llvm-ir.cpp      |  50 ++++----
 .../CodeGen/RISCV/riscv-vector-callingconv.c  |  12 +-
 .../RISCV/riscv-vector-callingconv.cpp        |   6 +-
 clang/tools/libclang/CXType.cpp               |  13 +-
 llvm/include/llvm/IR/CallingConv.h            |  13 +-
 llvm/lib/AsmParser/LLParser.cpp               |  30 ++++-
 llvm/lib/IR/AsmWriter.cpp                     |  18 ++-
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  15 ++-
 llvm/test/Assembler/riscv_vls_cc.ll           | 118 +++++++++++++++++-
 llvm/test/Bitcode/compatibility.ll            |  50 +++++++-
 26 files changed, 564 insertions(+), 187 deletions(-)

diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 21a4863203b6ec..dfcd493470075e 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3053,7 +3053,18 @@ enum CXCallingConv {
   CXCallingConv_M68kRTD = 19,
   CXCallingConv_PreserveNone = 20,
   CXCallingConv_RISCVVectorCall = 21,
-  CXCallingConv_RISCVVLSCall = 22,
+  CXCallingConv_RISCVVLSCall_32 = 22,
+  CXCallingConv_RISCVVLSCall_64 = 23,
+  CXCallingConv_RISCVVLSCall_128 = 24,
+  CXCallingConv_RISCVVLSCall_256 = 25,
+  CXCallingConv_RISCVVLSCall_512 = 26,
+  CXCallingConv_RISCVVLSCall_1024 = 27,
+  CXCallingConv_RISCVVLSCall_2048 = 28,
+  CXCallingConv_RISCVVLSCall_4096 = 29,
+  CXCallingConv_RISCVVLSCall_8192 = 30,
+  CXCallingConv_RISCVVLSCall_16384 = 31,
+  CXCallingConv_RISCVVLSCall_32768 = 32,
+  CXCallingConv_RISCVVLSCall_65536 = 33,
 
   CXCallingConv_Invalid = 100,
   CXCallingConv_Unexposed = 200
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index ccdcbfe14ff24b..1568ee4c8f8dcc 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1946,7 +1946,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
     /// Extra information which affects how the function is called, like
     /// regparm and the calling convention.
     LLVM_PREFERRED_TYPE(CallingConv)
-    unsigned ExtInfo : 18;
+    unsigned ExtInfo : 14;
 
     /// The ref-qualifier associated with a \c FunctionProtoType.
     ///
@@ -4437,40 +4437,36 @@ class FunctionType : public Type {
     // Type::FunctionTypeBitfields::ExtInfo as well.
 
     // |  CC  |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
-    // |0 .. 4|   5    |    6   |       7         |8 .. 10|    11   |    12    |
-    // |RISCV-ABI-VLEN|
-    // |13    ..    17|
+    // |0 .. 5|   6    |    7   |       8         |9 .. 11|    12   |    13    |
     //
     // regparm is either 0 (no regparm attribute) or the regparm value+1.
-    enum { CallConvMask = 0x1F };
-    enum { NoReturnMask = 0x20 };
-    enum { ProducesResultMask = 0x40 };
-    enum { NoCallerSavedRegsMask = 0x80 };
+    enum { CallConvMask = 0x3F };
+    enum { NoReturnMask = 0x40 };
+    enum { ProducesResultMask = 0x80 };
+    enum { NoCallerSavedRegsMask = 0x100 };
     enum {
-      RegParmMask =  0x700,
-      RegParmOffset = 8
+      RegParmMask =  0xe00,
+      RegParmOffset = 9
     };
-    enum { NoCfCheckMask = 0x800 };
-    enum { CmseNSCallMask = 0x1000 };
-    enum { Log2RISCVABIVLenMask = 0x3E000, Log2RISCVABIVLenOffset = 13 };
-    uint32_t Bits = CC_C;
+    enum { NoCfCheckMask = 0x1000 };
+    enum { CmseNSCallMask = 0x2000 };
+    uint16_t Bits = CC_C;
 
-    ExtInfo(unsigned Bits) : Bits(static_cast<uint32_t>(Bits)) {}
+    ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
 
   public:
     // Constructor with no defaults. Use this when you know that you
     // have all the elements (when reading an AST file for example).
     ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
             bool producesResult, bool noCallerSavedRegs, bool NoCfCheck,
-            bool cmseNSCall, unsigned Log2RISCVABIVLen) {
+            bool cmseNSCall) {
       assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
       Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
              (producesResult ? ProducesResultMask : 0) |
              (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
              (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
              (NoCfCheck ? NoCfCheckMask : 0) |
-             (cmseNSCall ? CmseNSCallMask : 0) |
-             (Log2RISCVABIVLen << Log2RISCVABIVLenOffset);
+             (cmseNSCall ? CmseNSCallMask : 0);
     }
 
     // Constructor with all defaults. Use when for example creating a
@@ -4497,10 +4493,6 @@ class FunctionType : public Type {
 
     CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
 
-    unsigned getLog2RISCVABIVLen() const {
-      return (Bits & Log2RISCVABIVLenMask) >> Log2RISCVABIVLenOffset;
-    }
-
     bool operator==(ExtInfo Other) const {
       return Bits == Other.Bits;
     }
@@ -4556,11 +4548,6 @@ class FunctionType : public Type {
       return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
     }
 
-    ExtInfo withLog2RISCVABIVLen(unsigned Log2RISCVABIVLen) const {
-      return ExtInfo((Bits & ~Log2RISCVABIVLenMask) |
-                     (Log2RISCVABIVLen << Log2RISCVABIVLenOffset));
-    }
-
     void Profile(llvm::FoldingSetNodeID &ID) const {
       ID.AddInteger(Bits);
     }
@@ -4670,9 +4657,6 @@ class FunctionType : public Type {
 
   bool getCmseNSCallAttr() const { return getExtInfo().getCmseNSCall(); }
   CallingConv getCallConv() const { return getExtInfo().getCC(); }
-  unsigned getLog2RISCVABIVLen() const {
-    return getExtInfo().getLog2RISCVABIVLen();
-  }
   ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
 
   static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index d5f653013a9b8b..6f1a76bd18fb50 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -313,9 +313,6 @@ let Class = FunctionType in {
   def : Property<"cmseNSCall", Bool> {
     let Read = [{ node->getExtInfo().getCmseNSCall() }];
   }
-  def : Property<"Log2RISCVABIVLen", UInt32> {
-    let Read = [{ node->getExtInfo().getLog2RISCVABIVLen() }];
-  }
 }
 
 let Class = FunctionNoProtoType in {
@@ -323,7 +320,7 @@ let Class = FunctionNoProtoType in {
     auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
                                          callingConvention, producesResult,
                                          noCallerSavedRegs, noCfCheck,
-                                         cmseNSCall, Log2RISCVABIVLen);
+                                         cmseNSCall);
     return ctx.getFunctionNoProtoType(returnType, extInfo);
   }]>;
 }
@@ -366,7 +363,7 @@ let Class = FunctionProtoType in {
     auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
                                          callingConvention, producesResult,
                                          noCallerSavedRegs, noCfCheck,
-                                         cmseNSCall, Log2RISCVABIVLen);
+                                         cmseNSCall);
     FunctionProtoType::ExtProtoInfo epi;
     epi.ExtInfo = extInfo;
     epi.Variadic = variadic;
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index d2df5a24da143e..491badcc804e77 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -276,31 +276,43 @@ namespace clang {
 
   /// CallingConv - Specifies the calling convention that a function uses.
   enum CallingConv {
-    CC_C,                 // __attribute__((cdecl))
-    CC_X86StdCall,        // __attribute__((stdcall))
-    CC_X86FastCall,       // __attribute__((fastcall))
-    CC_X86ThisCall,       // __attribute__((thiscall))
-    CC_X86VectorCall,     // __attribute__((vectorcall))
-    CC_X86Pascal,         // __attribute__((pascal))
-    CC_Win64,             // __attribute__((ms_abi))
-    CC_X86_64SysV,        // __attribute__((sysv_abi))
-    CC_X86RegCall,        // __attribute__((regcall))
-    CC_AAPCS,             // __attribute__((pcs("aapcs")))
-    CC_AAPCS_VFP,         // __attribute__((pcs("aapcs-vfp")))
-    CC_IntelOclBicc,      // __attribute__((intel_ocl_bicc))
-    CC_SpirFunction,      // default for OpenCL functions on SPIR target
-    CC_OpenCLKernel,      // inferred for OpenCL kernels
-    CC_Swift,             // __attribute__((swiftcall))
-    CC_SwiftAsync,        // __attribute__((swiftasynccall))
-    CC_PreserveMost,      // __attribute__((preserve_most))
-    CC_PreserveAll,       // __attribute__((preserve_all))
-    CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
-    CC_AArch64SVEPCS,     // __attribute__((aarch64_sve_pcs))
-    CC_AMDGPUKernelCall,  // __attribute__((amdgpu_kernel))
-    CC_M68kRTD,           // __attribute__((m68k_rtd))
-    CC_PreserveNone,      // __attribute__((preserve_none))
-    CC_RISCVVectorCall,   // __attribute__((riscv_vector_cc))
-    CC_RISCVVLSCall,      // __attribute__((riscv_vls_cc))
+    CC_C,                  // __attribute__((cdecl))
+    CC_X86StdCall,         // __attribute__((stdcall))
+    CC_X86FastCall,        // __attribute__((fastcall))
+    CC_X86ThisCall,        // __attribute__((thiscall))
+    CC_X86VectorCall,      // __attribute__((vectorcall))
+    CC_X86Pascal,          // __attribute__((pascal))
+    CC_Win64,              // __attribute__((ms_abi))
+    CC_X86_64SysV,         // __attribute__((sysv_abi))
+    CC_X86RegCall,         // __attribute__((regcall))
+    CC_AAPCS,              // __attribute__((pcs("aapcs")))
+    CC_AAPCS_VFP,          // __attribute__((pcs("aapcs-vfp")))
+    CC_IntelOclBicc,       // __attribute__((intel_ocl_bicc))
+    CC_SpirFunction,       // default for OpenCL functions on SPIR target
+    CC_OpenCLKernel,       // inferred for OpenCL kernels
+    CC_Swift,              // __attribute__((swiftcall))
+    CC_SwiftAsync,         // __attribute__((swiftasynccall))
+    CC_PreserveMost,       // __attribute__((preserve_most))
+    CC_PreserveAll,        // __attribute__((preserve_all))
+    CC_AArch64VectorCall,  // __attribute__((aarch64_vector_pcs))
+    CC_AArch64SVEPCS,      // __attribute__((aarch64_sve_pcs))
+    CC_AMDGPUKernelCall,   // __attribute__((amdgpu_kernel))
+    CC_M68kRTD,            // __attribute__((m68k_rtd))
+    CC_PreserveNone,       // __attribute__((preserve_none))
+    CC_RISCVVectorCall,    // __attribute__((riscv_vector_cc))
+    CC_RISCVVLSCall_32,    // __attribute__((riscv_vls_cc(32)))
+    CC_RISCVVLSCall_64,    // __attribute__((riscv_vls_cc(64)))
+    CC_RISCVVLSCall_128,   // __attribute__((riscv_vls_cc)) or
+                           // __attribute__((riscv_vls_cc(128)))
+    CC_RISCVVLSCall_256,   // __attribute__((riscv_vls_cc(256)))
+    CC_RISCVVLSCall_512,   // __attribute__((riscv_vls_cc(512)))
+    CC_RISCVVLSCall_1024,  // __attribute__((riscv_vls_cc(1024)))
+    CC_RISCVVLSCall_2048,  // __attribute__((riscv_vls_cc(2048)))
+    CC_RISCVVLSCall_4096,  // __attribute__((riscv_vls_cc(4096)))
+    CC_RISCVVLSCall_8192,  // __attribute__((riscv_vls_cc(8192)))
+    CC_RISCVVLSCall_16384, // __attribute__((riscv_vls_cc(16384)))
+    CC_RISCVVLSCall_32768, // __attribute__((riscv_vls_cc(32768)))
+    CC_RISCVVLSCall_65536, // __attribute__((riscv_vls_cc(65536)))
   };
 
   /// Checks whether the given calling convention supports variadic
diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 44ae2755a2ab04..9d785d878b61dc 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -625,9 +625,6 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
-  /// Log2 of ABI_VLEN used in RISCV VLS calling convention.
-  unsigned Log2RISCVABIVLen : 5;
-
   RequiredArgs Required;
 
   /// The struct representing all arguments passed in memory.  Only used when
@@ -738,13 +735,11 @@ class CGFunctionInfo final
   bool getHasRegParm() const { return HasRegParm; }
   unsigned getRegParm() const { return RegParm; }
 
-  unsigned getLog2RISCVABIVLen() const { return Log2RISCVABIVLen; }
-
   FunctionType::ExtInfo getExtInfo() const {
     return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
                                  getASTCallingConvention(), isReturnsRetained(),
                                  isNoCallerSavedRegs(), isNoCfCheck(),
-                                 isCmseNSCall(), getLog2RISCVABIVLen());
+                                 isCmseNSCall());
   }
 
   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -798,7 +793,6 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
-    ID.AddInteger(Log2RISCVABIVLen);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -826,7 +820,6 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
-    ID.AddInteger(info.getLog2RISCVABIVLen());
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7d043068fa095c..be1dd29d462788 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11108,8 +11108,6 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
     return {};
   if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
     return {};
-  if (lbaseInfo.getLog2RISCVABIVLen() != rbaseInfo.getLog2RISCVABIVLen())
-    return {};
 
   // When merging declarations, it's common for supplemental information like
   // attributes to only be present in one of the declarations, and we generally
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index a63556c647af42..a6ec9925a6fc20 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3489,7 +3489,20 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
   case CC_M68kRTD:
   case CC_PreserveNone:
   case CC_RISCVVectorCall:
-  case CC_RISCVVLSCall:
+#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
+    CC_VLS_CASE(32)
+    CC_VLS_CASE(64)
+    CC_VLS_CASE(128)
+    CC_VLS_CASE(256)
+    CC_VLS_CASE(512)
+    CC_VLS_CASE(1024)
+    CC_VLS_CASE(2048)
+    CC_VLS_CASE(4096)
+    CC_VLS_CASE(8192)
+    CC_VLS_CASE(16384)
+    CC_VLS_CASE(32768)
+    CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
     // FIXME: we should be mangling all of the above.
     return "";
 
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 3472972f6f1065..ff7ea5d97b83b2 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3561,7 +3561,21 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   case CC_PreserveNone: return "preserve_none";
     // clang-format off
   case CC_RISCVVectorCall: return "riscv_vector_cc";
-  case CC_RISCVVLSCall: return "riscv_vls_cc";
+#define CC_VLS_CASE(ABI_VLEN) \
+  case CC_RISCVVLSCall_##ABI_VLEN: return "riscv_vls_cc(" #ABI_VLEN ")";
+  CC_VLS_CASE(32)
+  CC_VLS_CASE(64)
+  CC_VLS_CASE(128)
+  CC_VLS_CASE(256)
+  CC_VLS_CASE(512)
+  CC_VLS_CASE(1024)
+  CC_VLS_CASE(2048)
+  CC_VLS_CASE(4096)
+  CC_VLS_CASE(8192)
+  CC_VLS_CASE(16384)
+  CC_VLS_CASE(32768)
+  CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
     // clang-format on
   }
 
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 65d3b3108175d2..ca62112e22c61a 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1136,9 +1136,23 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
     case CC_RISCVVectorCall:
       OS << "__attribute__((riscv_vector_cc))";
       break;
-    case CC_RISCVVLSCall:
-      OS << "__attribute__((riscv_vls_cc))";
-      break;
+#define CC_VLS_CASE(ABI_VLEN)                                                  \
+  case CC_RISCVVLSCall_##ABI_VLEN:                                             \
+    OS << "__attribute__((riscv_vls_cc" #ABI_VLEN "))";                        \
+    break;
+      CC_VLS_CASE(32)
+      CC_VLS_CASE(64)
+      CC_VLS_CASE(128)
+      CC_VLS_CASE(256)
+      CC_VLS_CASE(512)
+      CC_VLS_CASE(1024)
+      CC_VLS_CASE(2048)
+      CC_VLS_CASE(4096)
+      CC_VLS_CASE(8192)
+      CC_VLS_CASE(16384)
+      CC_VLS_CASE(32768)
+      CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
     }
   }
 
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index ebced9da22e8c0..d7fa44f5cf4005 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -516,7 +516,18 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
     return CCCR_Warning;
   case CC_C:
   case CC_RISCVVectorCall:
-  case CC_RISCVVLSCall:
+  case CC_RISCVVLSCall_32:
+  case CC_RISCVVLSCall_64:
+  case CC_RISCVVLSCall_128:
+  case CC_RISCVVLSCall_256:
+  case CC_RISCVVLSCall_512:
+  case CC_RISCVVLSCall_1024:
+  case CC_RISCVVLSCall_2048:
+  case CC_RISCVVLSCall_4096:
+  case CC_RISCVVLSCall_8192:
+  case CC_RISCVVLSCall_16384:
+  case CC_RISCVVLSCall_32768:
+  case CC_RISCVVLSCall_65536:
     return CCCR_OK;
   }
 }
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index e2364cf3b303c8..1564b2cdcdf3ab 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -76,8 +76,23 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
     // clang-format off
   case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
-  case CC_RISCVVLSCall: return llvm::CallingConv::RISCV_VLSCall;
     // clang-format on
+#define CC_VLS_CASE(ABI_VLEN)                                                  \
+  case CC_RISCVVLSCall_##ABI_VLEN:                                             \
+    return llvm::CallingConv::RISCV_VLSCall_##ABI_VLEN;
+    CC_VLS_CASE(32)
+    CC_VLS_CASE(64)
+    CC_VLS_CASE(128)
+    CC_VLS_CASE(256)
+    CC_VLS_CASE(512)
+    CC_VLS_CASE(1024)
+    CC_VLS_CASE(2048)
+    CC_VLS_CASE(4096)
+    CC_VLS_CASE(8192)
+    CC_VLS_CASE(16384)
+    CC_VLS_CASE(32768)
+    CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
   }
 }
 
@@ -267,8 +282,28 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
   if (D->hasAttr<RISCVVectorCCAttr>())
     return CC_RISCVVectorCall;
 
-  if (D->hasAttr<RISCVVLSCCAttr>())
-    return CC_RISCVVLSCall;
+  if (RISCVVLSCCAttr *PCS = D->getAttr<RISCVVLSCCAttr>()) {
+    switch (PCS->getVectorWidth()) {
+    default:
+      llvm_unreachable("Invalid RISC-V VLS ABI VLEN");
+#define CC_VLS_CASE(ABI_VLEN)                                                  \
+  case ABI_VLEN:                                                               \
+    return CC_RISCVVLSCall_##ABI_VLEN;
+      CC_VLS_CASE(32)
+      CC_VLS_CASE(64)
+      CC_VLS_CASE(128)
+      CC_VLS_CASE(256)
+      CC_VLS_CASE(512)
+      CC_VLS_CASE(1024)
+      CC_VLS_CASE(2048)
+      CC_VLS_CASE(4096)
+      CC_VLS_CASE(8192)
+      CC_VLS_CASE(16384)
+      CC_VLS_CASE(32768)
+      CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
+    }
+  }
 
   return CC_C;
 }
@@ -865,7 +900,6 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
   FI->HasExtParameterInfos = !paramInfos.empty();
   FI->getArgsBuffer()[0].type = resultType;
   FI->MaxVectorWidth = 0;
-  FI->Log2RISCVABIVLen = info.getLog2RISCVABIVLen();
   for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
     FI->getArgsBuffer()[i + 1].type = argTypes[i];
   for (unsigned i = 0, e = paramInfos.size(); i != e; ++i)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 9d6fa7f98461b7..68bf847f868133 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1593,8 +1593,21 @@ static unsigned getDwarfCC(CallingConv CC) {
     return llvm::dwarf::DW_CC_LLVM_PreserveNone;
   case CC_RISCVVectorCall:
     return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
-  case CC_RISCVVLSCall:
-    return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
+#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
+    CC_VLS_CASE(32)
+    CC_VLS_CASE(64)
+    CC_VLS_CASE(128)
+    CC_VLS_CASE(256)
+    CC_VLS_CASE(512)
+    CC_VLS_CASE(1024)
+    CC_VLS_CASE(2048)
+    CC_VLS_CASE(4096)
+    CC_VLS_CASE(8192)
+    CC_VLS_CASE(16384)
+    CC_VLS_CASE(32768)
+    CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
+    return llvm::dwarf::DW_CC_LLVM_RISCVVLSCall;
   }
   return 0;
 }
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 80e09ec6c455fe..bbc23738074fcb 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -115,7 +115,48 @@ void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
 }
 
 void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  unsigned ABIVLen = 1 << FI.getExtInfo().getLog2RISCVABIVLen();
+  unsigned ABIVLen;
+  switch (FI.getExtInfo().getCC()) {
+  default:
+    ABIVLen = 1;
+    break;
+  case CallingConv::CC_RISCVVLSCall_32:
+    ABIVLen = 32;
+    break;
+  case CallingConv::CC_RISCVVLSCall_64:
+    ABIVLen = 64;
+    break;
+  case CallingConv::CC_RISCVVLSCall_128:
+    ABIVLen = 128;
+    break;
+  case CallingConv::CC_RISCVVLSCall_256:
+    ABIVLen = 256;
+    break;
+  case CallingConv::CC_RISCVVLSCall_512:
+    ABIVLen = 512;
+    break;
+  case CallingConv::CC_RISCVVLSCall_1024:
+    ABIVLen = 1024;
+    break;
+  case CallingConv::CC_RISCVVLSCall_2048:
+    ABIVLen = 2048;
+    break;
+  case CallingConv::CC_RISCVVLSCall_4096:
+    ABIVLen = 4096;
+    break;
+  case CallingConv::CC_RISCVVLSCall_8192:
+    ABIVLen = 8192;
+    break;
+  case CallingConv::CC_RISCVVLSCall_16384:
+    ABIVLen = 16384;
+    break;
+  case CallingConv::CC_RISCVVLSCall_32768:
+    ABIVLen = 32768;
+    break;
+  case CallingConv::CC_RISCVVLSCall_65536:
+    ABIVLen = 65536;
+    break;
+  }
   QualType RetTy = FI.getReturnType();
   if (!getCXXABI().classifyReturnType(FI))
     FI.getReturnInfo() = classifyReturnType(RetTy, ABIVLen);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 4645c47f85b597..e730f25201dcd8 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5248,9 +5248,30 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
   case ParsedAttr::AT_RISCVVectorCC:
     CC = CC_RISCVVectorCall;
     break;
-  case ParsedAttr::AT_RISCVVLSCC:
-    CC = CC_RISCVVLSCall;
+  case ParsedAttr::AT_RISCVVLSCC: {
+    // If the riscv_abi_vlen doesn't have any argument, we set set it to default
+    // value 128.
+    unsigned ABIVLen = 128;
+    if (Attrs.getNumArgs() &&
+        !checkUInt32Argument(Attrs, Attrs.getArgAsExpr(0), ABIVLen)) {
+    Attrs.setInvalid();
+      return true;
+    }
+    if (Attrs.getNumArgs() && (ABIVLen < 32 || ABIVLen > 65536)) {
+    Attrs.setInvalid();
+      Diag(Attrs.getLoc(), diag::err_argument_invalid_range)
+          << ABIVLen << 32 << 65536;
+      return true;
+    }
+    if (!llvm::isPowerOf2_64(ABIVLen)) {
+    Attrs.setInvalid();
+      Diag(Attrs.getLoc(), diag::err_argument_not_power_of_2);
+      return true;
+    }
+    CC = static_cast<CallingConv>(CallingConv::CC_RISCVVLSCall_32 +
+                                  llvm::Log2_64(ABIVLen) - 5);
     break;
+  }
   default: llvm_unreachable("unexpected attribute kind");
   }
 
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 88e47fd5f82499..04e024764c22cc 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7618,8 +7618,20 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
     return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr);
   case ParsedAttr::AT_RISCVVectorCC:
     return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr);
-  case ParsedAttr::AT_RISCVVLSCC:
-    return ::new (Ctx) RISCVVLSCCAttr(Ctx, Attr, /*dummy*/ 0);
+  case ParsedAttr::AT_RISCVVLSCC: {
+    // If the riscv_abi_vlen doesn't have any argument, we set set it to default
+    // value 128.
+    unsigned ABIVLen = 128;
+    if (Attr.getNumArgs()) {
+      std::optional<llvm::APSInt> MaybeABIVLen =
+          Attr.getArgAsExpr(0)->getIntegerConstantExpr(Ctx);
+      if (!MaybeABIVLen)
+        llvm_unreachable("Invalid RISC-V ABI VLEN");
+      ABIVLen = MaybeABIVLen->getZExtValue();
+    }
+
+    return ::new (Ctx) RISCVVLSCCAttr(Ctx, Attr, ABIVLen);
+  }
   }
   llvm_unreachable("unexpected attribute kind!");
 }
@@ -8106,28 +8118,6 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   CallingConv CCOld = fn->getCallConv();
   Attr *CCAttr = getCCTypeAttr(S.Context, attr);
 
-  if (attr.getKind() == ParsedAttr::AT_RISCVVLSCC) {
-    // If the riscv_abi_vlen doesn't have any argument, we set set it to default
-    // value 128.
-    unsigned ABIVLen = 128;
-    if (attr.getNumArgs() &&
-        !S.checkUInt32Argument(attr, attr.getArgAsExpr(0), ABIVLen))
-      return false;
-    if (attr.getNumArgs() && (ABIVLen < 32 || ABIVLen > 65536)) {
-      S.Diag(attr.getLoc(), diag::err_argument_invalid_range)
-          << ABIVLen << 32 << 65536;
-      return false;
-    }
-    if (!llvm::isPowerOf2_64(ABIVLen)) {
-      S.Diag(attr.getLoc(), diag::err_argument_not_power_of_2);
-      return false;
-    }
-
-    auto EI = unwrapped.get()->getExtInfo().withLog2RISCVABIVLen(
-        llvm::Log2_64(ABIVLen));
-    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
-  }
-
   if (CCOld != CC) {
     // Error out on when there's already an attribute on the type
     // and the CCs don't match.
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 78e1ed37727894..61300d62e1eb69 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -38,34 +38,34 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 // CHECK-LLVM: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
-// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
-// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}
 
 
@@ -126,52 +126,52 @@ struct st_i32x4x9{
 
 typedef int __attribute__((vector_size(256))) int32x64_t;
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_too_large(ptr noundef %0)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_too_large(ptr noundef %0)
 void __attribute__((riscv_vls_cc)) test_too_large(int32x64_t arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_too_large_256(<vscale x 16 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_too_large_256(<vscale x 16 x i32> noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4(<vscale x 2 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4(<vscale x 2 x i32> %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_256(<vscale x 1 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_256(<vscale x 1 x i32> %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr1(<vscale x 2 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr1(<vscale x 2 x i32> %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr1_256(<vscale x 1 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr1_256(<vscale x 1 x i32> %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr4(<vscale x 8 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr4(<vscale x 8 x i32> %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr4_256(<vscale x 4 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr4_256(<vscale x 4 x i32> %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr8(<vscale x 16 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr8(<vscale x 16 x i32> %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4_arr8_256(<vscale x 8 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr8_256(<vscale x 8 x i32> %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x2_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x2_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x8x2_256(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x8x2_256(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x64x2(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x64x2(ptr noundef %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x64x2(struct st_i32x64x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x64x2_256(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x64x2_256(ptr noundef %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struct st_i32x4x8 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x8_256(struct st_i32x4x8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x9(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x9(ptr noundef %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x9(struct st_i32x4x9 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @test_st_i32x4x9_256(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x9_256(ptr noundef %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x9_256(struct st_i32x4x9 arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index 6281b640c4df06..dbf7671d967328 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -36,19 +36,19 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
 // CHECK-LLVM: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce)
 void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 4 x i16> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 4 x i16> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}
 
-// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x i32> noundef %arg.coerce)
+// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x i32> noundef %arg.coerce)
 [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
 
 
@@ -109,52 +109,52 @@ struct st_i32x4x9{
 
 typedef int __attribute__((vector_size(256))) int32x64_t;
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z14test_too_largeDv64_i(ptr noundef %0)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_too_largeDv64_i(ptr noundef %0)
 [[riscv::vls_cc]] void test_too_large(int32x64_t arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_too_large_256Dv64_i(<vscale x 16 x i32> noundef %arg.coerce)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_too_large_256Dv64_i(<vscale x 16 x i32> noundef %arg.coerce)
 [[riscv::vls_cc(256)]] void test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z13test_st_i32x48st_i32x4(<vscale x 2 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z13test_st_i32x48st_i32x4(<vscale x 2 x i32> %arg)
 [[riscv::vls_cc]] void test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z17test_st_i32x4_2568st_i32x4(<vscale x 1 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z17test_st_i32x4_2568st_i32x4(<vscale x 1 x i32> %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4_256(struct st_i32x4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr113st_i32x4_arr1(<vscale x 2 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr113st_i32x4_arr1(<vscale x 2 x i32> %arg)
 [[riscv::vls_cc]] void test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr1_25613st_i32x4_arr1(<vscale x 1 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr1_25613st_i32x4_arr1(<vscale x 1 x i32> %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr413st_i32x4_arr4(<vscale x 8 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr413st_i32x4_arr4(<vscale x 8 x i32> %arg)
 [[riscv::vls_cc]] void test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr4_25613st_i32x4_arr4(<vscale x 4 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr4_25613st_i32x4_arr4(<vscale x 4 x i32> %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z18test_st_i32x4_arr813st_i32x4_arr8(<vscale x 16 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr813st_i32x4_arr8(<vscale x 16 x i32> %arg)
 [[riscv::vls_cc]] void test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z22test_st_i32x4_arr8_25613st_i32x4_arr8(<vscale x 8 x i32> %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr8_25613st_i32x4_arr8(<vscale x 8 x i32> %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x210st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x210st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
 [[riscv::vls_cc]] void test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x2_25610st_i32x4x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x2_25610st_i32x4x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4x2_256(struct st_i32x4x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x8x210st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x8x210st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg)
 [[riscv::vls_cc]] void test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x8x2_25610st_i32x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x8x2_25610st_i32x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x8x2_256(struct st_i32x8x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z16test_st_i32x64x211st_i32x64x2(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_i32x64x211st_i32x64x2(ptr noundef %arg)
 [[riscv::vls_cc]] void test_st_i32x64x2(struct st_i32x64x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
 [[riscv::vls_cc]] void test_st_i32x4x8(struct st_i32x4x8 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4x8_256(struct st_i32x4x8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z15test_st_i32x4x910st_i32x4x9(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x910st_i32x4x9(ptr noundef %arg)
 [[riscv::vls_cc]] void test_st_i32x4x9(struct st_i32x4x9 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr noundef %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr noundef %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x4x9_256(struct st_i32x4x9 arg) {}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
index da4819186f4e21..6a71d1a9db81fc 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
@@ -19,17 +19,17 @@ void test_no_attribute2(int); // expected-note {{previous declaration is here}}
 __attribute__((riscv_vls_cc)) int var_vls; // expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'int'}}
 
 __attribute__((riscv_vls_cc)) void func_vls();
-__attribute__((riscv_vls_cc(1))) void func_vls_invalid(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'void (void)__attribute__((riscv_vls_cc))'}}
-__attribute__((riscv_vls_cc(129))) void func_vls_invalid(); // expected-error {{argument should be a power of 2}} expected-warning {{'riscv_vls_cc' only applies to function types; type here is 'void (void)__attribute__((riscv_vls_cc))'}}
+__attribute__((riscv_vls_cc(1))) void func_vls_invalid(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}}
+__attribute__((riscv_vls_cc(129))) void func_vls_invalid(); // expected-error {{argument should be a power of 2}}
 
 void test_vls_no_attribute(int); // expected-note {{previous declaration is here}}
-void __attribute__((riscv_vls_cc)) test_vls_no_attribute(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
+void __attribute__((riscv_vls_cc)) test_vls_no_attribute(int x) { } // expected-error {{function declared 'riscv_vls_cc(128)' here was previously declared without calling convention}}
 
 [[riscv::vls_cc]] int var2_vls; // expected-warning {{'vls_cc' only applies to function types; type here is 'int'}}
 
 [[riscv::vls_cc]] void func2_vls();
-[[riscv::vls_cc(1)]] void func_vls_invalid2(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'vls_cc' only applies to function types; type here is 'void (void)'}}
-[[riscv::vls_cc(129)]] void func_vls_invalid2(); // expected-error {{argument should be a power of 2}} expected-warning {{'vls_cc' only applies to function types; type here is 'void (void)'}}
+[[riscv::vls_cc(1)]] void func_vls_invalid2(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}}
+[[riscv::vls_cc(129)]] void func_vls_invalid2(); // expected-error {{argument should be a power of 2}}
 
 void test_vls_no_attribute2(int); // expected-note {{previous declaration is here}}
-[[riscv::vls_cc]] void test_vls_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
+[[riscv::vls_cc]] void test_vls_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vls_cc(128)' here was previously declared without calling convention}}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
index 5e27c76d5307fc..f041b0d36529ca 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
@@ -37,11 +37,11 @@ void test_lambda2() {
 [[riscv::vls_cc]] int var_vls; // expected-warning {{'vls_cc' only applies to function types; type here is 'int'}}
 
 [[riscv::vls_cc]] void func_vls();
-[[riscv::vls_cc(1)]] void func_invalid_vls(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}} expected-warning {{'vls_cc' only applies to function types; type here is 'void ()'}}
-[[riscv::vls_cc(129)]] void func_invalid_vls(); // expected-error {{argument should be a power of 2}} expected-warning {{'vls_cc' only applies to function types; type here is 'void ()'}}
+[[riscv::vls_cc(1)]] void func_invalid_vls(); // expected-error {{argument value 1 is outside the valid range [32, 65536]}}
+[[riscv::vls_cc(129)]] void func_invalid_vls(); // expected-error {{argument should be a power of 2}}
 
 void test_no_attribute_vls(int); // expected-note {{previous declaration is here}}
-[[riscv::vls_cc]] void test_no_attribute_vls(int x) { } // expected-error {{function declared 'riscv_vls_cc' here was previously declared without calling convention}}
+[[riscv::vls_cc]] void test_no_attribute_vls(int x) { } // expected-error {{function declared 'riscv_vls_cc(128)' here was previously declared without calling convention}}
 
 class test_cc_vls {
   [[riscv::vls_cc]] void member_func();
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 65fa6fa2540954..f4227fd0307343 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -701,7 +701,18 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
       TCALLINGCONV(M68kRTD);
       TCALLINGCONV(PreserveNone);
       TCALLINGCONV(RISCVVectorCall);
-      TCALLINGCONV(RISCVVLSCall);
+      TCALLINGCONV(RISCVVLSCall_32);
+      TCALLINGCONV(RISCVVLSCall_64);
+      TCALLINGCONV(RISCVVLSCall_128);
+      TCALLINGCONV(RISCVVLSCall_256);
+      TCALLINGCONV(RISCVVLSCall_512);
+      TCALLINGCONV(RISCVVLSCall_1024);
+      TCALLINGCONV(RISCVVLSCall_2048);
+      TCALLINGCONV(RISCVVLSCall_4096);
+      TCALLINGCONV(RISCVVLSCall_8192);
+      TCALLINGCONV(RISCVVLSCall_16384);
+      TCALLINGCONV(RISCVVLSCall_32768);
+      TCALLINGCONV(RISCVVLSCall_65536);
     case CC_SpirFunction: return CXCallingConv_Unexposed;
     case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed;
     case CC_OpenCLKernel: return CXCallingConv_Unexposed;
diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h
index bc3a75f2fe6656..7897aabb6c1a9b 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -271,7 +271,18 @@ namespace CallingConv {
     AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 = 111,
 
     /// Calling convention used for RISC-V V-extension fixed vectors.
-    RISCV_VLSCall = 112,
+    RISCV_VLSCall_32 = 112,
+    RISCV_VLSCall_64 = 113,
+    RISCV_VLSCall_128 = 114,
+    RISCV_VLSCall_256 = 115,
+    RISCV_VLSCall_512 = 116,
+    RISCV_VLSCall_1024 = 117,
+    RISCV_VLSCall_2048 = 118,
+    RISCV_VLSCall_4096 = 119,
+    RISCV_VLSCall_8192 = 120,
+    RISCV_VLSCall_16384 = 121,
+    RISCV_VLSCall_32768 = 122,
+    RISCV_VLSCall_65536 = 123,
 
     /// The highest possible ID. Must be some 2^k - 1.
     MaxID = 1023
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index abf98f76b6a610..6d5600212f2635 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2285,8 +2285,36 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
     CC = CallingConv::RISCV_VectorCall;
     break;
   case lltok::kw_riscv_vls_cc:
-    CC = CallingConv::RISCV_VLSCall;
+    // Default ABI_VLEN
+    CC = CallingConv::RISCV_VLSCall_128;
+    Lex.Lex();
+    if (!EatIfPresent(lltok::lparen))
+      break;
+    uint32_t ABIVlen;
+    if (parseUInt32(ABIVlen) || !EatIfPresent(lltok::rparen))
+      return true;
+    switch (ABIVlen) {
+    default:
+      return tokError("unknown RISC-V ABI VLEN");
+#define CC_VLS_CASE(ABIVlen)                                                  \
+  case ABIVlen:                                                               \
+    CC = CallingConv::RISCV_VLSCall_##ABIVlen;                                \
     break;
+      CC_VLS_CASE(32)
+      CC_VLS_CASE(64)
+      CC_VLS_CASE(128)
+      CC_VLS_CASE(256)
+      CC_VLS_CASE(512)
+      CC_VLS_CASE(1024)
+      CC_VLS_CASE(2048)
+      CC_VLS_CASE(4096)
+      CC_VLS_CASE(8192)
+      CC_VLS_CASE(16384)
+      CC_VLS_CASE(32768)
+      CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
+    }
+    return false;
   case lltok::kw_cc: {
       Lex.Lex();
       return parseUInt32(CC);
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 67a8e6260f1e39..f3cbc13a534e13 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -368,9 +368,23 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   case CallingConv::RISCV_VectorCall:
     Out << "riscv_vector_cc";
     break;
-  case CallingConv::RISCV_VLSCall:
-    Out << "riscv_vls_cc";
+#define CC_VLS_CASE(ABI_VLEN)                                                  \
+  case CallingConv::RISCV_VLSCall_##ABI_VLEN:                                  \
+    Out << "riscv_vls_cc(" #ABI_VLEN ")";                                      \
     break;
+    CC_VLS_CASE(32)
+    CC_VLS_CASE(64)
+    CC_VLS_CASE(128)
+    CC_VLS_CASE(256)
+    CC_VLS_CASE(512)
+    CC_VLS_CASE(1024)
+    CC_VLS_CASE(2048)
+    CC_VLS_CASE(4096)
+    CC_VLS_CASE(8192)
+    CC_VLS_CASE(16384)
+    CC_VLS_CASE(32768)
+    CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
   }
 }
 
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 96f51580d6ace9..0103b7d428976d 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19901,7 +19901,20 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
   case CallingConv::SPIR_KERNEL:
   case CallingConv::GRAAL:
   case CallingConv::RISCV_VectorCall:
-  case CallingConv::RISCV_VLSCall:
+#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
+    CC_VLS_CASE(32)
+    CC_VLS_CASE(64)
+    CC_VLS_CASE(128)
+    CC_VLS_CASE(256)
+    CC_VLS_CASE(512)
+    CC_VLS_CASE(1024)
+    CC_VLS_CASE(2048)
+    CC_VLS_CASE(4096)
+    CC_VLS_CASE(8192)
+    CC_VLS_CASE(16384)
+    CC_VLS_CASE(32768)
+    CC_VLS_CASE(65536)
+#undef CC_VLS_CASE
     break;
   case CallingConv::GHC:
     if (Subtarget.hasStdExtE())
diff --git a/llvm/test/Assembler/riscv_vls_cc.ll b/llvm/test/Assembler/riscv_vls_cc.ll
index cc63e61ed6a1f7..bfe1def3fc3bed 100644
--- a/llvm/test/Assembler/riscv_vls_cc.ll
+++ b/llvm/test/Assembler/riscv_vls_cc.ll
@@ -1,12 +1,122 @@
 ; RUN: llvm-as < %s | llvm-dis | FileCheck %s
 ; RUN: verify-uselistorder %s
 
-; CHECK: define riscv_vls_cc void @no_args() {
-define riscv_vls_cc void @no_args() {
+; CHECK: define riscv_vls_cc(32) void @no_args_32() {
+define riscv_vls_cc(32) void @no_args_32() {
   ret void
 }
 
-; CHECK: define riscv_vls_cc void @byval_arg(ptr byval(i32) %0) {
-define riscv_vls_cc void @byval_arg(ptr byval(i32)) {
+; CHECK: define riscv_vls_cc(64) void @no_args_64() {
+define riscv_vls_cc(64) void @no_args_64() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(128) void @no_args_128() {
+define riscv_vls_cc(128) void @no_args_128() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(256) void @no_args_256() {
+define riscv_vls_cc(256) void @no_args_256() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(512) void @no_args_512() {
+define riscv_vls_cc(512) void @no_args_512() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(1024) void @no_args_1024() {
+define riscv_vls_cc(1024) void @no_args_1024() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(2048) void @no_args_2048() {
+define riscv_vls_cc(2048) void @no_args_2048() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(4096) void @no_args_4096() {
+define riscv_vls_cc(4096) void @no_args_4096() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(8192) void @no_args_8192() {
+define riscv_vls_cc(8192) void @no_args_8192() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(16384) void @no_args_16384() {
+define riscv_vls_cc(16384) void @no_args_16384() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(32768) void @no_args_32768() {
+define riscv_vls_cc(32768) void @no_args_32768() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(65536) void @no_args_65536() {
+define riscv_vls_cc(65536) void @no_args_65536() {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(32) void @byval_arg_32(ptr byval(i32) %0) {
+define riscv_vls_cc(32) void @byval_arg_32(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(64) void @byval_arg_64(ptr byval(i32) %0) {
+define riscv_vls_cc(64) void @byval_arg_64(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(128) void @byval_arg_128(ptr byval(i32) %0) {
+define riscv_vls_cc(128) void @byval_arg_128(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(256) void @byval_arg_256(ptr byval(i32) %0) {
+define riscv_vls_cc(256) void @byval_arg_256(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(512) void @byval_arg_512(ptr byval(i32) %0) {
+define riscv_vls_cc(512) void @byval_arg_512(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(1024) void @byval_arg_1024(ptr byval(i32) %0) {
+define riscv_vls_cc(1024) void @byval_arg_1024(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(2048) void @byval_arg_2048(ptr byval(i32) %0) {
+define riscv_vls_cc(2048) void @byval_arg_2048(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(4096) void @byval_arg_4096(ptr byval(i32) %0) {
+define riscv_vls_cc(4096) void @byval_arg_4096(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(8192) void @byval_arg_8192(ptr byval(i32) %0) {
+define riscv_vls_cc(8192) void @byval_arg_8192(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(16384) void @byval_arg_16384(ptr byval(i32) %0) {
+define riscv_vls_cc(16384) void @byval_arg_16384(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(32768) void @byval_arg_32768(ptr byval(i32) %0) {
+define riscv_vls_cc(32768) void @byval_arg_32768(ptr byval(i32)) {
+  ret void
+}
+
+; CHECK: define riscv_vls_cc(65536) void @byval_arg_65536(ptr byval(i32) %0) {
+define riscv_vls_cc(65536) void @byval_arg_65536(ptr byval(i32)) {
   ret void
 }
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 485508ca0013ad..3e68ca061bd2eb 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -517,9 +517,53 @@ declare cc96 void @f.cc96()
 declare amdgpu_es void @f.amdgpu_es()
 ; CHECK: declare amdgpu_es void @f.amdgpu_es()
 declare cc112 void @f.cc112()
-; CHECK: declare riscv_vls_cc void @f.cc112()
-declare riscv_vls_cc void @riscv_vls_cc()
-; CHECK: declare riscv_vls_cc void @riscv_vls_cc()
+; CHECK: declare riscv_vls_cc(32) void @f.cc112()
+declare cc113 void @f.cc113()
+; CHECK: declare riscv_vls_cc(64) void @f.cc113()
+declare cc114 void @f.cc114()
+; CHECK: declare riscv_vls_cc(128) void @f.cc114()
+declare cc115 void @f.cc115()
+; CHECK: declare riscv_vls_cc(256) void @f.cc115()
+declare cc116 void @f.cc116()
+; CHECK: declare riscv_vls_cc(512) void @f.cc116()
+declare cc117 void @f.cc117()
+; CHECK: declare riscv_vls_cc(1024) void @f.cc117()
+declare cc118 void @f.cc118()
+; CHECK: declare riscv_vls_cc(2048) void @f.cc118()
+declare cc119 void @f.cc119()
+; CHECK: declare riscv_vls_cc(4096) void @f.cc119()
+declare cc120 void @f.cc120()
+; CHECK: declare riscv_vls_cc(8192) void @f.cc120()
+declare cc121 void @f.cc121()
+; CHECK: declare riscv_vls_cc(16384) void @f.cc121()
+declare cc122 void @f.cc122()
+; CHECK: declare riscv_vls_cc(32768) void @f.cc122()
+declare cc123 void @f.cc123()
+; CHECK: declare riscv_vls_cc(65536) void @f.cc123()
+declare riscv_vls_cc(32) void @riscv_vls_cc_32()
+; CHECK: declare riscv_vls_cc(32) void @riscv_vls_cc_32()
+declare riscv_vls_cc(64) void @riscv_vls_cc_64()
+; CHECK: declare riscv_vls_cc(64) void @riscv_vls_cc_64()
+declare riscv_vls_cc(128) void @riscv_vls_cc_128()
+; CHECK: declare riscv_vls_cc(128) void @riscv_vls_cc_128()
+declare riscv_vls_cc(256) void @riscv_vls_cc_256()
+; CHECK: declare riscv_vls_cc(256) void @riscv_vls_cc_256()
+declare riscv_vls_cc(512) void @riscv_vls_cc_512()
+; CHECK: declare riscv_vls_cc(512) void @riscv_vls_cc_512()
+declare riscv_vls_cc(1024) void @riscv_vls_cc_1024()
+; CHECK: declare riscv_vls_cc(1024) void @riscv_vls_cc_1024()
+declare riscv_vls_cc(2048) void @riscv_vls_cc_2048()
+; CHECK: declare riscv_vls_cc(2048) void @riscv_vls_cc_2048()
+declare riscv_vls_cc(4096) void @riscv_vls_cc_4096()
+; CHECK: declare riscv_vls_cc(4096) void @riscv_vls_cc_4096()
+declare riscv_vls_cc(8192) void @riscv_vls_cc_8192()
+; CHECK: declare riscv_vls_cc(8192) void @riscv_vls_cc_8192()
+declare riscv_vls_cc(16384) void @riscv_vls_cc_16384()
+; CHECK: declare riscv_vls_cc(16384) void @riscv_vls_cc_16384()
+declare riscv_vls_cc(32768) void @riscv_vls_cc_32768()
+; CHECK: declare riscv_vls_cc(32768) void @riscv_vls_cc_32768()
+declare riscv_vls_cc(65536) void @riscv_vls_cc_65536()
+; CHECK: declare riscv_vls_cc(65536) void @riscv_vls_cc_65536()
 declare cc1023 void @f.cc1023()
 ; CHECK: declare cc1023 void @f.cc1023()
 

>From 29b0c56c9ff62a008e3bd892dc89de22471793c6 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Fri, 17 Jan 2025 02:55:21 -0800
Subject: [PATCH 08/10] fixup! fixed comments

---
 clang/include/clang/Driver/Options.td         |  1 +
 clang/lib/CodeGen/Targets/RISCV.cpp           | 26 ++++++++++-------
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 29 +++++++++++++------
 .../riscv-vector-callingconv-llvm-ir.cpp      | 29 +++++++++++++------
 4 files changed, 57 insertions(+), 28 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 4a4900a0e3b6ea..2721c1b5d8dc55 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4992,6 +4992,7 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
       !eq(GlobalDocumentation.Program, "Flang") : "",
       true: " The value will be reflected in __riscv_v_fixed_vlen preprocessor define"),
     " (RISC-V only)")>;
+
 def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
   HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
 def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index bbc23738074fcb..66ab6d9261e1f2 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -118,7 +118,7 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
   unsigned ABIVLen;
   switch (FI.getExtInfo().getCC()) {
   default:
-    ABIVLen = 1;
+    ABIVLen = 0;
     break;
   case CallingConv::CC_RISCVVLSCall_32:
     ABIVLen = 32;
@@ -414,28 +414,34 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
   // Legal struct for VLS calling convention should fulfill following rules:
   // 1. Struct element should be either "homogeneous fixed-length vectors" or "a
   //    fixed-length vector array".
-  // 2. Number of struct elements or array elements should be power of 2.
+  // 2. Number of struct elements or array elements should be greater or equal
+  //    to 1 and less or equal to 8
   // 3. Total number of vector registers needed should not exceed 8.
   //
   // Examples: Assume ABI_VLEN = 128.
   // These are legal structs:
-  //   a. Structs with 1, 2, 4 or 8 "same" fixed-length vectors, e.g.
+  //   a. Structs with 1~8 "same" fixed-length vectors, e.g.
   //   struct {
   //     __attribute__((vector_size(16))) int a;
   //     __attribute__((vector_size(16))) int b;
   //   }
   //
-  //   b. Structs with "single" fixed-length vector array with lengh 1, 2, 4
-  //   or 8, e.g.
+  //   b. Structs with "single" fixed-length vector array with lengh 1~8, e.g.
   //   struct {
-  //     __attribute__((vector_size(16))) int a[2];
+  //     __attribute__((vector_size(16))) int a[3];
   //   }
   // These are illegal structs:
-  //   a. Structs with 3 fixed-length vectors, e.g.
+  //   a. Structs with 9 fixed-length vectors, e.g.
   //   struct {
   //     __attribute__((vector_size(16))) int a;
   //     __attribute__((vector_size(16))) int b;
   //     __attribute__((vector_size(16))) int c;
+  //     __attribute__((vector_size(16))) int d;
+  //     __attribute__((vector_size(16))) int e;
+  //     __attribute__((vector_size(16))) int f;
+  //     __attribute__((vector_size(16))) int g;
+  //     __attribute__((vector_size(16))) int h;
+  //     __attribute__((vector_size(16))) int i;
   //   }
   //
   //   b. Structs with "multiple" fixed-length vector array, e.g.
@@ -461,7 +467,7 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
 
   if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty))) {
     int NumElts = STy->getStructNumElements();
-    if (NumElts > 8 || !llvm::isPowerOf2_32(NumElts))
+    if (NumElts > 8)
       return false;
 
     auto *FirstEltTy = STy->getElementType(0);
@@ -517,7 +523,7 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
     // if legal.
     if (auto *ArrTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
       int NumArrElt = ArrTy->getNumElements();
-      if (NumArrElt > 8 || !llvm::isPowerOf2_32(NumArrElt))
+      if (NumArrElt > 8)
         return false;
 
       auto *ArrEltTy = dyn_cast<llvm::FixedVectorType>(ArrTy->getElementType());
@@ -728,7 +734,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
         VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
       return coerceVLSVector(Ty);
-    if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 1)
+    if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 0)
       // Generic vector without riscv_vls_cc should fall through and pass by
       // reference.
       return coerceVLSVector(Ty, ABIVLen);
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
index 61300d62e1eb69..ec4fd44be41936 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -69,39 +69,45 @@ void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((v
 [[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}
 
 
-struct st_i32x4{
+struct st_i32x4 {
     __attribute__((vector_size(16))) int i32;
 };
 
-struct st_i32x4_arr1{
+struct st_i32x4_arr1 {
     __attribute__((vector_size(16))) int i32[1];
 };
 
-struct st_i32x4_arr4{
+struct st_i32x4_arr4 {
     __attribute__((vector_size(16))) int i32[4];
 };
 
-struct st_i32x4_arr8{
+struct st_i32x4_arr8 {
     __attribute__((vector_size(16))) int i32[8];
 };
 
 
-struct st_i32x4x2{
+struct st_i32x4x2 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
 };
 
-struct st_i32x8x2{
+struct st_i32x8x2 {
     __attribute__((vector_size(32))) int i32_1;
     __attribute__((vector_size(32))) int i32_2;
 };
 
-struct st_i32x64x2{
+struct st_i32x64x2 {
     __attribute__((vector_size(256))) int i32_1;
     __attribute__((vector_size(256))) int i32_2;
 };
 
-struct st_i32x4x8{
+struct st_i32x4x3 {
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+};
+
+struct st_i32x4x8 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
     __attribute__((vector_size(16))) int i32_3;
@@ -112,7 +118,7 @@ struct st_i32x4x8{
     __attribute__((vector_size(16))) int i32_8;
 };
 
-struct st_i32x4x9{
+struct st_i32x4x9 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
     __attribute__((vector_size(16))) int i32_3;
@@ -166,6 +172,11 @@ void __attribute__((riscv_vls_cc)) test_st_i32x64x2(struct st_i32x64x2 arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x64x2_256(ptr noundef %arg)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
 
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x3(target("riscv.vector.tuple", <vscale x 8 x i8>, 3) %arg)
+void __attribute__((riscv_vls_cc)) test_st_i32x4x3(struct st_i32x4x3 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x3_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 3) %arg)
+void __attribute__((riscv_vls_cc(256))) test_st_i32x4x3_256(struct st_i32x4x3 arg) {}
+
 // CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struct st_i32x4x8 arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
index dbf7671d967328..0eedb13b53033f 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
@@ -52,39 +52,45 @@ void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
 [[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {}
 
 
-struct st_i32x4{
+struct st_i32x4 {
     __attribute__((vector_size(16))) int i32;
 };
 
-struct st_i32x4_arr1{
+struct st_i32x4_arr1 {
     __attribute__((vector_size(16))) int i32[1];
 };
 
-struct st_i32x4_arr4{
+struct st_i32x4_arr4 {
     __attribute__((vector_size(16))) int i32[4];
 };
 
-struct st_i32x4_arr8{
+struct st_i32x4_arr8 {
     __attribute__((vector_size(16))) int i32[8];
 };
 
 
-struct st_i32x4x2{
+struct st_i32x4x2 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
 };
 
-struct st_i32x8x2{
+struct st_i32x8x2 {
     __attribute__((vector_size(32))) int i32_1;
     __attribute__((vector_size(32))) int i32_2;
 };
 
-struct st_i32x64x2{
+struct st_i32x64x2 {
     __attribute__((vector_size(256))) int i32_1;
     __attribute__((vector_size(256))) int i32_2;
 };
 
-struct st_i32x4x8{
+struct st_i32x4x3 {
+    __attribute__((vector_size(16))) int i32_1;
+    __attribute__((vector_size(16))) int i32_2;
+    __attribute__((vector_size(16))) int i32_3;
+};
+
+struct st_i32x4x8 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
     __attribute__((vector_size(16))) int i32_3;
@@ -95,7 +101,7 @@ struct st_i32x4x8{
     __attribute__((vector_size(16))) int i32_8;
 };
 
-struct st_i32x4x9{
+struct st_i32x4x9 {
     __attribute__((vector_size(16))) int i32_1;
     __attribute__((vector_size(16))) int i32_2;
     __attribute__((vector_size(16))) int i32_3;
@@ -149,6 +155,11 @@ typedef int __attribute__((vector_size(256))) int32x64_t;
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef %arg)
 [[riscv::vls_cc(256)]] void test_st_i32x64x2_256(struct st_i32x64x2 arg) {}
 
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x310st_i32x4x3(target("riscv.vector.tuple", <vscale x 8 x i8>, 3) %arg)
+[[riscv::vls_cc]] void test_st_i32x4x3(struct st_i32x4x3 arg) {}
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x3_25610st_i32x4x3(target("riscv.vector.tuple", <vscale x 4 x i8>, 3) %arg)
+[[riscv::vls_cc(256)]] void test_st_i32x4x3_256(struct st_i32x4x3 arg) {}
+
 // CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg)
 [[riscv::vls_cc]] void test_st_i32x4x8(struct st_i32x4x8 arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg)

>From 62196b846b901859340fc8759cf9aaa120aa7476 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Fri, 17 Jan 2025 03:05:20 -0800
Subject: [PATCH 09/10] fixup! clang-format

---
 clang/include/clang/AST/Type.h      | 5 +----
 clang/lib/CodeGen/Targets/RISCV.cpp | 8 +++-----
 clang/lib/Sema/SemaDeclAttr.cpp     | 6 +++---
 llvm/lib/AsmParser/LLParser.cpp     | 6 +++---
 4 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1568ee4c8f8dcc..5af85418135405 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -4444,10 +4444,7 @@ class FunctionType : public Type {
     enum { NoReturnMask = 0x40 };
     enum { ProducesResultMask = 0x80 };
     enum { NoCallerSavedRegsMask = 0x100 };
-    enum {
-      RegParmMask =  0xe00,
-      RegParmOffset = 9
-    };
+    enum { RegParmMask = 0xe00, RegParmOffset = 9 };
     enum { NoCfCheckMask = 0x1000 };
     enum { CmseNSCallMask = 0x2000 };
     uint16_t Bits = CC_C;
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 66ab6d9261e1f2..9d39cb9dfc5c73 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -8,7 +8,6 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
-#include "llvm/TargetParser/RISCVTargetParser.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -41,8 +40,8 @@ class RISCVABIInfo : public DefaultABIInfo {
 public:
   RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
                bool EABI)
-      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen),
-        NumArgGPRs(EABI ? 6 : 8), NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
+      : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
+        NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
 
   // DefaultABIInfo's classifyReturnType and classifyArgumentType are
   // non-virtual, but computeInfo is virtual, so we overload it.
@@ -556,8 +555,7 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
 
 // Fixed-length RVV vectors are represented as scalable vectors in function
 // args/return and must be coerced from fixed vectors.
-ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
-                                         unsigned ABIVLen) const {
+ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty, unsigned ABIVLen) const {
   assert(Ty->isVectorType() && "expected vector type!");
 
   const auto *VT = Ty->castAs<VectorType>();
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index e730f25201dcd8..8425ea21737301 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5254,17 +5254,17 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
     unsigned ABIVLen = 128;
     if (Attrs.getNumArgs() &&
         !checkUInt32Argument(Attrs, Attrs.getArgAsExpr(0), ABIVLen)) {
-    Attrs.setInvalid();
+      Attrs.setInvalid();
       return true;
     }
     if (Attrs.getNumArgs() && (ABIVLen < 32 || ABIVLen > 65536)) {
-    Attrs.setInvalid();
+      Attrs.setInvalid();
       Diag(Attrs.getLoc(), diag::err_argument_invalid_range)
           << ABIVLen << 32 << 65536;
       return true;
     }
     if (!llvm::isPowerOf2_64(ABIVLen)) {
-    Attrs.setInvalid();
+      Attrs.setInvalid();
       Diag(Attrs.getLoc(), diag::err_argument_not_power_of_2);
       return true;
     }
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 6d5600212f2635..dfbf80ab0437e9 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2296,9 +2296,9 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
     switch (ABIVlen) {
     default:
       return tokError("unknown RISC-V ABI VLEN");
-#define CC_VLS_CASE(ABIVlen)                                                  \
-  case ABIVlen:                                                               \
-    CC = CallingConv::RISCV_VLSCall_##ABIVlen;                                \
+#define CC_VLS_CASE(ABIVlen)                                                   \
+  case ABIVlen:                                                                \
+    CC = CallingConv::RISCV_VLSCall_##ABIVlen;                                 \
     break;
       CC_VLS_CASE(32)
       CC_VLS_CASE(64)

>From 27fd1b7676dcb940414b4e5a2b3d17b65d991f1b Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Fri, 17 Jan 2025 03:16:47 -0800
Subject: [PATCH 10/10] fixup! missing include RISCVTargetParser.h

---
 clang/lib/CodeGen/Targets/RISCV.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 9d39cb9dfc5c73..3de35b3a7f4bda 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 
 using namespace clang;
 using namespace clang::CodeGen;



More information about the llvm-commits mailing list