[clang] added regcall struct by reg support (PR #95257)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 12 07:45:35 PDT 2024
https://github.com/mahesh-attarde created https://github.com/llvm/llvm-project/pull/95257
In Context of __regcall,
Whenever struct can fit in a register we must use single register to pass whole struct object.
Without this patch, it uses separate registers for each field. With Patch, if Struct size is <= 64
we can use GPR.
>From 6d6619f8f7a37906ac45791487a4d63b51a48ad1 Mon Sep 17 00:00:00 2001
From: mahesh-attarde <mahesh.attarde at intel.com>
Date: Wed, 12 Jun 2024 06:15:51 -0700
Subject: [PATCH] added regcall strct by reg support
---
clang/lib/CodeGen/Targets/X86.cpp | 20 ++++++++++++
clang/test/CodeGen/regcall3.c | 53 +++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 clang/test/CodeGen/regcall3.c
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 43dadf5e724ac..506d106ad65b0 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -148,6 +148,7 @@ class X86_32ABIInfo : public ABIInfo {
Class classify(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
+
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State,
unsigned ArgIndex) const;
@@ -1306,6 +1307,8 @@ class X86_64ABIInfo : public ABIInfo {
unsigned &NeededSSE,
unsigned &MaxVectorWidth) const;
+ bool DoesRegcallStructFitInReg(QualType Ty) const;
+
bool IsIllegalVectorType(QualType Ty) const;
/// The 0.98 ABI revision clarified a lot of ambiguities,
@@ -2830,6 +2833,20 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs,
return ABIArgInfo::getDirect(ResType);
}
+bool X86_64ABIInfo::DoesRegcallStructFitInReg(QualType Ty) const {
+ auto RT = Ty->castAs<RecordType>();
+ // For Integer class, Max GPR Size is 64
+ if (getContext().getTypeSize(Ty) > 64)
+ return false;
+ // Struct At hand must not have other non Builtin types
+ for (const auto *FD : RT->getDecl()->fields()) {
+ QualType MTy = FD->getType();
+ if (!MTy->isBuiltinType())
+ return false;
+ }
+ return true;
+}
+
ABIArgInfo
X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
unsigned &NeededSSE,
@@ -2837,6 +2854,9 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
auto RT = Ty->getAs<RecordType>();
assert(RT && "classifyRegCallStructType only valid with struct types");
+ if (DoesRegcallStructFitInReg(Ty))
+ return classifyArgumentType(Ty, UINT_MAX, NeededInt, NeededSSE, true, true);
+
if (RT->getDecl()->hasFlexibleArrayMember())
return getIndirectReturnResult(Ty);
diff --git a/clang/test/CodeGen/regcall3.c b/clang/test/CodeGen/regcall3.c
new file mode 100644
index 0000000000000..1c83407220861
--- /dev/null
+++ b/clang/test/CodeGen/regcall3.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -S %s -o - -ffreestanding -triple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=LINUX64
+
+#include <xmmintrin.h>
+struct struct1 { int x; int y; };
+void __regcall v6(int a, float b, struct struct1 c) {}
+
+void v6_caller(){
+ struct struct1 c0;
+ c0.x = 0xa0a0; c0.y = 0xb0b0;
+ int x= 0xf0f0, y = 0x0f0f;
+ v6(x,y,c0);
+}
+
+// LINUX64-LABEL: __regcall3__v6
+// LINUX64: movq %rcx, -8(%rsp)
+// LINUX64: movl %eax, -12(%rsp)
+// LINUX64: movss %xmm0, -16(%rsp)
+
+// LINUX64-LABEL: v6_caller
+// LINUX64: movl $41120, 16(%rsp) # imm = 0xA0A0
+// LINUX64: movl $45232, 20(%rsp) # imm = 0xB0B0
+// LINUX64: movl $61680, 12(%rsp) # imm = 0xF0F0
+// LINUX64: movl $3855, 8(%rsp) # imm = 0xF0F
+// LINUX64: movl 12(%rsp), %eax
+// LINUX64: cvtsi2ssl 8(%rsp), %xmm0
+// LINUX64: movq 16(%rsp), %rcx
+// LINUX64: callq .L__regcall3__v6$local
+
+
+struct struct2 { int x; float y; };
+void __regcall v31(int a, float b, struct struct2 c) {}
+
+void v31_caller(){
+ struct struct2 c0;
+ c0.x = 0xa0a0; c0.y = 0xb0b0;
+ int x= 0xf0f0, y = 0x0f0f;
+ v31(x,y,c0);
+}
+
+// LINUX64: __regcall3__v31: # @__regcall3__v31
+// LINUX64: movq %rcx, -8(%rsp)
+// LINUX64: movl %eax, -12(%rsp)
+// LINUX64: movss %xmm0, -16(%rsp)
+// LINUX64: v31_caller: # @v31_caller
+// LINUX64: movl $41120, 16(%rsp) # imm = 0xA0A0
+// LINUX64: movss .LCPI3_0(%rip), %xmm0 # xmm0 = [4.5232E+4,0.0E+0,0.0E+0,0.0E+0]
+// LINUX64: movss %xmm0, 20(%rsp)
+// LINUX64: movl $61680, 12(%rsp) # imm = 0xF0F0
+// LINUX64: movl $3855, 8(%rsp) # imm = 0xF0F
+// LINUX64: movl 12(%rsp), %eax
+// LINUX64: cvtsi2ssl 8(%rsp), %xmm0
+// LINUX64: movq 16(%rsp), %rcx
+// LINUX64: callq .L__regcall3__v31$local
More information about the cfe-commits
mailing list