[llvm] [GlobalISel] Fix inverted libcall status check in createFCMPLibcall (PR #219242)

Daniel Paoliello via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 09:56:52 PDT 2026


https://github.com/dpaoliello created https://github.com/llvm/llvm-project/pull/219242

BuildLibcall tested `if (!Status)` on the LegalizeResult returned by createLibcall. Since LegalizeResult is an enum with AlreadyLegal == 0, that condition is false for both Legalized and UnableToLegalize, so a failed libcall was never detected. The helper then built an ICMP against the undefined result register and reported success, so the legalizer never fell back.

Check `Status != Legalized` instead, so failures propagate and the caller can bail out.

On arm64ec, GlobalISel call lowering is unimplemented, so this silently dropped `fp128` compare libcalls at `-O0`. Add a test that checks the expected `__eqtf2`, `__lttf2` and `__unordtf2` calls are emitted at both `-O0` and `-O2`.

>From 9998da7b9066ffa077e188c32a878fbb83870291 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao at microsoft.com>
Date: Thu, 27 Aug 2026 09:54:25 -0700
Subject: [PATCH] [GlobalISel] Fix inverted libcall status check in
 createFCMPLibcall

BuildLibcall tested `if (!Status)` on the LegalizeResult returned by
createLibcall. Since LegalizeResult is an enum with AlreadyLegal == 0,
that condition is false for both Legalized and UnableToLegalize, so a
failed libcall was never detected. The helper then built an ICMP against
the undefined result register and reported success, so the legalizer
never fell back.

Check `Status != Legalized` instead, so failures propagate and the
caller can bail out.

On arm64ec, GlobalISel call lowering is unimplemented, so this silently
dropped `fp128` compare libcalls at `-O0`. Add a test that checks the
expected `__eqtf2`, `__lttf2` and `__unordtf2` calls are emitted at both `-O0` and
`-O2`.
---
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    |  2 +-
 .../test/CodeGen/AArch64/arm64ec-fp128-cmp.ll | 33 +++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/AArch64/arm64ec-fp128-cmp.ll

diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index b46a5b26e0b6a..4ab02b0b12bff 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1205,7 +1205,7 @@ LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
         Libcall, {Temp, Type::getInt32Ty(Ctx), 0},
         {{Cmp->getLHSReg(), OpType, 0}, {Cmp->getRHSReg(), OpType, 1}},
         LocObserver, &MI);
-    if (!Status)
+    if (Status != Legalized)
       return {};
 
     // Compare temp with #0 to get the final result.
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-fp128-cmp.ll b/llvm/test/CodeGen/AArch64/arm64ec-fp128-cmp.ll
new file mode 100644
index 0000000000000..db3df7737743f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64ec-fp128-cmp.ll
@@ -0,0 +1,33 @@
+; GlobalISel is the default selector at -O0, but Arm64EC call lowering is
+; unimplemented there, so fp128 compares must fall back to SelectionDAG rather
+; than silently dropping the libcall.
+; RUN: llc -mtriple=arm64ec-pc-windows-msvc -O0 < %s | FileCheck %s
+; RUN: llc -mtriple=arm64ec-pc-windows-msvc -O2 < %s | FileCheck %s
+
+define i1 @cmp_oeq(fp128 %a, fp128 %b) {
+; CHECK-LABEL: "#cmp_oeq":
+; CHECK: bl "#__eqtf2"
+  %r = fcmp oeq fp128 %a, %b
+  ret i1 %r
+}
+
+define i1 @cmp_olt(fp128 %a, fp128 %b) {
+; CHECK-LABEL: "#cmp_olt":
+; CHECK: bl "#__lttf2"
+  %r = fcmp olt fp128 %a, %b
+  ret i1 %r
+}
+
+define i1 @cmp_uno(fp128 %a, fp128 %b) {
+; CHECK-LABEL: "#cmp_uno":
+; CHECK: bl "#__unordtf2"
+  %r = fcmp uno fp128 %a, %b
+  ret i1 %r
+}
+
+define i1 @cmp_une_self(fp128 %a) {
+; CHECK-LABEL: "#cmp_une_self":
+; CHECK: bl "#__unordtf2"
+  %r = fcmp une fp128 %a, %a
+  ret i1 %r
+}



More information about the llvm-commits mailing list