Skip to content

Conversation

@davemgreen
Copy link
Collaborator

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 legalise in the same manner.

@llvmbot
Copy link
Member

llvmbot commented Dec 1, 2025

@llvm/pr-subscribers-llvm-globalisel

Author: David Green (davemgreen)

Changes

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 legalise in the same manner.


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

7 Files Affected:

  • (modified) llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp (+7-6)
  • (modified) llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir (+1-1)
  • (modified) llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll (+1-5)
  • (modified) llvm/test/CodeGen/AArch64/lrint-conv-win.ll (+1-6)
  • (modified) llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll (+18-38)
  • (modified) llvm/test/CodeGen/AArch64/lround-conv-win.ll (+20-43)
  • (modified) llvm/test/CodeGen/AArch64/vector-lrint.ll (+17-12)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..19b4afadcc571 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -432,10 +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,
@@ -451,9 +447,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: {{.*}}

@llvmbot
Copy link
Member

llvmbot commented Dec 1, 2025

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

Changes

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 legalise in the same manner.


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

7 Files Affected:

  • (modified) llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp (+7-6)
  • (modified) llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir (+1-1)
  • (modified) llvm/test/CodeGen/AArch64/lrint-conv-fp16-win.ll (+1-5)
  • (modified) llvm/test/CodeGen/AArch64/lrint-conv-win.ll (+1-6)
  • (modified) llvm/test/CodeGen/AArch64/lround-conv-fp16-win.ll (+18-38)
  • (modified) llvm/test/CodeGen/AArch64/lround-conv-win.ll (+20-43)
  • (modified) llvm/test/CodeGen/AArch64/vector-lrint.ll (+17-12)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..19b4afadcc571 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -432,10 +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,
@@ -451,9 +447,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: {{.*}}

@github-actions
Copy link

github-actions bot commented Dec 1, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

…int.

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.
getActionDefinitionsBuilder({G_LLROUND, G_INTRINSIC_LLRINT})
.legalFor({{s64, s32}, {s64, s64}})
.legalFor(HasFP16, {{s64, s16}})
.legalFor(HasFP16, {{s32, s16}, {s64, s16}})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the s32, s16 variant exist ? Even on windows it seems to always be i64.

Copy link
Contributor

@Lukacma Lukacma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@davemgreen davemgreen merged commit 4f2d209 into llvm:main Dec 4, 2025
10 checks passed
@davemgreen davemgreen deleted the gh-gi-lrint32 branch December 4, 2025 16:24
honeygoyal pushed a commit to honeygoyal/llvm-project that referenced this pull request Dec 9, 2025
…int (llvm#170175)

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 legalise in the same manner.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants