https://github.com/doac updated https://github.com/llvm/llvm-project/pull/222264

>From 40bfa1c590f7a08a85f9a968d9a556f32f58e1e4 Mon Sep 17 00:00:00 2001
From: Daniel Cederman <[email protected]>
Date: Mon, 17 Aug 2026 07:11:06 +0200
Subject: [PATCH 1/2] [Sparc][clang] Match GCC's SPARC V8 vector return
 convention

Match GCC's SPARC V8 calling convention for vector return values.
Return floating-point vectors and vectors larger than 64 bits indirectly.
Return smaller integer vectors in floating-point registers.

Assisted-by: Codex
---
 clang/lib/CodeGen/Targets/Sparc.cpp    | 11 ++++
 clang/test/CodeGen/Sparc/sparcv8-abi.c | 76 +++++++++++++++++++++++++-
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index f5a17aa51184a..09663661bacce 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -71,6 +71,17 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) 
const {
   if (const auto *CT = Ty->getAs<ComplexType>())
     return classifyComplexType(CT, /*IsRet=*/true);
 
+  if (const auto *VT = Ty->getAs<VectorType>()) {
+    uint64_t Size = getContext().getTypeSize(Ty);
+    if (VT->getElementType()->isRealFloatingType() || Size > 64)
+      return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+
+    llvm::Type *FloatTy = llvm::Type::getFloatTy(getVMContext());
+    llvm::Type *CoerceTy =
+        Size <= 32 ? FloatTy : llvm::StructType::get(FloatTy, FloatTy);
+    return ABIArgInfo::getDirect(CoerceTy);
+  }
+
   if (const auto *BT = Ty->getAs<BuiltinType>();
       BT && BT->getKind() == BuiltinType::LongDouble)
     return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
diff --git a/clang/test/CodeGen/Sparc/sparcv8-abi.c 
b/clang/test/CodeGen/Sparc/sparcv8-abi.c
index 7beddd20e5e4d..1aa2687f14f39 100644
--- a/clang/test/CodeGen/Sparc/sparcv8-abi.c
+++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c
@@ -1,4 +1,4 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --filter "^define |^entry:" --version 6
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --filter "^define |^entry:|call .*@return_" --version 6
 // RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | 
FileCheck %s
 
 float __complex__
@@ -50,3 +50,77 @@ t(long double _Complex a)
 {
     return 0;
 }
+
+typedef char v4i8 __attribute__((vector_size(4)));
+typedef char v8i8 __attribute__((vector_size(8)));
+typedef char v16i8 __attribute__((vector_size(16)));
+typedef float v1f32 __attribute__((vector_size(4)));
+typedef double v1f64 __attribute__((vector_size(8)));
+
+// Integer vectors of at most eight bytes are returned in floating-point
+// registers. Larger integer vectors and all floating-point vectors are
+// returned indirectly.
+// CHECK-LABEL: define dso_local float @return_v4i8(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v4i8 return_v4i8(int x) { return (v4i8){x, x, x, x}; }
+// CHECK-LABEL: define dso_local { float, float } @return_v8i8(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v8i8 return_v8i8(int x) { return (v8i8){x, x, x, x, x, x, x, x}; }
+// CHECK-LABEL: define dso_local void @return_v16i8(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 
[[AGG_RESULT:%.*]], i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v16i8 return_v16i8(int x) {
+  return (v16i8){x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x};
+}
+// CHECK-LABEL: define dso_local void @return_v1f32(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(<1 x float>) align 4 
[[AGG_RESULT:%.*]], float noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v1f32 return_v1f32(float x) { return (v1f32){x}; }
+// CHECK-LABEL: define dso_local void @return_v1f64(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(<1 x double>) align 8 
[[AGG_RESULT:%.*]], double noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v1f64 return_v1f64(double x) { return (v1f64){x}; }
+
+volatile v4i8 v4i8_result;
+volatile v8i8 v8i8_result;
+volatile v16i8 v16i8_result;
+volatile v1f32 v1f32_result;
+volatile v1f64 v1f64_result;
+
+// CHECK-LABEL: define dso_local void @call_integer_vector_returns(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[CALL:%.*]] = call float @return_v4i8(i32 noundef 1)
+// CHECK:    [[CALL1:%.*]] = call { float, float } @return_v8i8(i32 noundef 1)
+// CHECK:    call void @return_v16i8(ptr dead_on_unwind writable sret(<16 x 
i8>) align 16 [[TMP:%.*]], i32 noundef 1)
+//
+void call_integer_vector_returns(void) {
+  v4i8_result = return_v4i8(1);
+  v8i8_result = return_v8i8(1);
+  v16i8_result = return_v16i8(1);
+}
+
+// CHECK-LABEL: define dso_local void @call_f32_vector_return(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    call void @return_v1f32(ptr dead_on_unwind writable sret(<1 x 
float>) align 4 [[TMP:%.*]], float noundef 1.000000e+00)
+//
+void call_f32_vector_return(void) {
+  v1f32_result = return_v1f32(1.0f);
+}
+
+// CHECK-LABEL: define dso_local void @call_f64_vector_return(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    call void @return_v1f64(ptr dead_on_unwind writable sret(<1 x 
double>) align 8 [[TMP:%.*]], double noundef 1.000000e+00)
+//
+void call_f64_vector_return(void) {
+  v1f64_result = return_v1f64(1.0);
+}

