Skip to content

Conversation

Steelskin
Copy link
Contributor

This cherry-picks the following commits into the release/21.x branch:

This solves an issue when building the release/21.x branch with MSVC for Windows Arm64 where the function is too large to compile, resulting in this error:

S:\SourceCache\llvm-project\clang\lib\CodeGen\TargetBuiltins\RISCV.cpp(138) : fatal error C1053: '?EmitRISCVBuiltinExpr@CodeGenFunction@CodeGen@clang@@QEAAPEAVValue@llvm@@IPEBVCallExpr@3@VReturnValueSlot@23@@Z': function too large

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. labels Sep 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Fabrice de Gans (Steelskin)

Changes

This cherry-picks the following commits into the release/21.x branch:

This solves an issue when building the release/21.x branch with MSVC for Windows Arm64 where the function is too large to compile, resulting in this error:

S:\SourceCache\llvm-project\clang\lib\CodeGen\TargetBuiltins\RISCV.cpp(138) : fatal error C1053: '?EmitRISCVBuiltinExpr@<!-- -->CodeGenFunction@<!-- -->CodeGen@<!-- -->clang@@<!-- -->QEAAPEAVValue@<!-- -->llvm@@<!-- -->IPEBVCallExpr@<!-- -->3@<!-- -->VReturnValueSlot@<!-- -->23@@<!-- -->Z': function too large

Patch is 88.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158164.diff

