[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