[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-07-17 Thread via cfe-commits

github-actions[bot] wrote:



@T0b1-iOS Congratulations on having your first Pull Request (PR) merged into 
the LLVM Project!

Your changes will be combined with recent changes from other authors, then 
tested by our [build bots](https://lab.llvm.org/buildbot/). If there is a 
problem with a build, you may receive a report in an email or a comment on this 
PR.

Please check whether problems have been caused by your change specifically, as 
the builds can include changes from many authors. It is not uncommon for your 
change to be included in a build that fails due to someone else's changes, or 
infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail 
[here](https://llvm.org/docs/MyFirstTypoFix.html#myfirsttypofix-issues-after-landing-your-pr).

If your change does cause a problem, it may be reverted, or you can revert it 
yourself. This is a normal part of [LLVM 
development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy).
 You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are 
working as expected, well done!


https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

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

https://github.com/efriedma-quic closed 
https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-07-16 Thread via cfe-commits

T0b1-iOS wrote:

Fixed. Thanks for the review! As I don't have commit access, could you merge 
this for me?. And do you think this could be put onto the 21 release branch? I 
think it should be possible from a policy pov but I think you need to have 
commit access to make a backport request if I'm reading the docs correctly.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-07-16 Thread via cfe-commits

https://github.com/T0b1-iOS updated 
https://github.com/llvm/llvm-project/pull/135230

>From 16068fb6bce3443b608c6007ae0b9ea4eb18825d Mon Sep 17 00:00:00 2001
From: T0b1 
Date: Fri, 11 Jul 2025 01:26:51 +0200
Subject: [PATCH 1/5] [Clang][CodeGen][X86] don't coerce int128 into
 `{i64,i64}` for SysV-like ABIs

---
 clang/lib/CodeGen/Targets/X86.cpp | 18 +++
 clang/test/CodeGen/X86/i128-debuginfo.c   | 10 
 clang/test/CodeGen/X86/x86_64-arguments.c | 21 
 clang/test/CodeGen/alloc-align-attr.c | 58 +++
 clang/test/CodeGen/builtins.c | 18 ++-
 clang/test/CodeGen/extend-arg-64.c|  2 +-
 6 files changed, 70 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/i128-debuginfo.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 0f59caac2323e..bb90e3611b533 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2594,6 +2594,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2726,6 +2734,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 
-emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a)
+// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression()
+__int128_t add(__int128_t a) {
+  return a + a;
+}
+
+// CHECK: ![[DI]] = !DILocalVariable(name: "a", arg: 1
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index 82845f0a2b31f..fd73fbaa8e54f 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -551,6 +551,27 @@ struct s68 {
 void f68(struct s68 x) {
 }
 
+// CHECK-LABEL: define{{.*}} i128 @f69(i128 noundef %a)
+__int128_t f69(__int128_t a) {
+  return a;
+}
+
+// CHECK-LABEL: define{{.*}} i128 @f70(i128 noundef %a)
+__uint128_t f70(__uint128_t a) {
+  return a;
+}
+
+// check that registers are correctly counted for (u)int128_t arguments
+struct s71 {
+  long long a, b;
+};
+// CHECK-LABEL: define{{.*}} void @f71(i128 noundef %a, i128 noundef %b, i64 
noundef %c, ptr noundef byval(%struct.s71) align 8 %d)
+void f71(__int128_t a, __int128_t b, long long c, struct s71 d) {
+}
+// CHECK-LABEL: define{{.*}} void @f72(i128 noundef %a, i128 noundef %b, i64 
%d.coerce0, i64 %d.coerce1)
+void f72(__int128_t a, __int128_t b, struct s71 d) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:
diff --git a/clang/test/CodeGen/alloc-align-attr.c 
b/clang/test/CodeGen/alloc-align-attr.c
index 76e5d1041b19f..c4c4e76eaaa04 100644
--- a/clang/test/CodeGen/alloc-align-attr.c
+++ b/clang/test/CodeGen/alloc-align-attr.c
@@ -70,66 +70,42 @@ __INT32_TYPE__ test4(__SIZE_TYPE__ a) {
 
 struct Empty {};
 struct MultiArgs { __INT64_TYPE__ a, b;};
-// Struct parameter doesn't take up an IR parameter, 'i' takes up 2.
+// Struct parameter doesn't take up an IR parameter, 'i' takes up 1.
 // Truncation to i64 is permissible, since alignments of greater than 2^64 are 
insane.
 __INT32_TYPE__ *m3(struct Empty s, __int128_t i) 
__attribute__((alloc_align(2)));
 // CHECK-LABEL: @test5(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:[[A:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[A_ADDR:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
-// CHECK-NEXT:[[COERCE:%.*]] = alloca i128, align 16
-// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr 
[[A]], i32 0, i32 0
-// CHECK-NEXT:store i64 [[A_COERCE0:%.*

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-07-11 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

@efriedma-quic Okay, the CI problems are fixed now. It seems there was some 
external problem with libcxx that made its tests fail before. Maybe you could 
take a look now

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-06-30 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

No problem. I changed it to now do an early return. Is that better? I don't 
think the CI ran again so maybe you need to approve it running or something?

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-06-30 Thread via cfe-commits

https://github.com/T0b1-iOS updated 
https://github.com/llvm/llvm-project/pull/135230

>From 36ee902227e66c24cd7de42ed6a26637f440b4a3 Mon Sep 17 00:00:00 2001
From: T0b1 
Date: Thu, 10 Apr 2025 19:16:00 +0200
Subject: [PATCH 1/4] [Clang][CodeGen][X86] don't coerce int128 into
 `{i64,i64}` for SysV-like ABIs

---
 clang/lib/CodeGen/Targets/X86.cpp | 18 +++
 clang/test/CodeGen/X86/i128-debuginfo.c   | 10 
 clang/test/CodeGen/X86/x86_64-arguments.c | 21 
 clang/test/CodeGen/alloc-align-attr.c | 58 +++
 clang/test/CodeGen/builtins.c | 18 ++-
 clang/test/CodeGen/extend-arg-64.c|  2 +-
 6 files changed, 70 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/i128-debuginfo.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 0f59caac2323e..bb90e3611b533 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2594,6 +2594,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2726,6 +2734,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 
-emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a)
+// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression()
+__int128_t add(__int128_t a) {
+  return a + a;
+}
+
+// CHECK: ![[DI]] = !DILocalVariable(name: "a", arg: 1
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index 82845f0a2b31f..fd73fbaa8e54f 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -551,6 +551,27 @@ struct s68 {
 void f68(struct s68 x) {
 }
 
+// CHECK-LABEL: define{{.*}} i128 @f69(i128 noundef %a)
+__int128_t f69(__int128_t a) {
+  return a;
+}
+
+// CHECK-LABEL: define{{.*}} i128 @f70(i128 noundef %a)
+__uint128_t f70(__uint128_t a) {
+  return a;
+}
+
+// check that registers are correctly counted for (u)int128_t arguments
+struct s71 {
+  long long a, b;
+};
+// CHECK-LABEL: define{{.*}} void @f71(i128 noundef %a, i128 noundef %b, i64 
noundef %c, ptr noundef byval(%struct.s71) align 8 %d)
+void f71(__int128_t a, __int128_t b, long long c, struct s71 d) {
+}
+// CHECK-LABEL: define{{.*}} void @f72(i128 noundef %a, i128 noundef %b, i64 
%d.coerce0, i64 %d.coerce1)
+void f72(__int128_t a, __int128_t b, struct s71 d) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:
diff --git a/clang/test/CodeGen/alloc-align-attr.c 
b/clang/test/CodeGen/alloc-align-attr.c
index 76e5d1041b19f..c4c4e76eaaa04 100644
--- a/clang/test/CodeGen/alloc-align-attr.c
+++ b/clang/test/CodeGen/alloc-align-attr.c
@@ -70,66 +70,42 @@ __INT32_TYPE__ test4(__SIZE_TYPE__ a) {
 
 struct Empty {};
 struct MultiArgs { __INT64_TYPE__ a, b;};
-// Struct parameter doesn't take up an IR parameter, 'i' takes up 2.
+// Struct parameter doesn't take up an IR parameter, 'i' takes up 1.
 // Truncation to i64 is permissible, since alignments of greater than 2^64 are 
insane.
 __INT32_TYPE__ *m3(struct Empty s, __int128_t i) 
__attribute__((alloc_align(2)));
 // CHECK-LABEL: @test5(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:[[A:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[A_ADDR:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
-// CHECK-NEXT:[[COERCE:%.*]] = alloca i128, align 16
-// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr 
[[A]], i32 0, i32 0
-// CHECK-NEXT:store i64 [[A_COERCE0:%.*

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-06-03 Thread Eli Friedman via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

efriedma-quic wrote:

Sorry about the delay here.

I think this does the right thing, but in a pretty unintuitive way; I had to 
read through the code multiple times to convince myself this actually works the 
way it's supposed to.

I'd rather not have GetINTEGERTypeAtOffset return nullptr; instead, the callers 
of GetINTEGERTypeAtOffset should explicitly check for an i128 return type, and 
return early.  And assert `Hi == Integer`.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-05-26 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

@efriedma-quic ping

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-05-13 Thread via cfe-commits

https://github.com/T0b1-iOS edited 
https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-05-13 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

@efriedma-quic ping. Would this be okay now?

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-27 Thread via cfe-commits

https://github.com/T0b1-iOS updated 
https://github.com/llvm/llvm-project/pull/135230

>From f0bb89e5cfe2739dc51faef64215251cfe1516d4 Mon Sep 17 00:00:00 2001
From: T0b1 
Date: Thu, 10 Apr 2025 19:16:00 +0200
Subject: [PATCH 1/3] [Clang][CodeGen][X86] don't coerce int128 into
 `{i64,i64}` for SysV-like ABIs

---
 clang/lib/CodeGen/Targets/X86.cpp | 18 +++
 clang/test/CodeGen/X86/i128-debuginfo.c   | 10 
 clang/test/CodeGen/X86/x86_64-arguments.c | 21 
 clang/test/CodeGen/alloc-align-attr.c | 58 +++
 clang/test/CodeGen/builtins.c | 18 ++-
 clang/test/CodeGen/extend-arg-64.c|  2 +-
 6 files changed, 70 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/i128-debuginfo.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index b36a6e1396653..aa4ab1c2e5490 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2727,6 +2735,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 
-emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a)
+// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression()
+__int128_t add(__int128_t a) {
+  return a + a;
+}
+
+// CHECK: ![[DI]] = !DILocalVariable(name: "a", arg: 1
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index 82845f0a2b31f..fd73fbaa8e54f 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -551,6 +551,27 @@ struct s68 {
 void f68(struct s68 x) {
 }
 
+// CHECK-LABEL: define{{.*}} i128 @f69(i128 noundef %a)
+__int128_t f69(__int128_t a) {
+  return a;
+}
+
+// CHECK-LABEL: define{{.*}} i128 @f70(i128 noundef %a)
+__uint128_t f70(__uint128_t a) {
+  return a;
+}
+
+// check that registers are correctly counted for (u)int128_t arguments
+struct s71 {
+  long long a, b;
+};
+// CHECK-LABEL: define{{.*}} void @f71(i128 noundef %a, i128 noundef %b, i64 
noundef %c, ptr noundef byval(%struct.s71) align 8 %d)
+void f71(__int128_t a, __int128_t b, long long c, struct s71 d) {
+}
+// CHECK-LABEL: define{{.*}} void @f72(i128 noundef %a, i128 noundef %b, i64 
%d.coerce0, i64 %d.coerce1)
+void f72(__int128_t a, __int128_t b, struct s71 d) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:
diff --git a/clang/test/CodeGen/alloc-align-attr.c 
b/clang/test/CodeGen/alloc-align-attr.c
index 76e5d1041b19f..c4c4e76eaaa04 100644
--- a/clang/test/CodeGen/alloc-align-attr.c
+++ b/clang/test/CodeGen/alloc-align-attr.c
@@ -70,66 +70,42 @@ __INT32_TYPE__ test4(__SIZE_TYPE__ a) {
 
 struct Empty {};
 struct MultiArgs { __INT64_TYPE__ a, b;};
-// Struct parameter doesn't take up an IR parameter, 'i' takes up 2.
+// Struct parameter doesn't take up an IR parameter, 'i' takes up 1.
 // Truncation to i64 is permissible, since alignments of greater than 2^64 are 
insane.
 __INT32_TYPE__ *m3(struct Empty s, __int128_t i) 
__attribute__((alloc_align(2)));
 // CHECK-LABEL: @test5(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:[[A:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[A_ADDR:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
-// CHECK-NEXT:[[COERCE:%.*]] = alloca i128, align 16
-// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr 
[[A]], i32 0, i32 0
-// CHECK-NEXT:store i64 [[A_COERCE0:%.*

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-27 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

I changed GetINTEGERTypeAtOffset to return an i128 when appropriate. That also 
causes _BitInt(128) to be passed as an i128 but that should be fine as long as 
it doesn't change how it is passed on the stack.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-27 Thread via cfe-commits

https://github.com/T0b1-iOS updated 
https://github.com/llvm/llvm-project/pull/135230

>From f0bb89e5cfe2739dc51faef64215251cfe1516d4 Mon Sep 17 00:00:00 2001
From: T0b1 
Date: Thu, 10 Apr 2025 19:16:00 +0200
Subject: [PATCH 1/2] [Clang][CodeGen][X86] don't coerce int128 into
 `{i64,i64}` for SysV-like ABIs

---
 clang/lib/CodeGen/Targets/X86.cpp | 18 +++
 clang/test/CodeGen/X86/i128-debuginfo.c   | 10 
 clang/test/CodeGen/X86/x86_64-arguments.c | 21 
 clang/test/CodeGen/alloc-align-attr.c | 58 +++
 clang/test/CodeGen/builtins.c | 18 ++-
 clang/test/CodeGen/extend-arg-64.c|  2 +-
 6 files changed, 70 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/i128-debuginfo.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index b36a6e1396653..aa4ab1c2e5490 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2727,6 +2735,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 
-emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a)
+// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression()
+__int128_t add(__int128_t a) {
+  return a + a;
+}
+
+// CHECK: ![[DI]] = !DILocalVariable(name: "a", arg: 1
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index 82845f0a2b31f..fd73fbaa8e54f 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -551,6 +551,27 @@ struct s68 {
 void f68(struct s68 x) {
 }
 
+// CHECK-LABEL: define{{.*}} i128 @f69(i128 noundef %a)
+__int128_t f69(__int128_t a) {
+  return a;
+}
+
+// CHECK-LABEL: define{{.*}} i128 @f70(i128 noundef %a)
+__uint128_t f70(__uint128_t a) {
+  return a;
+}
+
+// check that registers are correctly counted for (u)int128_t arguments
+struct s71 {
+  long long a, b;
+};
+// CHECK-LABEL: define{{.*}} void @f71(i128 noundef %a, i128 noundef %b, i64 
noundef %c, ptr noundef byval(%struct.s71) align 8 %d)
+void f71(__int128_t a, __int128_t b, long long c, struct s71 d) {
+}
+// CHECK-LABEL: define{{.*}} void @f72(i128 noundef %a, i128 noundef %b, i64 
%d.coerce0, i64 %d.coerce1)
+void f72(__int128_t a, __int128_t b, struct s71 d) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:
diff --git a/clang/test/CodeGen/alloc-align-attr.c 
b/clang/test/CodeGen/alloc-align-attr.c
index 76e5d1041b19f..c4c4e76eaaa04 100644
--- a/clang/test/CodeGen/alloc-align-attr.c
+++ b/clang/test/CodeGen/alloc-align-attr.c
@@ -70,66 +70,42 @@ __INT32_TYPE__ test4(__SIZE_TYPE__ a) {
 
 struct Empty {};
 struct MultiArgs { __INT64_TYPE__ a, b;};
-// Struct parameter doesn't take up an IR parameter, 'i' takes up 2.
+// Struct parameter doesn't take up an IR parameter, 'i' takes up 1.
 // Truncation to i64 is permissible, since alignments of greater than 2^64 are 
insane.
 __INT32_TYPE__ *m3(struct Empty s, __int128_t i) 
__attribute__((alloc_align(2)));
 // CHECK-LABEL: @test5(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:[[A:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[A_ADDR:%.*]] = alloca i128, align 16
 // CHECK-NEXT:[[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
-// CHECK-NEXT:[[COERCE:%.*]] = alloca i128, align 16
-// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr 
[[A]], i32 0, i32 0
-// CHECK-NEXT:store i64 [[A_COERCE0:%.*

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-23 Thread Jeremy Morse via cfe-commits

jmorse wrote:

> To solve this problem in general, it would probably(?) be best to make SROA 
> create fragment #dbg_value records if it decomposes an alloca into multiple 
> IR values but I have no idea how difficult that would be to accomplish.

An example of this happening today with C++ structured bindings is here: 
https://godbolt.org/z/rn3os13M7 . Specifically, the i64 return value from "f", 
a squashed-together pair of i32s, is decomposed into two `#dbg_value`s 
corresponding to the two variables that the structured-binding assigns to. Each 
`#dbg_value` refers to different IR Values, which seems similar to what's 
desired here. The major difference is that structured bindings have independent 
source variables contained within one alloca; wheras the situation here is one 
source variable being split into fragments.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-16 Thread Eli Friedman via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

efriedma-quic wrote:

Something like that, yes.  Or maybe it's simpler to do it in a separate 
function; whatever's more readable.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-15 Thread via cfe-commits

T0b1-iOS wrote:

> Maybe a bad suggestion, I have not looked into the implementation, but at the 
> point where the i128 gets split into two i64s, could we already update the 
> #dbg_value there to use fragments? At that point we have all the required 
> information, and it sounds like it would avoid the problem since there is 
> then no longer any larger-than-i64 debug info to cause poison?

I think would be possible but currently the code that inserts the 
`#dbg_declare` records (`CodeGenFunction::EmitParmDecl`) is oblivious to the 
splitting. It only gets handed the `i128` value that is loaded from the 
temporary `{i64, i64}` alloca (created in 
`CodeGenFunction::EmitFunctionProlog`) where both `i64` arguments are stored 
into. Thus you would need to add debug handling code into the part that creates 
the temporary alloca which would require a refactoring of the way debug info 
metadata is created because the code responsible for that currently creates the 
`#dbg_declare` records together with the metadata (c.f. 
`CGDebugInfo::EmitDeclare`).
Passing as i128 seems like the better choice in that case.

To solve this problem in general, it would probably(?) be best to make SROA 
create fragment `#dbg_value` records if it decomposes an alloca into multiple 
IR values but I have no idea how difficult that would be to accomplish.

> Presumably the desire here is to improve the variable availability of 
> parameters rather than fully supporting i128's through LLVM debug-info

Yes, at least my primary motivation is for me to be able to retrieve the 
registers the parameter is passed in without having to rely on any crude 
heuristics.

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-15 Thread via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

T0b1-iOS wrote:

I suppose you could make GetINTEGERTypeAtOffset return an i128 if it sees an 
i128 as the IRType and IROffset is 0 but then you need to check if it did that 
in classifyArgumentType and return immediately or make GetINTEGERTypeAtOffset 
return nullptr if the IROffset is >0 to prevent it from creating an aggregate 
argument? The latter seems like something one could easily trip over though

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-11 Thread Eli Friedman via cfe-commits


@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;

efriedma-quic wrote:

We still need to handle i128 in structs.

We could maybe extend GetINTEGERTypeAtOffset to allow it to return i128 when 
appropriate.  (That code is pretty fragile, though; see #76017.)

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-11 Thread Jeremy Morse via cfe-commits

jmorse wrote:

There's precedent for splitting the debug-info into fragments early, we do 
something similar for C++ structured-bindings in SROA and a very similar 
process happens when the i128 argument is split up in instruction-selection.

Split-up locations become brittle to optimisations though: any 
source-expression that gets salvaged into a DIExpression can't be decomposed 
into two fragments, and we have to mark them optimised out. Any salvaging into 
DIExpression for an i128 will almost certainly fail when the value gets split 
up in isel. Plus I believe DWARF doesn't support values on the expression stack 
larger than the machine-address-size, but that's an assumption that can be bent.

Presumably the desire here is to improve the variable availability of 
parameters rather than fully supporting i128's through LLVM debug-info? If so, 
the least invasive approach may be to teach SROA to decompose into fragments 
similar to structured-bindings for the first variable location in the function. 
Or, passing an i128 instead works alright, I have no opinion on ABI matters.

(Paging @OCHyams as he worked on structured bindings; and @slinder1 as this is 
another scenario that might be easier with a typed expression stack)

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread Harald van Dijk via cfe-commits

hvdijk wrote:

Both agreed with @nikic that this PR is a good idea and with @efriedma-quic 
that this does not solve the problem in general. I don't think the latter 
should stop this from being merged but it would be nice to find something that 
addresses all cases.

> Another fix may be to generate `DW_OP_LLVM_fragment` expressions when 
> removing the `or`

Maybe a bad suggestion, I have not looked into the implementation, but at the 
point where the `i128` gets split into two `i64`s, could we already update the 
`#dbg_value` there to use fragments? At that point we have all the required 
information, and it sounds like it would avoid the problem since there is then 
no longer any larger-than-`i64` debug info to cause `poison`?

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

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

efriedma-quic wrote:

There isn't any reason we can't do this... but it doesn't really solve the 
issue in general.  And there are a lot of other ways to trip over this.  CC 
@dblaike @hvdijk @jmorse 

Do we want to try to handle _BitInt, or a struct containing an i128?

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread Nikita Popov via cfe-commits

https://github.com/nikic edited https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread Nikita Popov via cfe-commits

https://github.com/nikic commented:

I haven't checked the implementation, but conceptually this looks fine. Passing 
as i128 instead of {i64, i64} is better for optimization purposes. Rust already 
passes these as i128, so we know that works, and change will improve x-lang 
LTO. (Clang also passes as i128 already, but only for ones that are known to be 
passed in memory -- go figure.)

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (T0b1-iOS)


Changes

Currently, clang coerces (u)int128_t to two i64 IR parameters when they are 
passed in registers. This leads to broken debug info for them after applying 
SROA+InstCombine. SROA generates IR like this 
([godbolt](https://godbolt.org/z/YrTa4chfc)):
```llvm
define dso_local { i64, i64 } @add(i64 noundef %a.coerce0, i64 noundef 
%a.coerce1)  {
entry:
  %a.sroa.2.0.insert.ext = zext i64 %a.coerce1 to i128
  %a.sroa.2.0.insert.shift = shl nuw i128 %a.sroa.2.0.insert.ext, 64
  %a.sroa.0.0.insert.ext = zext i64 %a.coerce0 to i128
  %a.sroa.0.0.insert.insert = or i128 %a.sroa.2.0.insert.shift, 
%a.sroa.0.0.insert.ext
#dbg_value(i128 %a.sroa.0.0.insert.insert, !17, !DIExpression(), !18)
// ...
!17 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !11, line: 1, type: 
!14)
// ...
```
  
  and InstCombine then removes the `or`, moving it into the `DIExpression`, and 
the `shl` at which point the debug info salvaging in `Transforms/Local` 
replaces the arguments with `poison` as it does not allow constants larger than 
64 bit in `DIExpression`s.
  
  I'm working under the assumption that there is interest in fixing this. If 
not, please tell me.
  By not coercing `int128_t`s into `{i64, i64}` but keeping them as `i128`, the 
debug info stays intact and SelectionDAG then generates two 
`DW_OP_LLVM_fragment` expressions for the two corresponding argument registers.

Given that the ABI code for x64 seems to not coerce the argument when it is 
passed on the stack, it should not lead to any problems keeping it as an `i128` 
when it is passed in registers.

Alternatively, this could be fixed by checking if a constant value fits in 64 
bits in the debug info salvaging code and then extending the value on the 
expression stack to the necessary width. This fixes InstCombine breaking the 
debug info but then SelectionDAG removes the expression and that seems 
significantly more complex to debug.

Another fix may be to generate `DW_OP_LLVM_fragment` expressions when removing 
the `or` as it gets marked as disjoint by InstCombine. However, I don't know if 
the KnownBits information is still available at the time the `or` gets removed 
and it would probably require refactoring of the debug info salvaging code as 
that currently only seems to replace single expressions and is not designed to 
support generating new debug records.

Converting `(u)int128_t` arguments to `i128` in the IR seems like the simpler 
solution, if it doesn't cause any ABI issues.

tagging potential reviewers: @nikic @phoebewang @rnk 

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


6 Files Affected:

- (modified) clang/lib/CodeGen/Targets/X86.cpp (+18) 
- (added) clang/test/CodeGen/X86/i128-debuginfo.c (+10) 
- (modified) clang/test/CodeGen/X86/x86_64-arguments.c (+21) 
- (modified) clang/test/CodeGen/alloc-align-attr.c (+17-41) 
- (modified) clang/test/CodeGen/builtins.c (+3-15) 
- (modified) clang/test/CodeGen/extend-arg-64.c (+1-1) 


``diff
diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index b36a6e1396653..aa4ab1c2e5490 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2727,6 +2735,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 
-emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a)
+// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression()
+__int128_t add(__int128_t a) {
+  return a + a;
+}
+
+// CHECK: ![[DI]] = !DILocalVa

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread via cfe-commits

https://github.com/T0b1-iOS created 
https://github.com/llvm/llvm-project/pull/135230

Currently, clang coerces (u)int128_t to two i64 IR parameters when they are 
passed in registers. This leads to broken debug info for them after applying 
SROA+InstCombine. SROA generates IR like this 
([godbolt](https://godbolt.org/z/YrTa4chfc)):
```llvm
define dso_local { i64, i64 } @add(i64 noundef %a.coerce0, i64 noundef 
%a.coerce1)  {
entry:
  %a.sroa.2.0.insert.ext = zext i64 %a.coerce1 to i128
  %a.sroa.2.0.insert.shift = shl nuw i128 %a.sroa.2.0.insert.ext, 64
  %a.sroa.0.0.insert.ext = zext i64 %a.coerce0 to i128
  %a.sroa.0.0.insert.insert = or i128 %a.sroa.2.0.insert.shift, 
%a.sroa.0.0.insert.ext
#dbg_value(i128 %a.sroa.0.0.insert.insert, !17, !DIExpression(), !18)
// ...
!17 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !11, line: 1, type: 
!14)
// ...
```
  
  and InstCombine then removes the `or`, moving it into the `DIExpression`, and 
the `shl` at which point the debug info salvaging in `Transforms/Local` 
replaces the arguments with `poison` as it does not allow constants larger than 
64 bit in `DIExpression`s.
  
  I'm working under the assumption that there is interest in fixing this. If 
not, please tell me.
  By not coercing `int128_t`s into `{i64, i64}` but keeping them as `i128`, the 
debug info stays intact and SelectionDAG then generates two 
`DW_OP_LLVM_fragment` expressions for the two corresponding argument registers.

Given that the ABI code for x64 seems to not coerce the argument when it is 
passed on the stack, it should not lead to any problems keeping it as an `i128` 
when it is passed in registers.

Alternatively, this could be fixed by checking if a constant value fits in 64 
bits in the debug info salvaging code and then extending the value on the 
expression stack to the necessary width. This fixes InstCombine breaking the 
debug info but then SelectionDAG removes the expression and that seems 
significantly more complex to debug.

Another fix may be to generate `DW_OP_LLVM_fragment` expressions when removing 
the `or` as it gets marked as disjoint by InstCombine. However, I don't know if 
the KnownBits information is still available at the time the `or` gets removed 
and it would probably require refactoring of the debug info salvaging code as 
that currently only seems to replace single expressions and is not designed to 
support generating new debug records.

Converting `(u)int128_t` arguments to `i128` in the IR seems like the simpler 
solution, if it doesn't cause any ABI issues.

tagging potential reviewers: @nikic @phoebewang @rnk 

>From f0bb89e5cfe2739dc51faef64215251cfe1516d4 Mon Sep 17 00:00:00 2001
From: T0b1 
Date: Thu, 10 Apr 2025 19:16:00 +0200
Subject: [PATCH] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}`
 for SysV-like ABIs

---
 clang/lib/CodeGen/Targets/X86.cpp | 18 +++
 clang/test/CodeGen/X86/i128-debuginfo.c   | 10 
 clang/test/CodeGen/X86/x86_64-arguments.c | 21 
 clang/test/CodeGen/alloc-align-attr.c | 58 +++
 clang/test/CodeGen/builtins.c | 18 ++-
 clang/test/CodeGen/extend-arg-64.c|  2 +-
 6 files changed, 70 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/i128-debuginfo.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index b36a6e1396653..aa4ab1c2e5490 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2595,6 +2595,14 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type 
*Hi,
 
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy) const {
+  // return int128 as i128
+  if (const BuiltinType *BT = RetTy->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  return ABIArgInfo::getDirect();
+}
+  }
+
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
   // classification algorithm.
   X86_64ABIInfo::Class Lo, Hi;
@@ -2727,6 +2735,16 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 bool isNamedArg, bool IsRegCall) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  // represent int128 as i128
+  if (const BuiltinType *BT = Ty->getAs()) {
+BuiltinType::Kind k = BT->getKind();
+if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+  neededInt = 2;
+  neededSSE = 0;
+  return ABIArgInfo::getDirect();
+}
+  }
+
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
 
diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c 
b/clang/test/CodeGen/X86/i128-debuginfo.c
new file mode 100644
index 0..4b865c1bed9f0
--- /dev/null
+++ b/clang/test/CodeGen/X86/i128-debuginfo.c
@@ -0,0 +1,10 @@
+// no autogeneration since update_cc_test_checks does not support -g
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited 

[clang] [Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (PR #135230)

2025-04-10 Thread via cfe-commits

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write 
permissions for the repository. In which case you can instead tag reviewers by 
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a 
review by "ping"ing the PR by adding a comment “Ping”. The common courtesy 
"ping" rate is once a week. Please remember that you are asking for valuable 
time from other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/135230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits