[llvm] [AArch64][GlobalISel] Add basic scalar handling for i32 lround and lrint (PR #170175)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 1 09:49:05 PST 2025
https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/170175
>From 9199eb3595c84fb31df0dc46113468f6aec6a4b5 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 1 Dec 2025 17:48:55 +0000
Subject: [PATCH] [AArch64][GlobalISel] Add basic scalar handling for i32
lround and lrint.
This covers the windows variants, where long == i32. We can treat them as legal
and generate the expected fcvtas instruction. The lround/llround and
lrint/llrint were rejigged to allow the common parts to legalize in the same
manner.
---
.../AArch64/GISel/AArch64LegalizerInfo.cpp | 14 ++---
.../GlobalISel/legalizer-info-validation.mir | 2 +-
.../CodeGen/AArch64/lrint-conv-fp16-win.ll | 6 +-
llvm/test/CodeGen/AArch64/lrint-conv-win.ll | 7 +--
.../CodeGen/AArch64/lround-conv-fp16-win.ll | 56 ++++++-----------
llvm/test/CodeGen/AArch64/lround-conv-win.ll | 63 ++++++-------------
llvm/test/CodeGen/AArch64/vector-lrint.ll | 29 +++++----
7 files changed, 65 insertions(+), 112 deletions(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..51c0b1bf3589c 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -432,11 +432,6 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.minScalar(0, s32)
.scalarize(0);
- getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
- .legalFor({{s64, MinFPScalar}, {s64, s32}, {s64, s64}})
- .libcallFor({{s64, s128}})
- .minScalarOrElt(1, MinFPScalar);
-
getActionDefinitionsBuilder({G_FCOS, G_FSIN, G_FPOW, G_FLOG, G_FLOG2,
G_FLOG10, G_FTAN, G_FEXP, G_FEXP2, G_FEXP10,
G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH,
@@ -451,9 +446,14 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.minScalar(0, s32)
.libcallFor({{s32, s32}, {s64, s32}, {s128, s32}});
- getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
+ getActionDefinitionsBuilder({G_LROUND, G_INTRINSIC_LRINT})
+ .legalFor({{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})
+ .legalFor(HasFP16, {{s32, s16}, {s64, s16}})
+ .minScalar(1, s32)
+ .libcallFor({{s64, s128}});
+ getActionDefinitionsBuilder({G_LLROUND, G_INTRINSIC_LLRINT})
.legalFor({{s64, s32}, {s64, s64}})
- .legalFor(HasFP16, {{s64, s16}})
+ .legalFor(HasFP16, {{s32, s16}, {s64, s16}})
.minScalar(0, s64)
.minScalar(1, s32)
.libcallFor({{s64, s128}});
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index e68278dadc4b8..af72ffbcfadce 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -187,6 +187,7 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_INTRINSIC_LRINT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_INTRINSIC_LLRINT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
@@ -698,7 +699,6 @@
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_LLROUND (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_BR (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll b/llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll
index 0fc8b9a9f57ad..610ab92c01221 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll
@@ -1,10 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=aarch64 -mattr=+neon | FileCheck %s --check-prefixes=CHECK,CHECK-SD
-; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-
-; CHECK-GI: warning: Instruction selection used fallback path for testmhhs
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmhws
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmhxs
+; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i16 @testmhhs(half %x) {
; CHECK-LABEL: testmhhs:
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv-win.ll b/llvm/test/CodeGen/AArch64/lrint-conv-win.ll
index 164dbd854173c..00fc862eaa4f4 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv-win.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv-win.ll
@@ -1,11 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=aarch64 -mattr=+neon | FileCheck %s --check-prefixes=CHECK,CHECK-SD
-; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-
-; CHECK-GI: warning: Instruction selection used fallback path for testmsxs
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmsws
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmsxd
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for testmswd
+; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i64 @testmsxs(float %x) {
; CHECK-LABEL: testmsxs:
diff --git a/llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll b/llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll
index e5390169c51d6..63539a154add4 100644
--- a/llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll
+++ b/llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll
@@ -3,18 +3,11 @@
; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i16 @testmhhs(half %x) {
-; CHECK-SD-LABEL: testmhhs:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvt s0, h0
-; CHECK-SD-NEXT: fcvtas w0, s0
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmhhs:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvt s0, h0
-; CHECK-GI-NEXT: fcvtas x0, s0
-; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmhhs:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvt s0, h0
+; CHECK-NEXT: fcvtas w0, s0
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f16(half %x)
%conv = trunc i32 %0 to i16
@@ -22,41 +15,28 @@ entry:
}
define i32 @testmhws(half %x) {
-; CHECK-SD-LABEL: testmhws:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvt s0, h0
-; CHECK-SD-NEXT: fcvtas w0, s0
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmhws:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvt s0, h0
-; CHECK-GI-NEXT: fcvtas x0, s0
-; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmhws:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvt s0, h0
+; CHECK-NEXT: fcvtas w0, s0
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f16(half %x)
ret i32 %0
}
define i64 @testmhxs(half %x) {
-; CHECK-SD-LABEL: testmhxs:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvt s0, h0
-; CHECK-SD-NEXT: fcvtas w8, s0
-; CHECK-SD-NEXT: sxtw x0, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmhxs:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvt s0, h0
-; CHECK-GI-NEXT: fcvtas x8, s0
-; CHECK-GI-NEXT: sxtw x0, w8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmhxs:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvt s0, h0
+; CHECK-NEXT: fcvtas w8, s0
+; CHECK-NEXT: sxtw x0, w8
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f16(half %x)
%conv = sext i32 %0 to i64
ret i64 %conv
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/lround-conv-win.ll b/llvm/test/CodeGen/AArch64/lround-conv-win.ll
index 02c1e9381eb06..5bb4525586662 100644
--- a/llvm/test/CodeGen/AArch64/lround-conv-win.ll
+++ b/llvm/test/CodeGen/AArch64/lround-conv-win.ll
@@ -3,17 +3,11 @@
; RUN: llc < %s -mtriple=aarch64 -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i64 @testmsxs(float %x) {
-; CHECK-SD-LABEL: testmsxs:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvtas w8, s0
-; CHECK-SD-NEXT: sxtw x0, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmsxs:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvtas x8, s0
-; CHECK-GI-NEXT: sxtw x0, w8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmsxs:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvtas w8, s0
+; CHECK-NEXT: sxtw x0, w8
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f32(float %x)
%conv = sext i32 %0 to i64
@@ -21,33 +15,21 @@ entry:
}
define i32 @testmsws(float %x) {
-; CHECK-SD-LABEL: testmsws:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvtas w0, s0
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmsws:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvtas x0, s0
-; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmsws:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvtas w0, s0
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f32(float %x)
ret i32 %0
}
define i64 @testmsxd(double %x) {
-; CHECK-SD-LABEL: testmsxd:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvtas w8, d0
-; CHECK-SD-NEXT: sxtw x0, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmsxd:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvtas x8, d0
-; CHECK-GI-NEXT: sxtw x0, w8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmsxd:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvtas w8, d0
+; CHECK-NEXT: sxtw x0, w8
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f64(double %x)
%conv = sext i32 %0 to i64
@@ -55,20 +37,15 @@ entry:
}
define i32 @testmswd(double %x) {
-; CHECK-SD-LABEL: testmswd:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: fcvtas w0, d0
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: testmswd:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: fcvtas x0, d0
-; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: testmswd:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvtas w0, d0
+; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.lround.i32.f64(double %x)
ret i32 %0
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/vector-lrint.ll b/llvm/test/CodeGen/AArch64/vector-lrint.ll
index c226ec3c3e25c..305f8cd67a044 100644
--- a/llvm/test/CodeGen/AArch64/vector-lrint.ll
+++ b/llvm/test/CodeGen/AArch64/vector-lrint.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=aarch64 -mattr=+neon |\
-; RUN: FileCheck %s --check-prefixes=CHECK-i32
+; RUN: FileCheck %s --check-prefixes=CHECK-i32,CHECK-i32-SD
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=aarch64 -mattr=+neon |\
; RUN: FileCheck %s --check-prefixes=CHECK-i64,CHECK-i64-SD
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=aarch64 -mattr=+neon \
@@ -10,19 +10,16 @@
; RUN: -global-isel -global-isel-abort=2 2>&1 |\
; RUN: FileCheck %s --check-prefixes=CHECK-i64,CHECK-i64-GI
-; CHECK-i32-GI: warning: Instruction selection used fallback path for lrint_v1f16
-; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v2f16
+; CHECK-i32-GI: warning: Instruction selection used fallback path for lrint_v2f16
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4f16
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8f16
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v16f16
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v32f16
-; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v1f32
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v2f32
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4f32
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8f32
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v16f32
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v32f32
-; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v1f64
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v2f64
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4f64
; CHECK-i32-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8f64
@@ -53,6 +50,9 @@
; CHECK-i64-GI-NEXT: warning: Instruction selection used fallback path for lrint_v4fp128
; CHECK-i64-GI-NEXT: warning: Instruction selection used fallback path for lrint_v8fp128
; CHECK-i64-GI-NEXT: warning: Instruction selection used fallback path for lrint_v16fp128
+;
+;
+;
define <1 x iXLen> @lrint_v1f16(<1 x half> %x) nounwind {
@@ -759,11 +759,11 @@ define <32 x iXLen> @lrint_v32f16(<32 x half> %x) nounwind {
declare <32 x iXLen> @llvm.lrint.v32iXLen.v32f16(<32 x half>)
define <1 x iXLen> @lrint_v1f32(<1 x float> %x) nounwind {
-; CHECK-i32-LABEL: lrint_v1f32:
-; CHECK-i32: // %bb.0:
-; CHECK-i32-NEXT: frintx v0.2s, v0.2s
-; CHECK-i32-NEXT: fcvtzs v0.2s, v0.2s
-; CHECK-i32-NEXT: ret
+; CHECK-i32-SD-LABEL: lrint_v1f32:
+; CHECK-i32-SD: // %bb.0:
+; CHECK-i32-SD-NEXT: frintx v0.2s, v0.2s
+; CHECK-i32-SD-NEXT: fcvtzs v0.2s, v0.2s
+; CHECK-i32-SD-NEXT: ret
;
; CHECK-i64-SD-LABEL: lrint_v1f32:
; CHECK-i64-SD: // %bb.0:
@@ -773,6 +773,13 @@ define <1 x iXLen> @lrint_v1f32(<1 x float> %x) nounwind {
; CHECK-i64-SD-NEXT: fmov d0, x8
; CHECK-i64-SD-NEXT: ret
;
+; CHECK-i32-GI-LABEL: lrint_v1f32:
+; CHECK-i32-GI: // %bb.0:
+; CHECK-i32-GI-NEXT: frintx s0, s0
+; CHECK-i32-GI-NEXT: fcvtzs w8, s0
+; CHECK-i32-GI-NEXT: fmov s0, w8
+; CHECK-i32-GI-NEXT: ret
+;
; CHECK-i64-GI-LABEL: lrint_v1f32:
; CHECK-i64-GI: // %bb.0:
; CHECK-i64-GI-NEXT: frintx s0, s0
@@ -1791,5 +1798,3 @@ define <16 x iXLen> @lrint_v16fp128(<16 x fp128> %x) nounwind {
}
declare <16 x iXLen> @llvm.lrint.v16iXLen.v16fp128(<16 x fp128>)
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK-i32-GI: {{.*}}
More information about the llvm-commits
mailing list