[clang] [clang][RISCV] Fix crash on VLS calling convention (PR #145489)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
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)
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)
+
