https://github.com/heiher created 
https://github.com/llvm/llvm-project/pull/211464

Allow `i128` values to be used with the `f` inline assembly constraint when 
targeting LSX.

Although `i128` is not a legal LSX value type, it naturally maps to a single 
128-bit LSX vector register for inline assembly. This enables instructions such 
as `vadd.q` to operate directly on `__int128` operands without requiring 
explicit vector types.

>From 8b45a363a2aea09568a34467ed3b9d96edca27aa Mon Sep 17 00:00:00 2001
From: WANG Rui <[email protected]>
Date: Thu, 9 Jul 2026 14:52:13 +0800
Subject: [PATCH] [LoongArch] Support i128 operands for LSX inline assembly

Allow `i128` values to be used with the `f` inline assembly constraint when
targeting LSX.

Although `i128` is not a legal LSX value type, it naturally maps to a single
128-bit LSX vector register for inline assembly. This enables instructions
such as `vadd.q` to operate directly on `__int128` operands without requiring
explicit vector types.
---
 .../LoongArch/lsx/inline-asm-operand-types.c  | 15 +++++++++++++
 .../LoongArch/LoongArchISelLowering.cpp       |  2 ++
 .../LoongArch/lsx/inline-asm-operand-types.ll | 21 +++++++++++++++++++
 3 files changed, 38 insertions(+)
 create mode 100644 clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.c
 create mode 100644 llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.ll

diff --git a/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.c 
b/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.c
new file mode 100644
index 0000000000000..6fdf1a8eac255
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.c
@@ -0,0 +1,15 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 2
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s -o - | FileCheck %s
+
+// CHECK-LABEL: define dso_local void @test_i128
+// CHECK-SAME: (ptr nofree noundef readonly captures(none) [[A:%.*]], ptr 
nofree noundef readonly captures(none) [[B:%.*]], ptr nofree noundef writeonly 
captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr 
#[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i128, ptr [[A]], align 16, !tbaa 
[[TBAA6:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load i128, ptr [[B]], align 16, !tbaa 
[[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call i128 asm sideeffect "vadd.q ${0:w}, 
${1:w}, ${2:w}", "=f,f,f"(i128 [[TMP0]], i128 [[TMP1]]) #[[ATTR1:[0-9]+]], 
!srcloc [[META8:![0-9]+]]
+// CHECK-NEXT:    store i128 [[TMP2]], ptr [[R]], align 16, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_i128(__int128 *a, __int128 *b, __int128 *r) {
+  asm volatile ("vadd.q %w0, %w1, %w2" : "=f" (*r) : "f" (*a), "f" (*b));
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp 
b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 4c5bb28a5e42f..409e23f292c93 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -11332,6 +11332,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
       if (Subtarget.hasExtLSX() &&
           TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
         return std::make_pair(0U, &LoongArch::LSX128RegClass);
+      if (Subtarget.hasExtLSX() && VT == MVT::i128)
+        return std::make_pair(0U, &LoongArch::LSX128RegClass);
       if (Subtarget.hasExtLASX() &&
           TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
         return std::make_pair(0U, &LoongArch::LASX256RegClass);
diff --git a/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.ll 
b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.ll
new file mode 100644
index 0000000000000..77081f0aaad7c
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-types.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 2
+; RUN: llc --mtriple=loongarch32 -mattr=+32s,+lsx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 -mattr=+lsx < %s | FileCheck %s
+
+define void @i128(ptr %a, ptr %b, ptr %r) nounwind {
+; CHECK-LABEL: i128:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vld $vr0, $a1, 0
+; CHECK-NEXT:    vld $vr1, $a0, 0
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vadd.q $vr2, $vr1, $vr0
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    vst $vr2, $a2, 0
+; CHECK-NEXT:    ret
+entry:
+  %0 = load i128, ptr %a, align 16
+  %1 = load i128, ptr %b, align 16
+  %2 = tail call i128 asm sideeffect "vadd.q ${0:w}, ${1:w}, ${2:w}", 
"=&f,f,f"(i128 %0, i128 %1)
+  store i128 %2, ptr %r, align 16
+  ret void
+}

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

Reply via email to