2 Files Affected:

  • (modified) clang/include/clang/Basic/riscv_vector.td (+77-858)
  • (modified) clang/lib/CodeGen/TargetBuiltins/RISCV.cpp (+945-4)
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 275bb2b9924dd..cc5ab38f8f960 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -56,34 +56,8 @@ multiclass RVVVLEFFBuiltin<list<string> types> {
       SupportOverloading = false,
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          // Move mask to right before vl.
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()};
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()};
-        }
-        Value *NewVL = Ops[2];
-        Ops.erase(Ops.begin() + 2);
-        llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-        llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
-        llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
-        // Store new_vl.
-        clang::CharUnits Align;
-        if (IsMasked)
-          Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(E->getNumArgs()-2)->getType());
-        else
-          Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType());
-        llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1});
-        Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align));
-        return V;
-      }
+        return emitRVVVLEFFBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
     foreach type = types in {
       def : RVVBuiltin<"v", "vPCePz", type>;
@@ -139,17 +113,8 @@ multiclass RVVIndexedLoad<string op> {
 let HasMaskedOffOperand = false,
     MaskedPolicyScheme = NonePolicy,
     ManualCodegen = [{
-      if (IsMasked) {
-        // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl)
-        std::swap(Ops[0], Ops[2]);
-      } else {
-        // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl)
-        std::swap(Ops[0], Ops[1]);
-      }
-      if (IsMasked)
-        IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
-      else
-        IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
+      return emitRVVVSEMaskBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
     }] in {
   class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> {
     let Name = "vsm_v";
@@ -177,17 +142,8 @@ multiclass RVVVSSEBuiltin<list<string> types> {
       HasMaskedOffOperand = false,
       MaskedPolicyScheme = NonePolicy,
       ManualCodegen = [{
-        if (IsMasked) {
-          // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl)
-          std::swap(Ops[0], Ops[3]);
-        } else {
-          // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
-          std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
-        }
-        if (IsMasked)
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()};
-        else
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
+        return emitRVVVSSEBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                  PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
     foreach type = types in {
       def : RVVBuiltin<"v", "0Petv", type>;
@@ -202,17 +158,8 @@ multiclass RVVIndexedStore<string op> {
   let HasMaskedOffOperand = false,
       MaskedPolicyScheme = NonePolicy,
       ManualCodegen = [{
-        if (IsMasked) {
-          // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl)
-          std::swap(Ops[0], Ops[3]);
-        } else {
-          // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl)
-          std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
-        }
-        if (IsMasked)
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[4]->getType()};
-        else
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[3]->getType()};
+        return emitRVVIndexedStoreBuiltin(this, E, ReturnValue, ResultType, ID,
+                                          Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
       foreach type = TypeList in {
         foreach eew_list = EEWList[0-2] in {
@@ -367,28 +314,8 @@ multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
-
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl, policy
-          IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
-        } else {
-          // passthru, op1, op2, vl
-          IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoUnaryBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
   }
@@ -400,32 +327,8 @@ multiclass RVVPseudoVNotBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
-        Ops.insert(Ops.begin() + 2,
-                   llvm::Constant::getAllOnesValue(ElemTy));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, po2, mask, vl, policy
-          IntrinsicTypes = {ResultType,
-                            ElemTy,
-                            Ops[4]->getType()};
-        } else {
-          // passthru, op1, op2, vl
-          IntrinsicTypes = {ResultType,
-                            ElemTy,
-                            Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVNotBuiltin(this, E, ReturnValue, ResultType, ID,
+                                        Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
         def : RVVBuiltin<"Uv", "UvUv", type_range>;
@@ -437,13 +340,8 @@ multiclass RVVPseudoMaskBuiltin<string IR, string type_range> {
       IRName = IR,
       HasMasked = false,
       ManualCodegen = [{
-      {
-        // op1, vl
-        IntrinsicTypes = {ResultType,
-                          Ops[1]->getType()};
-        Ops.insert(Ops.begin() + 1, Ops[0]);
-        break;
-      }
+        return emitRVVPseudoMaskBuiltin(this, E, ReturnValue, ResultType, ID,
+                                        Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"m", "mm", type_range>;
   }
@@ -455,28 +353,8 @@ multiclass RVVPseudoVFUnaryBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          Ops.insert(Ops.begin() + 2, Ops[1]);
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[2]->getType(),
-                            Ops.back()->getType()};
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          // op1, po2, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(), Ops[2]->getType()};
-          Ops.insert(Ops.begin() + 2, Ops[1]);
-          break;
-        }
-        break;
-      }
+        return emitRVVPseudoVFUnaryBuiltin(this, E, ReturnValue, ResultType, ID,
+                                           Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
   }
@@ -490,33 +368,8 @@ multiclass RVVPseudoVWCVTBuiltin<string IR, string MName, string type_range,
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(Ops[1]->getType())->getElementType();
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl, policy
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            ElemTy,
-                            Ops[4]->getType()};
-        } else {
-          // passtru, op1, op2, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            ElemTy,
-                            Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVWCVTBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         foreach s_p = suffixes_prototypes in {
           def : RVVBuiltin<s_p[0], s_p[1], type_range>;
@@ -532,32 +385,8 @@ multiclass RVVPseudoVNCVTBuiltin<string IR, string MName, string type_range,
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(Ops.back()->getType()));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, xlen, mask, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            Ops[4]->getType(),
-                            Ops[4]->getType()};
-        } else {
-          // passthru, op1, xlen, vl
-          IntrinsicTypes = {ResultType,
-                  Ops[1]->getType(),
-                  Ops[3]->getType(),
-                  Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVNCVTBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         foreach s_p = suffixes_prototypes in {
           def : RVVBuiltin<s_p[0], s_p[1], type_range>;
@@ -575,17 +404,8 @@ let HasBuiltinAlias = false, HasVL = false, HasMasked = false,
     UnMaskedPolicyScheme = NonePolicy, MaskedPolicyScheme = NonePolicy,
     Log2LMUL = [0], IRName = "",
     ManualCodegen = [{
-    {
-      LLVMContext &Context = CGM.getLLVMContext();
-      llvm::MDBuilder MDHelper(Context);
-
-      llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "vlenb")};
-      llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
-      llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
-      llvm::Function *F =
-        CGM.getIntrinsic(llvm::Intrinsic::read_register, {SizeTy});
-      return Builder.CreateCall(F, Metadata);
-    }
+      return emitRVVVlenbBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                 PolicyAttrs, IsMasked, SegInstSEW);
     }] in
 {
   def vlenb : RVVBuiltin<"", "u", "i">;
@@ -660,7 +480,10 @@ let HasBuiltinAlias = false,
     HasMasked = false,
     MaskedPolicyScheme = NonePolicy,
     Log2LMUL = [0],
-    ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
+    ManualCodegen = [{
+      return emitRVVVsetvliBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
+    }] in // Set XLEN type
 {
   def vsetvli : RVVBuiltin<"", "zzKzKz", "i">;
   def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">;
@@ -720,43 +543,10 @@ multiclass RVVUnitStridedSegLoadTuple<string op> {
             MaskedIRName = op # nf # "_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 6> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
-
-      if (IsMasked)
-        IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(), Ops.back()->getType()};
-      else
-        IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType()};
-
-      if (NoPassthru) { // Push poison into passthru
-        Operands.push_back(llvm::PoisonValue::get(ResultType));
-      } else { // Push intrinsics operands into passthru
-        llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0];
-        Operands.push_back(PassthruOperand);
-      }
-
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 1]); // VL
-      if (IsMasked)
-        Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-
-      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
-      if (ReturnValue.isNull())
-        return LoadValue;
-      else
-        return Builder.CreateStore(LoadValue, ReturnValue.getValue());
-    }
-    }] in {
+              return emitRVVUnitStridedSegLoadTupleBuiltin(
+                  this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs,
+                  IsMasked, SegInstSEW);
+            }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", T # "vPCe", type>;
         if !not(IsFloat<type>.val) then {
@@ -784,31 +574,10 @@ multiclass RVVUnitStridedSegStoreTuple<string op> {
           NF = nf,
           HasMaskedOffOperand = false,
           ManualCodegen = [{
-    {
-      // Masked
-      // Builtin: (mask, ptr, v_tuple, vl)
-      // Intrinsic: (tuple, ptr, mask, vl)
-      // Unmasked
-      // Builtin: (ptr, v_tuple, vl)
-      // Intrinsic: (tuple, ptr, vl)
-      unsigned Offset = IsMasked ? 1 : 0;
-
-      SmallVector<llvm::Value*, 5> Operands;
-      Operands.push_back(Ops[Offset + 1]); // tuple
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 2]); // VL
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      if (IsMasked)
-        IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Ops[0]->getType(), Operands.back()->getType()};
-      else
-        IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Operands.back()->getType()};
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-      return Builder.CreateCall(F, Operands, "");
-   }
-      }] in {
+            return emitRVVUnitStridedSegStoreTupleBuiltin(
+                this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs,
+                IsMasked, SegInstSEW);
+          }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", "0Pe" # T # "v", type>;
         if !not(IsFloat<type>.val) then {
@@ -835,52 +604,9 @@ multiclass RVVUnitStridedSegLoadFFTuple<string op> {
             MaskedIRName = op # nf # "ff_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 6> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
-
-      if (IsMasked)
-        IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(), Ops[0]->getType()};
-      else
-        IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType()};
-
-      if (NoPassthru) { // Push poison into passthru
-        Operands.push_back(llvm::PoisonValue::get(ResultType));
-      } else { // Push intrinsics operands into passthru
-        llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0];
-        Operands.push_back(PassthruOperand);
-      }
-
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 2]); // vl
-      if (IsMasked)
-        Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-
-      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
-      // Get alignment from the new vl operand
-      clang::CharUnits Align =
-          CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType());
-
-      llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0);
-
-      // Store new_vl
-      llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1);
-      Builder.CreateStore(V, Address(Ops[Offset + 1], V->getType(), Align));
-
-      if (ReturnValue.isNull())
-        return ReturnTuple;
-      else
-        return Builder.CreateStore(ReturnTuple, ReturnValue.getValue());
-    }
+      return emitRVVUnitStridedSegLoadFFTupleBuiltin(
+          this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked,
+          SegInstSEW);
     }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", T # "vPCePz", type>;