>From c34ee51571c92aae564f1078a0a6004425443c49 Mon Sep 17 00:00:00 2001
From: Daniel Cederman <[email protected]>
Date: Mon, 14 Sep 2026 08:22:04 +0200
Subject: [PATCH 2/2] [Sparc][clang] Match GCC's SPARC V8 vector return
 convention v2

Use double to return 64-bit integer vectors.
Add tests for v1i32, v2i32, and v4i16 variants.
---
 clang/lib/CodeGen/Targets/Sparc.cpp    |  5 +++--
 clang/test/CodeGen/Sparc/sparcv8-abi.c | 31 ++++++++++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index 09663661bacce..ee49f2a1f864f 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -76,9 +76,10 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) 
const {
     if (VT->getElementType()->isRealFloatingType() || Size > 64)
       return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
 
+    // Return smaller integer vectors via float registers.
     llvm::Type *FloatTy = llvm::Type::getFloatTy(getVMContext());
-    llvm::Type *CoerceTy =
-        Size <= 32 ? FloatTy : llvm::StructType::get(FloatTy, FloatTy);
+    llvm::Type *DoubleTy = llvm::Type::getDoubleTy(getVMContext());
+    llvm::Type *CoerceTy = Size <= 32 ? FloatTy : DoubleTy;
     return ABIArgInfo::getDirect(CoerceTy);
   }
 
diff --git a/clang/test/CodeGen/Sparc/sparcv8-abi.c 
b/clang/test/CodeGen/Sparc/sparcv8-abi.c
index 1aa2687f14f39..d2ba172377786 100644
--- a/clang/test/CodeGen/Sparc/sparcv8-abi.c
+++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c
@@ -54,6 +54,9 @@ t(long double _Complex a)
 typedef char v4i8 __attribute__((vector_size(4)));
 typedef char v8i8 __attribute__((vector_size(8)));
 typedef char v16i8 __attribute__((vector_size(16)));
+typedef int v1i32 __attribute__((vector_size(4)));
+typedef int v2i32 __attribute__((vector_size(8)));
+typedef short v4i16 __attribute__((vector_size(8)));
 typedef float v1f32 __attribute__((vector_size(4)));
 typedef double v1f64 __attribute__((vector_size(8)));
 
@@ -65,11 +68,26 @@ typedef double v1f64 __attribute__((vector_size(8)));
 // CHECK:  [[ENTRY:.*:]]
 //
 v4i8 return_v4i8(int x) { return (v4i8){x, x, x, x}; }
-// CHECK-LABEL: define dso_local { float, float } @return_v8i8(
+// CHECK-LABEL: define dso_local double @return_v8i8(
 // CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
 // CHECK:  [[ENTRY:.*:]]
 //
 v8i8 return_v8i8(int x) { return (v8i8){x, x, x, x, x, x, x, x}; }
+// CHECK-LABEL: define dso_local float @return_v1i32(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v1i32 return_v1i32(int x) { return (v1i32){x}; }
+// CHECK-LABEL: define dso_local double @return_v2i32(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v2i32 return_v2i32(int x) { return (v2i32){x, x}; }
+// CHECK-LABEL: define dso_local double @return_v4i16(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+//
+v4i16 return_v4i16(int x) { return (v4i16){x, x, x, x}; }
 // CHECK-LABEL: define dso_local void @return_v16i8(
 // CHECK-SAME: ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 
[[AGG_RESULT:%.*]], i32 noundef [[X:%.*]]) #[[ATTR0]] {
 // CHECK:  [[ENTRY:.*:]]
@@ -91,6 +109,9 @@ v1f64 return_v1f64(double x) { return (v1f64){x}; }
 volatile v4i8 v4i8_result;
 volatile v8i8 v8i8_result;
 volatile v16i8 v16i8_result;
+volatile v1i32 v1i32_result;
+volatile v2i32 v2i32_result;
+volatile v4i16 v4i16_result;
 volatile v1f32 v1f32_result;
 volatile v1f64 v1f64_result;
 
@@ -98,12 +119,18 @@ volatile v1f64 v1f64_result;
 // CHECK-SAME: ) #[[ATTR0]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[CALL:%.*]] = call float @return_v4i8(i32 noundef 1)
-// CHECK:    [[CALL1:%.*]] = call { float, float } @return_v8i8(i32 noundef 1)
+// CHECK:    [[CALL1:%.*]] = call double @return_v8i8(i32 noundef 1)
+// CHECK:    [[CALL3:%.*]] = call float @return_v1i32(i32 noundef 1)
+// CHECK:    [[CALL5:%.*]] = call double @return_v2i32(i32 noundef 1)
+// CHECK:    [[CALL7:%.*]] = call double @return_v4i16(i32 noundef 1)
 // CHECK:    call void @return_v16i8(ptr dead_on_unwind writable sret(<16 x 
i8>) align 16 [[TMP:%.*]], i32 noundef 1)
 //
 void call_integer_vector_returns(void) {
   v4i8_result = return_v4i8(1);
   v8i8_result = return_v8i8(1);
+  v1i32_result = return_v1i32(1);
+  v2i32_result = return_v2i32(1);
+  v4i16_result = return_v4i16(1);
   v16i8_result = return_v16i8(1);
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to