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