@@ -908,43 +634,9 @@ multiclass RVVStridedSegLoadTuple<string op> {
             MaskedIRName = op # nf # "_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 7> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Fabrice de Gans (Steelskin)

Changes

This cherry-picks the following commits into the release/21.x branch:

This solves an issue when building the release/21.x branch with MSVC for Windows Arm64 where the function is too large to compile, resulting in this error:

S:\SourceCache\llvm-project\clang\lib\CodeGen\TargetBuiltins\RISCV.cpp(138) : fatal error C1053: '?EmitRISCVBuiltinExpr@<!-- -->CodeGenFunction@<!-- -->CodeGen@<!-- -->clang@@<!-- -->QEAAPEAVValue@<!-- -->llvm@@<!-- -->IPEBVCallExpr@<!-- -->3@<!-- -->VReturnValueSlot@<!-- -->23@@<!-- -->Z': function too large

Patch is 88.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158164.diff

2 Files Affected:

  • (modified) clang/include/clang/Basic/riscv_vector.td (+77-858)
  • (modified) clang/lib/CodeGen/TargetBuiltins/RISCV.cpp (+945-4)
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 275bb2b9924dd..cc5ab38f8f960 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -56,34 +56,8 @@ multiclass RVVVLEFFBuiltin<list<string> types> {
       SupportOverloading = false,
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          // Move mask to right before vl.
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()};
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()};
-        }
-        Value *NewVL = Ops[2];
-        Ops.erase(Ops.begin() + 2);
-        llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-        llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
-        llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
-        // Store new_vl.
-        clang::CharUnits Align;
-        if (IsMasked)
-          Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(E->getNumArgs()-2)->getType());
-        else
-          Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType());
-        llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1});
-        Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align));
-        return V;
-      }
+        return emitRVVVLEFFBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
     foreach type = types in {
       def : RVVBuiltin<"v", "vPCePz", type>;
@@ -139,17 +113,8 @@ multiclass RVVIndexedLoad<string op> {
 let HasMaskedOffOperand = false,
     MaskedPolicyScheme = NonePolicy,
     ManualCodegen = [{
-      if (IsMasked) {
-        // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl)
-        std::swap(Ops[0], Ops[2]);
-      } else {
-        // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl)
-        std::swap(Ops[0], Ops[1]);
-      }
-      if (IsMasked)
-        IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
-      else
-        IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
+      return emitRVVVSEMaskBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
     }] in {
   class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> {
     let Name = "vsm_v";
@@ -177,17 +142,8 @@ multiclass RVVVSSEBuiltin<list<string> types> {
       HasMaskedOffOperand = false,
       MaskedPolicyScheme = NonePolicy,
       ManualCodegen = [{
-        if (IsMasked) {
-          // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl)
-          std::swap(Ops[0], Ops[3]);
-        } else {
-          // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
-          std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
-        }
-        if (IsMasked)
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()};
-        else
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
+        return emitRVVVSSEBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                  PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
     foreach type = types in {
       def : RVVBuiltin<"v", "0Petv", type>;
@@ -202,17 +158,8 @@ multiclass RVVIndexedStore<string op> {
   let HasMaskedOffOperand = false,
       MaskedPolicyScheme = NonePolicy,
       ManualCodegen = [{
-        if (IsMasked) {
-          // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl)
-          std::swap(Ops[0], Ops[3]);
-        } else {
-          // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl)
-          std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
-        }
-        if (IsMasked)
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[4]->getType()};
-        else
-          IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[3]->getType()};
+        return emitRVVIndexedStoreBuiltin(this, E, ReturnValue, ResultType, ID,
+                                          Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
       foreach type = TypeList in {
         foreach eew_list = EEWList[0-2] in {
@@ -367,28 +314,8 @@ multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
-
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl, policy
-          IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
-        } else {
-          // passthru, op1, op2, vl
-          IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoUnaryBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
   }
@@ -400,32 +327,8 @@ multiclass RVVPseudoVNotBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
-        Ops.insert(Ops.begin() + 2,
-                   llvm::Constant::getAllOnesValue(ElemTy));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, po2, mask, vl, policy
-          IntrinsicTypes = {ResultType,
-                            ElemTy,
-                            Ops[4]->getType()};
-        } else {
-          // passthru, op1, op2, vl
-          IntrinsicTypes = {ResultType,
-                            ElemTy,
-                            Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVNotBuiltin(this, E, ReturnValue, ResultType, ID,
+                                        Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
         def : RVVBuiltin<"Uv", "UvUv", type_range>;
@@ -437,13 +340,8 @@ multiclass RVVPseudoMaskBuiltin<string IR, string type_range> {
       IRName = IR,
       HasMasked = false,
       ManualCodegen = [{
-      {
-        // op1, vl
-        IntrinsicTypes = {ResultType,
-                          Ops[1]->getType()};
-        Ops.insert(Ops.begin() + 1, Ops[0]);
-        break;
-      }
+        return emitRVVPseudoMaskBuiltin(this, E, ReturnValue, ResultType, ID,
+                                        Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"m", "mm", type_range>;
   }
@@ -455,28 +353,8 @@ multiclass RVVPseudoVFUnaryBuiltin<string IR, string type_range> {
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          Ops.insert(Ops.begin() + 2, Ops[1]);
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[2]->getType(),
-                            Ops.back()->getType()};
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-          // op1, po2, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(), Ops[2]->getType()};
-          Ops.insert(Ops.begin() + 2, Ops[1]);
-          break;
-        }
-        break;
-      }
+        return emitRVVPseudoVFUnaryBuiltin(this, E, ReturnValue, ResultType, ID,
+                                           Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         def : RVVBuiltin<"v", "vv", type_range>;
   }
@@ -490,33 +368,8 @@ multiclass RVVPseudoVWCVTBuiltin<string IR, string MName, string type_range,
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        auto ElemTy = cast<llvm::VectorType>(Ops[1]->getType())->getElementType();
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, op2, mask, vl, policy
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            ElemTy,
-                            Ops[4]->getType()};
-        } else {
-          // passtru, op1, op2, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            ElemTy,
-                            Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVWCVTBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         foreach s_p = suffixes_prototypes in {
           def : RVVBuiltin<s_p[0], s_p[1], type_range>;
@@ -532,32 +385,8 @@ multiclass RVVPseudoVNCVTBuiltin<string IR, string MName, string type_range,
       MaskedIRName = IR # "_mask",
       UnMaskedPolicyScheme = HasPassthruOperand,
       ManualCodegen = [{
-      {
-        if (IsMasked) {
-          std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
-          if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        } else {
-          if (PolicyAttrs & RVV_VTA)
-            Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
-        }
-        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(Ops.back()->getType()));
-        if (IsMasked) {
-          Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-          // maskedoff, op1, xlen, mask, vl
-          IntrinsicTypes = {ResultType,
-                            Ops[1]->getType(),
-                            Ops[4]->getType(),
-                            Ops[4]->getType()};
-        } else {
-          // passthru, op1, xlen, vl
-          IntrinsicTypes = {ResultType,
-                  Ops[1]->getType(),
-                  Ops[3]->getType(),
-                  Ops[3]->getType()};
-        }
-        break;
-      }
+        return emitRVVPseudoVNCVTBuiltin(this, E, ReturnValue, ResultType, ID,
+                                         Ops, PolicyAttrs, IsMasked, SegInstSEW);
       }] in {
         foreach s_p = suffixes_prototypes in {
           def : RVVBuiltin<s_p[0], s_p[1], type_range>;
@@ -575,17 +404,8 @@ let HasBuiltinAlias = false, HasVL = false, HasMasked = false,
     UnMaskedPolicyScheme = NonePolicy, MaskedPolicyScheme = NonePolicy,
     Log2LMUL = [0], IRName = "",
     ManualCodegen = [{
-    {
-      LLVMContext &Context = CGM.getLLVMContext();
-      llvm::MDBuilder MDHelper(Context);
-
-      llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "vlenb")};
-      llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
-      llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
-      llvm::Function *F =
-        CGM.getIntrinsic(llvm::Intrinsic::read_register, {SizeTy});
-      return Builder.CreateCall(F, Metadata);
-    }
+      return emitRVVVlenbBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                 PolicyAttrs, IsMasked, SegInstSEW);
     }] in
 {
   def vlenb : RVVBuiltin<"", "u", "i">;
@@ -660,7 +480,10 @@ let HasBuiltinAlias = false,
     HasMasked = false,
     MaskedPolicyScheme = NonePolicy,
     Log2LMUL = [0],
-    ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
+    ManualCodegen = [{
+      return emitRVVVsetvliBuiltin(this, E, ReturnValue, ResultType, ID, Ops,
+                                   PolicyAttrs, IsMasked, SegInstSEW);
+    }] in // Set XLEN type
 {
   def vsetvli : RVVBuiltin<"", "zzKzKz", "i">;
   def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">;
@@ -720,43 +543,10 @@ multiclass RVVUnitStridedSegLoadTuple<string op> {
             MaskedIRName = op # nf # "_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 6> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
-
-      if (IsMasked)
-        IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(), Ops.back()->getType()};
-      else
-        IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType()};
-
-      if (NoPassthru) { // Push poison into passthru
-        Operands.push_back(llvm::PoisonValue::get(ResultType));
-      } else { // Push intrinsics operands into passthru
-        llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0];
-        Operands.push_back(PassthruOperand);
-      }
-
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 1]); // VL
-      if (IsMasked)
-        Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-
-      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
-      if (ReturnValue.isNull())
-        return LoadValue;
-      else
-        return Builder.CreateStore(LoadValue, ReturnValue.getValue());
-    }
-    }] in {
+              return emitRVVUnitStridedSegLoadTupleBuiltin(
+                  this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs,
+                  IsMasked, SegInstSEW);
+            }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", T # "vPCe", type>;
         if !not(IsFloat<type>.val) then {
@@ -784,31 +574,10 @@ multiclass RVVUnitStridedSegStoreTuple<string op> {
           NF = nf,
           HasMaskedOffOperand = false,
           ManualCodegen = [{
-    {
-      // Masked
-      // Builtin: (mask, ptr, v_tuple, vl)
-      // Intrinsic: (tuple, ptr, mask, vl)
-      // Unmasked
-      // Builtin: (ptr, v_tuple, vl)
-      // Intrinsic: (tuple, ptr, vl)
-      unsigned Offset = IsMasked ? 1 : 0;
-
-      SmallVector<llvm::Value*, 5> Operands;
-      Operands.push_back(Ops[Offset + 1]); // tuple
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 2]); // VL
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      if (IsMasked)
-        IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Ops[0]->getType(), Operands.back()->getType()};
-      else
-        IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Operands.back()->getType()};
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-      return Builder.CreateCall(F, Operands, "");
-   }
-      }] in {
+            return emitRVVUnitStridedSegStoreTupleBuiltin(
+                this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs,
+                IsMasked, SegInstSEW);
+          }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", "0Pe" # T # "v", type>;
         if !not(IsFloat<type>.val) then {
@@ -835,52 +604,9 @@ multiclass RVVUnitStridedSegLoadFFTuple<string op> {
             MaskedIRName = op # nf # "ff_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 6> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
-
-      if (IsMasked)
-        IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(), Ops[0]->getType()};
-      else
-        IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType()};
-
-      if (NoPassthru) { // Push poison into passthru
-        Operands.push_back(llvm::PoisonValue::get(ResultType));
-      } else { // Push intrinsics operands into passthru
-        llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0];
-        Operands.push_back(PassthruOperand);
-      }
-
-      Operands.push_back(Ops[Offset]); // Ptr
-      if (IsMasked)
-        Operands.push_back(Ops[0]);
-      Operands.push_back(Ops[Offset + 2]); // vl
-      if (IsMasked)
-        Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
-      Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
-
-      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
-
-      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
-      // Get alignment from the new vl operand
-      clang::CharUnits Align =
-          CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType());
-
-      llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0);
-
-      // Store new_vl
-      llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1);
-      Builder.CreateStore(V, Address(Ops[Offset + 1], V->getType(), Align));
-
-      if (ReturnValue.isNull())
-        return ReturnTuple;
-      else
-        return Builder.CreateStore(ReturnTuple, ReturnValue.getValue());
-    }
+      return emitRVVUnitStridedSegLoadFFTupleBuiltin(
+          this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked,
+          SegInstSEW);
     }] in {
         defvar T = "(Tuple:" # nf # ")";
         def : RVVBuiltin<T # "v", T # "vPCePz", type>;
@@ -908,43 +634,9 @@ multiclass RVVStridedSegLoadTuple<string op> {
             MaskedIRName = op # nf # "_mask",
             NF = nf,
             ManualCodegen = [{
-    {
-      SmallVector<llvm::Value*, 7> Operands;
-
-      bool NoPassthru =
-        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
-        (!IsMasked && (PolicyAttrs & RVV_VTA));
-      unsigned Offset = IsMasked ...
[truncated]

@compnerd compnerd requested a review from tru September 12, 2025 01:36
@nikic nikic added this to the LLVM 21.x Release milestone Sep 12, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Sep 12, 2025
@nikic nikic changed the title 🍒 [RISCV] Reduce RISCV code generation build time release/21.x: [RISCV] Reduce RISCV code generation build time Sep 12, 2025
@nikic nikic requested a review from topperc September 12, 2025 07:39
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-project-automation github-project-automation bot moved this from Needs Triage to Needs Merge in LLVM Release Status Sep 12, 2025
@Steelskin
Copy link
Contributor Author

Steelskin commented Sep 15, 2025

I do not know what this error means or how to fix it:

error: Expected version 21.1.2 but found version 21.1.1

@compnerd
Copy link
Member

I do not know what this error means or how to fix it:

error: Expected version 21.1.2 but found version 21.1.1

This just needs to be updated in CMakeLists.txt

@Steelskin Steelskin force-pushed the fabrice/cp-upstream-21-riscv-compile branch from fe69a8e to 422f4e8 Compare September 16, 2025 18:57
@llvmbot llvmbot added the cmake Build system in general and CMake in particular label Sep 16, 2025
@Steelskin
Copy link
Contributor Author

This just needs to be updated in CMakeLists.txt

Thanks, I think I updated the right thing.

@Steelskin
Copy link
Contributor Author

This landed on the Swift side, so closing.

@Steelskin Steelskin closed this Sep 22, 2025
@Steelskin
Copy link
Contributor Author

Re-opening per @compnerd suggestion. I do not know what to do to get this landed here.

@Steelskin Steelskin reopened this Sep 22, 2025
@github-project-automation github-project-automation bot moved this from Needs Merge to Needs Triage in LLVM Release Status Sep 22, 2025
@tstellar tstellar moved this from Needs Triage to Needs Merge in LLVM Release Status Sep 23, 2025
topperc and others added 3 commits September 22, 2025 18:05
Operate directly on the existing Ops vector instead of copying to
a new vector. This is similar to what the autogenerated codegen
does for other intrinsics.

This reduced the clang binary size by ~96kb on my local Release+Asserts
build.
Operate directly on the existing Ops vector instead of copying to
a new vector. This is similar to what the autogenerated codegen
does for other intrinsics.
…ime [NFC] (llvm#154906)

Extract ManualCodegen blocks from riscv_vector.td to dedicated helper
functions in RISCV.cpp to improve compilation times and code
organization.

This refactoring:
- Reduces riscv_vector_builtin_cg.inc from ~70,000 lines to ~30,000
lines
- Extracts lots of ManualCodegen blocks into helper functions in
RISCV.cpp
- Moves complex code generation logic from TableGen to C++
- Marks extracted functions with LLVM_ATTRIBUTE_NOINLINE to prevent
excessive inlining in EmitRISCVBuiltinExpr's large switch statement,
which would cause compilation time to increase significantly

Performance Impact on AMD Ryzen 9 3950X 16-Core with SSD (Release build)
with GCC 11:

Before: real 1m4.560s, user 0m0.529s, sys 0m0.175s
After:  real 0m22.577s, user 0m0.498s, sys 0m0.152s

Which reduced around 65% of compilation time.

During this refactoring, I also found few more opportunities to optimize
and simplify the code generation logic, but I think leave to next PR
since it already change a lot of code.

Fix llvm#88368
@tstellar tstellar force-pushed the fabrice/cp-upstream-21-riscv-compile branch from 422f4e8 to 77a3b0e Compare September 23, 2025 01:06
@Steelskin
Copy link
Contributor Author

@tstellar If we're all good, can you land it, please?

@tstellar tstellar merged commit 77a3b0e into llvm:release/21.x Sep 23, 2025
13 checks passed
@github-project-automation github-project-automation bot moved this from Needs Merge to Done in LLVM Release Status Sep 23, 2025
Copy link

@Steelskin (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR.

@Steelskin Steelskin deleted the fabrice/cp-upstream-21-riscv-compile branch September 23, 2025 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category cmake Build system in general and CMake in particular

Projects

Development

Successfully merging this pull request may close these issues.

7 participants