[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-08-20 Thread Brandon Wu via cfe-commits

https://github.com/4vtomat closed 
https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-08-18 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-08-10 Thread Brandon Wu via cfe-commits

4vtomat wrote:

Gentle ping~

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-21 Thread Craig Topper via cfe-commits


@@ -244,6 +244,15 @@ ABIInfo::getOptimalVectorMemoryType(llvm::FixedVectorType 
*T,
   return T;
 }
 
+llvm::Value *ABIInfo::CreateCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
+CodeGenFunction &CGF) const {
+  return nullptr;
+}
+void ABIInfo::CreateCoercedStore(llvm::Value *Val, Address DstAddr,

topperc wrote:

Blank line between function definitions

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-12 Thread Brandon Wu via cfe-commits

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

>From e51b061b7231ccb990e74a313f7cea900faf34c5 Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Sun, 6 Jul 2025 00:42:02 -0700
Subject: [PATCH] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/include/clang/CodeGen/CGFunctionInfo.h  |  46 -
 clang/lib/CodeGen/ABIInfo.cpp |   9 +
 clang/lib/CodeGen/ABIInfo.h   |   6 +
 clang/lib/CodeGen/CGCall.cpp  |  71 +--
 clang/lib/CodeGen/TargetInfo.cpp  |   7 +
 clang/lib/CodeGen/Targets/RISCV.cpp   | 181 +-
 clang/lib/CodeGen/Targets/Sparc.cpp   |   1 +
 clang/lib/CodeGen/Targets/X86.cpp |   1 +
 clang/lib/CodeGen/Targets/XCore.cpp   |   1 +
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  |  93 +++--
 .../riscv-vector-callingconv-llvm-ir.cpp  |  32 ++--
 11 files changed, 394 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h 
b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 50be51769f1a8..d469efc8b431d 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -77,6 +77,10 @@ class ABIArgInfo {
 /// Array elements in the type are assumed to be padding and skipped.
 CoerceAndExpand,
 
+/// TargetSpecific - Some argument types are passed as target specific 
types
+/// such as RISCV's tuple type, these need to be handled in the target 
hook.
+TargetSpecific,
+
 /// InAlloca - Pass the argument directly using the LLVM inalloca 
attribute.
 /// This is similar to indirect with byval, except it only applies to
 /// arguments stored in memory and forbids any implicit copies.  When
@@ -120,7 +124,7 @@ class ABIArgInfo {
 
   bool canHavePaddingType() const {
 return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
-   isExpand();
+   isExpand() || isTargetSpecific();
   }
   void setPaddingType(llvm::Type *T) {
 assert(canHavePaddingType());
@@ -291,6 +295,20 @@ class ABIArgInfo {
 return AI;
   }
 
+  static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
+  unsigned Offset = 0,
+  llvm::Type *Padding = nullptr,
+  bool CanBeFlattened = true,
+  unsigned Align = 0) {
+auto AI = ABIArgInfo(TargetSpecific);
+AI.setCoerceToType(T);
+AI.setPaddingType(Padding);
+AI.setDirectOffset(Offset);
+AI.setDirectAlign(Align);
+AI.setCanBeFlattened(CanBeFlattened);
+return AI;
+  }
+
   static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
 return eltType->isArrayTy() &&
eltType->getArrayElementType()->isIntegerTy(8);
@@ -305,27 +323,33 @@ class ABIArgInfo {
   bool isIndirectAliased() const { return TheKind == IndirectAliased; }
   bool isExpand() const { return TheKind == Expand; }
   bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
+  bool isTargetSpecific() const { return TheKind == TargetSpecific; }
 
   bool canHaveCoerceToType() const {
-return isDirect() || isExtend() || isCoerceAndExpand();
+return isDirect() || isExtend() || isCoerceAndExpand() ||
+   isTargetSpecific();
   }
 
   // Direct/Extend accessors
   unsigned getDirectOffset() const {
-assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+assert((isDirect() || isExtend() || isTargetSpecific()) &&
+   "Not a direct or extend or target specific kind");
 return DirectAttr.Offset;
   }
   void setDirectOffset(unsigned Offset) {
-assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+assert((isDirect() || isExtend() || isTargetSpecific()) &&
+   "Not a direct or extend or target specific kind");
 DirectAttr.Offset = Offset;
   }
 
   unsigned getDirectAlign() const {
-assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+assert((isDirect() || isExtend() || isTargetSpecific()) &&
+   "Not a direct or extend or target specific kind");
 return DirectAttr.Align;
   }
   void setDirectAlign(unsigned Align) {
-assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+assert((isDirect() || isExtend() || isTargetSpecific()) &&
+   "Not a direct or extend or target specific kind");
 DirectAttr.Align = Align;
   }
 
@@ -394,12 +418,14 @@ class ABIArgInfo {
   }
 
   bool getInReg() const {
-assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
+   "Invalid kind!");
 return InReg;
   }
 
  

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-10 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic commented:

I'm not really happy with the way the code is organized for "coerced" 
load/store involving scalable types.

At the point where we're analyzing the calling convention; we have a bunch of 
information: exactly what kind of coercion we're doing, whether the sizes 
match, whether there are any unusual types involved.  We're throwing away that 
information, and then trying to re-derive it later.

So I think:

- The target code should compute whether the sizes are guaranteed to match.  If 
they do, "coerced" load/store simplifies to just a plain load/store, and we can 
skip all these complicated computations involving the sizes of the 
source/destination.
- If some types need target-specific code to lower arguments, that should be 
its own ABIArgInfo::Kind, and the target-independent code should call into a 
target-specific implementation in clang/lib/CodeGen/Targets/RISCV.cpp.

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-06 Thread Brandon Wu via cfe-commits

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

>From 88d1184bf6c8ac71c3a80a402e7e0122aad2bf52 Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Sun, 6 Jul 2025 00:42:02 -0700
Subject: [PATCH] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/lib/CodeGen/CGCall.cpp  | 167 --
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  |  93 --
 .../riscv-vector-callingconv-llvm-ir.cpp  |  32 ++--
 3 files changed, 246 insertions(+), 46 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c8c3d6b20c496..f93862f7407d2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -41,6 +41,7 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include 
@@ -1329,9 +1330,77 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
-Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
- DstSize.getFixedValue(), CGF);
-SrcTy = Src.getElementType();
+if (llvm::TargetExtType *TupTy = dyn_cast(Ty)) {
+  // In RISC-V VLS calling convention, struct of fixed vectors or struct of
+  // array of fixed vector of length >1 might be lowered using vector tuple
+  // type, we consider it as a valid load, e.g.
+  // struct i32x4x2 {
+  // __attribute__((vector_size(16))) int i;
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // or
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i[2];
+  // };
+  // is lowered to target("riscv.vector.tuple", , 2)
+  // when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  assert(TupTy->getName() == "riscv.vector.tuple");
+  llvm::Type *EltTy = TupTy->getTypeParameter(0);
+  unsigned NumElts = TupTy->getIntParameter(0);
+
+  if (auto *ArrayTy = dyn_cast(SrcSTy->getElementType(0)))
+Src = Src.withElementType(ArrayTy);
+
+  // Perform extract element and load
+  llvm::Value *PoisonTuple = llvm::PoisonValue::get(Ty);
+  auto *Load = CGF.Builder.CreateLoad(Src);
+  for (unsigned i = 0; i < NumElts; ++i) {
+// Extract from struct
+llvm::Value *ExtractFromLoad = CGF.Builder.CreateExtractValue(Load, i);
+// Element in vector tuple type is always i8, so we need to cast back 
to
+// it's original element type.
+EltTy = cast(
+llvm::VectorType::getWithSizeAndScalar(
+cast(EltTy), ExtractFromLoad->getType()));
+llvm::Value *PoisonVec = llvm::PoisonValue::get(EltTy);
+// Insert to scalable vector
+PoisonVec = CGF.Builder.CreateInsertVector(
+EltTy, PoisonVec, ExtractFromLoad, uint64_t(0), "cast.scalable");
+// Insert scalable vector to vector tuple
+llvm::Value *Idx = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), i);
+PoisonTuple = CGF.Builder.CreateIntrinsic(
+llvm::Intrinsic::riscv_tuple_insert, {Ty, EltTy},
+{PoisonTuple, PoisonVec, Idx});
+  }
+  return PoisonTuple;
+}
+
+if (Ty->isScalableTy()) {
+  // In RISC-V VLS calling convention, struct of fixed vector or struct of
+  // fixed vector array of length 1 might be lowered using scalable vector,
+  // we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // or
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i[1];
+  // };
+  // is lowered to 
+  // when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  SrcTy = SrcSTy->getElementType(0);
+  if (auto *ArrayTy = dyn_cast(SrcTy))
+SrcTy = ArrayTy->getElementType();
+  Src = Src.withElementType(SrcTy);
+} else {
+  Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
+   DstSize.getFixedValue(), CGF);
+  SrcTy = Src.getElementType();
+}
   }
 
   llvm::TypeSize SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -1412,6 +1481,87 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (llvm::TargetExtType

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-06 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff HEAD~1 HEAD --extensions cpp,c -- 
clang/lib/CodeGen/CGCall.cpp 
clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c 
clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index bc7698e64..70123b2c1 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1482,10 +1482,9 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
   if (llvm::TargetExtType *TupTy = dyn_cast(SrcTy)) {
-// In RISC-V VLS calling convention, struct of fixed vectors or struct 
of
-// array of fixed vector of length >1 might be lowered using vector 
tuple
-// type, we consider it as a valid load, e.g.
-// struct i32x4x2 {
+// In RISC-V VLS calling convention, struct of fixed vectors or struct
+// of array of fixed vector of length >1 might be lowered using vector
+// tuple type, we consider it as a valid load, e.g. struct i32x4x2 {
 // __attribute__((vector_size(16))) int i;
 // __attribute__((vector_size(16))) int i;
 // };
@@ -1537,9 +1536,8 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 
   if (SrcTy->isScalableTy()) {
 // In RISC-V VLS calling convention, struct of fixed vector or struct 
of
-// fixed vector array of length 1 might be lowered using scalable 
vector,
-// we consider it as a valid load, e.g.
-// struct i32x4 {
+// fixed vector array of length 1 might be lowered using scalable
+// vector, we consider it as a valid load, e.g. struct i32x4 {
 // __attribute__((vector_size(16))) int i;
 // };
 // or

``




https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-06 Thread Brandon Wu via cfe-commits

https://github.com/4vtomat edited 
https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-07-06 Thread Brandon Wu via cfe-commits

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

>From 8b90033dd07ec2256f26670a43a0f713cc7b84ef Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Sun, 6 Jul 2025 00:42:02 -0700
Subject: [PATCH] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/lib/CodeGen/CGCall.cpp  | 167 --
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  |  93 --
 .../riscv-vector-callingconv-llvm-ir.cpp  |  32 ++--
 3 files changed, 246 insertions(+), 46 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c8c3d6b20c496..bc7698e648027 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -41,6 +41,7 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include 
@@ -1329,9 +1330,77 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
-Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
- DstSize.getFixedValue(), CGF);
-SrcTy = Src.getElementType();
+if (llvm::TargetExtType *TupTy = dyn_cast(Ty)) {
+  // In RISC-V VLS calling convention, struct of fixed vectors or struct of
+  // array of fixed vector of length >1 might be lowered using vector tuple
+  // type, we consider it as a valid load, e.g.
+  // struct i32x4x2 {
+  // __attribute__((vector_size(16))) int i;
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // or
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i[2];
+  // };
+  // is lowered to target("riscv.vector.tuple", , 2)
+  // when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  assert(TupTy->getName() == "riscv.vector.tuple");
+  llvm::Type *EltTy = TupTy->getTypeParameter(0);
+  unsigned NumElts = TupTy->getIntParameter(0);
+
+  if (auto *ArrayTy = dyn_cast(SrcSTy->getElementType(0)))
+Src = Src.withElementType(ArrayTy);
+
+  // Perform extract element and load
+  llvm::Value *PoisonTuple = llvm::PoisonValue::get(Ty);
+  auto *Load = CGF.Builder.CreateLoad(Src);
+  for (unsigned i = 0; i < NumElts; ++i) {
+// Extract from struct
+llvm::Value *ExtractFromLoad = CGF.Builder.CreateExtractValue(Load, i);
+// Element in vector tuple type is always i8, so we need to cast back 
to
+// it's original element type.
+EltTy = cast(
+llvm::VectorType::getWithSizeAndScalar(
+cast(EltTy), ExtractFromLoad->getType()));
+llvm::Value *PoisonVec = llvm::PoisonValue::get(EltTy);
+// Insert to scalable vector
+PoisonVec = CGF.Builder.CreateInsertVector(
+EltTy, PoisonVec, ExtractFromLoad, uint64_t(0), "cast.scalable");
+// Insert scalable vector to vector tuple
+llvm::Value *Idx = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), i);
+PoisonTuple = CGF.Builder.CreateIntrinsic(
+llvm::Intrinsic::riscv_tuple_insert, {Ty, EltTy},
+{PoisonTuple, PoisonVec, Idx});
+  }
+  return PoisonTuple;
+}
+
+if (Ty->isScalableTy()) {
+  // In RISC-V VLS calling convention, struct of fixed vector or struct of
+  // fixed vector array of length 1 might be lowered using scalable vector,
+  // we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // or
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i[1];
+  // };
+  // is lowered to 
+  // when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  SrcTy = SrcSTy->getElementType(0);
+  if (auto *ArrayTy = dyn_cast(SrcTy))
+SrcTy = ArrayTy->getElementType();
+  Src = Src.withElementType(SrcTy);
+} else {
+  Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
+   DstSize.getFixedValue(), CGF);
+  SrcTy = Src.getElementType();
+}
   }
 
   llvm::TypeSize SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -1412,6 +1481,87 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (llvm::TargetExtType

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-27 Thread Brandon Wu via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-27 Thread Craig Topper via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-26 Thread Brandon Wu via cfe-commits

https://github.com/4vtomat edited 
https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-26 Thread Brandon Wu via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Craig Topper via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Brandon Wu via cfe-commits

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

>From 5d4fb54e6ee61c258d4fb1a5ecb00021addbd471 Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Tue, 24 Jun 2025 02:46:21 -0700
Subject: [PATCH 1/2] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/lib/CodeGen/CGCall.cpp  | 39 
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 62 ++-
 .../riscv-vector-callingconv-llvm-ir.cpp  | 32 +-
 3 files changed, 90 insertions(+), 43 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
a

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Craig Topper via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Brandon Wu via cfe-commits

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

>From 5d4fb54e6ee61c258d4fb1a5ecb00021addbd471 Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Tue, 24 Jun 2025 02:46:21 -0700
Subject: [PATCH 1/3] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/lib/CodeGen/CGCall.cpp  | 39 
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 62 ++-
 .../riscv-vector-callingconv-llvm-ir.cpp  | 32 +-
 3 files changed, 90 insertions(+), 43 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
a

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Brandon Wu via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Craig Topper via cfe-commits


@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be

topperc wrote:

```suggestion
  // In RISC-V VLS calling convention, struct of fixed vector might be
```

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Craig Topper via cfe-commits


@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be

topperc wrote:

```suggestion
// In RISC-V VLS calling convention, struct of fixed vector might be
```

https://github.com/llvm/llvm-project/pull/145489
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Brandon Wu via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread via cfe-commits

llvmbot wrote:




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

Author: Brandon Wu (4vtomat)


Changes

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.


---
Full diff: https://github.com/llvm/llvm-project/pull/145489.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+28-11) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c 
(+46-16) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp 
(+16-16) 


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Pengcheng Wang via cfe-commits


@@ -143,52 +143,82 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct 
st_i32x4_arr1 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct 
st_i32x4_arr4 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr8( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr8_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct 
st_i32x4_arr8 arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x2(target("riscv.vector.tuple", , 2) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 
arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x8x2(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) 
%arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 
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(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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg.coerce)
 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", , 3) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4x3_256(target("riscv.vector.tuple", , 3) 
%arg.coerce)
 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", , 8) %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4x8(target("riscv.vector.tuple", , 8) %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struc

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Brandon Wu (4vtomat)


Changes

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.


---
Full diff: https://github.com/llvm/llvm-project/pull/145489.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+28-11) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c 
(+46-16) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp 
(+16-16) 


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define 

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Brandon Wu (4vtomat)


Changes

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.


---
Full diff: https://github.com/llvm/llvm-project/pull/145489.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+28-11) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c 
(+46-16) 
- (modified) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp 
(+16-16) 


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 
arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_arr1_256( %arg)
+// CHECK-LLVM: define dso_loca

[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)

2025-06-24 Thread Brandon Wu via cfe-commits

https://github.com/4vtomat created 
https://github.com/llvm/llvm-project/pull/145489

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.


>From 5d4fb54e6ee61c258d4fb1a5ecb00021addbd471 Mon Sep 17 00:00:00 2001
From: Brandon Wu 
Date: Tue, 24 Jun 2025 02:46:21 -0700
Subject: [PATCH] [clang][RISCV] Fix crash on VLS calling convention

This patch handle struct of fixed vector and struct of array of fixed
vector correctly for VLS calling convention in EmitFunctionProlog,
EmitFunctionEpilog and EmitCall.
---
 clang/lib/CodeGen/CGCall.cpp  | 39 
 .../RISCV/riscv-vector-callingconv-llvm-ir.c  | 62 ++-
 .../riscv-vector-callingconv-llvm-ir.cpp  | 32 +-
 3 files changed, 90 insertions(+), 43 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index fd75de42515da..46182f9f418c2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1329,6 +1329,19 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
   llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
 
   if (llvm::StructType *SrcSTy = dyn_cast(SrcTy)) {
+if (Ty->isScalableTy() || Ty->isRISCVVectorTupleTy()) {
+  // In RISCV VLS calling convention, struct of fixed vector might be
+  // lowered using scalable vector, we consider it as a valid load, e.g.
+  // struct i32x4 {
+  // __attribute__((vector_size(16))) int i;
+  // };
+  // is lowered to
+  //  when ABI_VLEN = 128 bits, please checkout
+  // clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+  // for more information.
+  Src = Src.withElementType(Ty);
+  return CGF.Builder.CreateLoad(Src);
+}
 Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
  DstSize.getFixedValue(), CGF);
 SrcTy = Src.getElementType();
@@ -1412,6 +1425,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   if (SrcTy != Dst.getElementType()) {
 if (llvm::StructType *DstSTy =
 dyn_cast(Dst.getElementType())) {
+  if (SrcTy->isScalableTy() || SrcTy->isRISCVVectorTupleTy()) {
+// In RISCV VLS calling convention, struct of fixed vector might be
+// lowered using scalable vector, we consider it as a valid load, e.g.
+// struct i32x4 {
+// __attribute__((vector_size(16))) int i;
+// };
+// is lowered to
+//  when ABI_VLEN = 128 bits, please checkout
+// clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+// for more information.
+Dst = Dst.withElementType(SrcTy);
+auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+addInstToCurrentSourceAtom(I, Src);
+return;
+  }
   assert(!SrcSize.isScalable());
   Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
SrcSize.getFixedValue(), *this);
@@ -3328,17 +3356,6 @@ 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(ConvertType(Ty)) &&
-  (isa(ArgI.getCoerceToType()) ||
-   isa(ArgI.getCoerceToType( {
-ArgVals.push_back(ParamValue::forDirect(AI));
-break;
-  }
-
   llvm::StructType *STy =
   dyn_cast(ArgI.getCoerceToType());
   Address Alloca =
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 3044d91f1c31c..5799c6bd811b0 100644
--- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -143,34 +143,34 @@ void __attribute__((riscv_vls_cc)) 
test_too_large(int32x64_t arg) {}
 // CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_too_large_256( noundef %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4( %arg.coerce)
 void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}
-// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg)
+// CHECK-LLVM: define dso_local riscv_vls_cc(256) void 
@test_st_i32x4_256( %arg.coerce)
 void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) 
{}
 
-// CHECK-LLVM: define dso_local riscv_vls_cc(128) void 
@test_st_i32x4_arr1( %arg)
+