This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 84d05e9a24 [LLVM][Codegen] Cast NaN to bool gives true (#18772)
84d05e9a24 is described below
commit 84d05e9a24e1587886eef7552f9d80c475637e7e
Author: Nguyen Duy Loc <[email protected]>
AuthorDate: Fri Feb 13 19:21:27 2026 +0700
[LLVM][Codegen] Cast NaN to bool gives true (#18772)
Due to some recent changes to CI, PR #18646 will be closed and a new PR
created. This PR was created by opening a new pull request on the main
branch.
- Update test code: using tvmscript instead of schedule te.
### Summary
Cast NaN to bool gives true to ensure consistency with the existing
framework (C, C++, Python, Torch, NumPy, OnnxRuntime, ...).
### Steps to Reproduce
- Python:
```
bool(float('nan'))
```
> True
- Torch:
```
torch.tensor(float("nan"), dtype=torch.float32).to(torch.bool)
```
> tensor(True)
- Numpy:
```
import numpy as np
bool(np.nan)
```
> True
- TVM:
```
class Module:
def main(x: R.Tensor((), dtype="float32")) -> R.Tensor((),
dtype="bool"):
with R.dataflow():
gv: R.Tensor((), dtype="bool") = R.astype(x, dtype="bool")
R.output(gv)
return gv
x = np.array(float("nan"), dtype="float32")
```
> False
### Expected
- TVM:
```
class Module:
def main(x: R.Tensor((), dtype="float32")) -> R.Tensor((),
dtype="bool"):
with R.dataflow():
gv: R.Tensor((), dtype="bool") = R.astype(x, dtype="bool")
R.output(gv)
return gv
x = np.array(float("nan"), dtype="float32")
```
> True
### Resolved
- Replace the instruction `fcmp one` with `fcmp une` in LLVM.
- Citation:
https://releases.llvm.org/20.1.0/docs/LangRef.html#fcmp-instruction
<img width="400" height="200" alt="PR1-18605"
src="https://github.com/user-attachments/assets/cffeebd8-dfe6-436e-9c4c-61e1e84d5439"
/>
- Related:
+
https://stackoverflow.com/questions/9158567/nan-to-bool-conversion-true-or-false
+
https://stackoverflow.com/questions/15686318/why-do-not-a-number-values-equal-true-when-cast-as-boolean-in-python-numpy
- Fixed: #18605
---
src/target/llvm/codegen_llvm.cc | 2 +-
tests/python/codegen/test_target_codegen_llvm.py | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc
index 0a2ae8b09e..b7004dec32 100644
--- a/src/target/llvm/codegen_llvm.cc
+++ b/src/target/llvm/codegen_llvm.cc
@@ -928,7 +928,7 @@ llvm::Value* CodeGenLLVM::CreateCast(DataType from,
DataType to, llvm::Value* va
} else if (to.is_bool()) {
if (from.is_float()) {
llvm::Constant* zero = llvm::ConstantFP::get(DTypeToLLVMType(from), 0.);
- return builder_->CreateFCmpONE(value, zero);
+ return builder_->CreateFCmpUNE(value, zero);
} else {
llvm::Constant* zero = llvm::ConstantInt::get(DTypeToLLVMType(from), 0);
return builder_->CreateICmpNE(value, zero);
diff --git a/tests/python/codegen/test_target_codegen_llvm.py
b/tests/python/codegen/test_target_codegen_llvm.py
index da58f5bb45..78f2abf523 100644
--- a/tests/python/codegen/test_target_codegen_llvm.py
+++ b/tests/python/codegen/test_target_codegen_llvm.py
@@ -370,6 +370,30 @@ def test_llvm_bool():
tvm.testing.assert_allclose(c.numpy(), c_np)
[email protected]_llvm
+def test_llvm_cast_float_to_bool():
+ @I.ir_module
+ class Module:
+ @T.prim_func
+ def main(A: T.Buffer((4,), "float32"), C: T.Buffer((4,), "bool")):
+ T.func_attr({"tir.noalias": True})
+ for i in range(4):
+ with T.sblock("C"):
+ v_i = T.axis.spatial(4, i)
+ T.reads(A[v_i])
+ T.writes(C[v_i])
+ C[v_i] = T.Cast("bool", A[v_i])
+
+ n = 4
+ f = tvm.compile(Module, target="llvm")
+ dev = tvm.cpu(0)
+ a = tvm.runtime.tensor(np.array([0.0, 1.0, np.nan, np.inf],
dtype="float32"), dev)
+ c = tvm.runtime.empty((n,), dtype="bool", device=dev)
+ f(a, c)
+ c_np = np.array([False, True, True, True], dtype="bool")
+ tvm.testing.assert_allclose(c.numpy(), c_np)
+
+
@tvm.testing.requires_llvm
def test_rank_zero():
@I.ir_module