[llvm] [AArch64][GlobalISel] Add handling for cls intrinsic (PR #200440)
Joshua Rodriguez via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 03:35:08 PDT 2026
https://github.com/JoshdRod updated https://github.com/llvm/llvm-project/pull/200440
>From 473c00533ac0102239c5c88f6c1c6da966277fed Mon Sep 17 00:00:00 2001
From: Josh Rodriguez <josh.rodriguez at arm.com>
Date: Fri, 29 May 2026 15:59:09 +0000
Subject: [PATCH 1/6] [AArch64][GlobalISel] Add handling for cls intrinsic
Neon intrinsic neon.cls wasn't linked to the generic node G_CTLS, which wasn't linked to AArch64 specific SDAG node ctls.
Add in these links to allow the intrinsic to properly lower.
---
llvm/lib/Target/AArch64/AArch64InstrGISel.td | 2 ++
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp | 2 ++
llvm/test/CodeGen/AArch64/arm64-vcnt.ll | 1 +
3 files changed, 5 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index ec95448f61043..b4d04f428bcd2 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -355,6 +355,8 @@ def : GINodeEquiv<G_AARCH64_RANGE_PREFETCH, AArch64RangePrefetch>;
def : GINodeEquiv<G_FPTRUNC_ODD, AArch64fcvtxn_n>;
+def : GINodeEquiv<G_CTLS, ctls>;
+
// These are patterns that we only use for GlobalISel via the importer.
def : Pat<(f32 (fadd (vector_extract (v2f32 FPR64:$Rn), (i64 0)),
(vector_extract (v2f32 FPR64:$Rn), (i64 1)))),
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 6092f63fcde72..78c2268aac986 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -2106,6 +2106,8 @@ bool AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
return LowerUnaryOp(TargetOpcode::G_FPTOUI_SAT);
case Intrinsic::aarch64_neon_fcvtzs:
return LowerUnaryOp(TargetOpcode::G_FPTOSI_SAT);
+ case Intrinsic::aarch64_neon_cls:
+ return LowerUnaryOp(TargetOpcode::G_CTLS);
case Intrinsic::vector_reverse:
// TODO: Add support for vector_reverse
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
index f2113d45589b3..c5ef62293c25a 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel -global-isel-abort=2 2>&1 | FileCheck %s
define <8 x i8> @cls_8b(ptr %A) nounwind {
;CHECK-LABEL: cls_8b:
>From 9bec3bbd6d49a1f65a58d55d68f880306eb9db60 Mon Sep 17 00:00:00 2001
From: Josh Rodriguez <josh.rodriguez at arm.com>
Date: Tue, 2 Jun 2026 13:11:50 +0000
Subject: [PATCH 2/6] [AArch64][GlobalISel] Remove duplicate GI node
equivalence statement
The generic opcode G_CTLS is already defined as equivalent to the SDAG node ctls in a generic SelectionDAGCompat file.
Hence, we can remove this AArch64-specific duplicate definition.
---
llvm/lib/Target/AArch64/AArch64InstrGISel.td | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index b4d04f428bcd2..9c646c43cdcbf 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -355,7 +355,6 @@ def : GINodeEquiv<G_AARCH64_RANGE_PREFETCH, AArch64RangePrefetch>;
def : GINodeEquiv<G_FPTRUNC_ODD, AArch64fcvtxn_n>;
-def : GINodeEquiv<G_CTLS, ctls>;
// These are patterns that we only use for GlobalISel via the importer.
def : Pat<(f32 (fadd (vector_extract (v2f32 FPR64:$Rn), (i64 0)),
>From 2fdd74d7654f52891c69610cf0a1a3a12e8302aa Mon Sep 17 00:00:00 2001
From: Josh Rodriguez <josh.rodriguez at arm.com>
Date: Tue, 2 Jun 2026 13:20:00 +0000
Subject: [PATCH 3/6] [AArch64] Modernise test arm64-vcnt.ll
---
llvm/test/CodeGen/AArch64/arm64-vcnt.ll | 43 ++++++++++++++++++-------
1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
index c5ef62293c25a..6e4d5d5fe418b 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
@@ -1,49 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel -global-isel-abort=2 2>&1 | FileCheck %s
define <8 x i8> @cls_8b(ptr %A) nounwind {
-;CHECK-LABEL: cls_8b:
-;CHECK: cls.8b
+; CHECK-LABEL: cls_8b:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr d0, [x0]
+; CHECK-NEXT: cls.8b v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <8 x i8>, ptr %A
%tmp3 = call <8 x i8> @llvm.aarch64.neon.cls.v8i8(<8 x i8> %tmp1)
ret <8 x i8> %tmp3
}
define <16 x i8> @cls_16b(ptr %A) nounwind {
-;CHECK-LABEL: cls_16b:
-;CHECK: cls.16b
+; CHECK-LABEL: cls_16b:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr q0, [x0]
+; CHECK-NEXT: cls.16b v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <16 x i8>, ptr %A
%tmp3 = call <16 x i8> @llvm.aarch64.neon.cls.v16i8(<16 x i8> %tmp1)
ret <16 x i8> %tmp3
}
define <4 x i16> @cls_4h(ptr %A) nounwind {
-;CHECK-LABEL: cls_4h:
-;CHECK: cls.4h
+; CHECK-LABEL: cls_4h:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr d0, [x0]
+; CHECK-NEXT: cls.4h v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <4 x i16>, ptr %A
%tmp3 = call <4 x i16> @llvm.aarch64.neon.cls.v4i16(<4 x i16> %tmp1)
ret <4 x i16> %tmp3
}
define <8 x i16> @cls_8h(ptr %A) nounwind {
-;CHECK-LABEL: cls_8h:
-;CHECK: cls.8h
+; CHECK-LABEL: cls_8h:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr q0, [x0]
+; CHECK-NEXT: cls.8h v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <8 x i16>, ptr %A
%tmp3 = call <8 x i16> @llvm.aarch64.neon.cls.v8i16(<8 x i16> %tmp1)
ret <8 x i16> %tmp3
}
define <2 x i32> @cls_2s(ptr %A) nounwind {
-;CHECK-LABEL: cls_2s:
-;CHECK: cls.2s
+; CHECK-LABEL: cls_2s:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr d0, [x0]
+; CHECK-NEXT: cls.2s v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <2 x i32>, ptr %A
%tmp3 = call <2 x i32> @llvm.aarch64.neon.cls.v2i32(<2 x i32> %tmp1)
ret <2 x i32> %tmp3
}
define <4 x i32> @cls_4s(ptr %A) nounwind {
-;CHECK-LABEL: cls_4s:
-;CHECK: cls.4s
+; CHECK-LABEL: cls_4s:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ldr q0, [x0]
+; CHECK-NEXT: cls.4s v0, v0
+; CHECK-NEXT: ret
%tmp1 = load <4 x i32>, ptr %A
%tmp3 = call <4 x i32> @llvm.aarch64.neon.cls.v4i32(<4 x i32> %tmp1)
ret <4 x i32> %tmp3
>From 83e577b07802785de8707050c8a84f62287b7f5d Mon Sep 17 00:00:00 2001
From: Joshua Rodriguez <josh.rodriguez at arm.com>
Date: Tue, 2 Jun 2026 17:36:24 +0100
Subject: [PATCH 4/6] [AArch64] Remove newline
Removed an empty line in the AArch64InstrGISel.td file.
---
llvm/lib/Target/AArch64/AArch64InstrGISel.td | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index 9c646c43cdcbf..ec95448f61043 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -355,7 +355,6 @@ def : GINodeEquiv<G_AARCH64_RANGE_PREFETCH, AArch64RangePrefetch>;
def : GINodeEquiv<G_FPTRUNC_ODD, AArch64fcvtxn_n>;
-
// These are patterns that we only use for GlobalISel via the importer.
def : Pat<(f32 (fadd (vector_extract (v2f32 FPR64:$Rn), (i64 0)),
(vector_extract (v2f32 FPR64:$Rn), (i64 1)))),
>From b43f5b7bec7177a995329aff4d7aefe793e09132 Mon Sep 17 00:00:00 2001
From: Joshua Rodriguez <josh.rodriguez at arm.com>
Date: Tue, 2 Jun 2026 17:39:32 +0100
Subject: [PATCH 5/6] [AArch64][GlobalISel] Remove -global-isel-fallback from
test line
As there are now no functions in this file that fallback to SDAG, remove the flag allowing fallbacks.
This means that if a change causes one of these function's code generation to fallback to SDAG, the test will fail.
---
llvm/test/CodeGen/AArch64/arm64-vcvt.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcvt.ll b/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
index 7f6b16d3ccbb4..c9644c381b73d 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-SD
-; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define <2 x i32> @fcvtas_2s(<2 x float> %A) nounwind {
; CHECK-LABEL: fcvtas_2s:
>From 98f121a9762add5390b1de6948273b2cd624ef4d Mon Sep 17 00:00:00 2001
From: Josh Rodriguez <josh.rodriguez at arm.com>
Date: Wed, 3 Jun 2026 10:34:44 +0000
Subject: [PATCH 6/6] [AArch64][GlobalISel] Remove -global-isel-fallback from
correct test file
Previous commit removed the -global-isel-fallback flag from the wrong test (typo in file name). Fix this by re-adding the flag into the wrong file, and removing it from the correct one.
---
llvm/test/CodeGen/AArch64/arm64-vcnt.ll | 2 +-
llvm/test/CodeGen/AArch64/arm64-vcvt.ll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
index 6e4d5d5fe418b..0bd34eb91079b 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcnt.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s
-; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel -global-isel-abort=2 2>&1 | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel | FileCheck %s
define <8 x i8> @cls_8b(ptr %A) nounwind {
; CHECK-LABEL: cls_8b:
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcvt.ll b/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
index c9644c381b73d..7f6b16d3ccbb4 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcvt.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-SD
-; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define <2 x i32> @fcvtas_2s(<2 x float> %A) nounwind {
; CHECK-LABEL: fcvtas_2s:
More information about the llvm-commits
mailing list