[llvm] 3ad43f2 - [LangRef] Clarify nsz semantics (#180906)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 01:53:11 PST 2026
Author: Nikita Popov
Date: 2026-03-02T10:53:07+01:00
New Revision: 3ad43f2d1c03f7f04bd2943e9411a7986b1962c3
URL: https://github.com/llvm/llvm-project/commit/3ad43f2d1c03f7f04bd2943e9411a7986b1962c3
DIFF: https://github.com/llvm/llvm-project/commit/3ad43f2d1c03f7f04bd2943e9411a7986b1962c3.diff
LOG: [LangRef] Clarify nsz semantics (#180906)
The current LangRef wording says that the sign of a zero argument or
result is "insignificant", which is not really clear on what this means.
Alive2 models this as non-deterministically flipping the zero sign bits
for both inputs and outputs.
This PR proposes to specify this flag as non-deterministically flipping
inputs only. A consequence of this is that fabs is guaranteed to have an
unset sign bit even if the input is zero (that is,
https://alive2.llvm.org/ce/z/irCftQ is no longer a valid transform), and
that the copysign result sign only depends on the second operand (that
is, https://alive2.llvm.org/ce/z/VnHdfh is no longer a valid transform).
These rules are still more liberal than we'd really like them to be, but
at least avoid some of the issues with nsz.
This is based on the discussion in:
https://discourse.llvm.org/t/rfc-clarify-the-behavior-of-fp-operations-on-bit-strings-with-nsz-flag/85981
Added:
Modified:
llvm/docs/LangRef.rst
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/intrinsic-select.ll
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index be1765660d36d..a1835436ae359 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4173,9 +4173,9 @@ following flags to enable otherwise unsafe floating-point transformations.
produces a :ref:`poison value <poisonvalues>` instead.
``nsz``
- No Signed Zeros - Allow optimizations to treat the sign of a zero
- argument or zero result as insignificant. This does not imply that -0.0
- is poison and/or guaranteed to not exist in the operation.
+ No Signed Zeros - Unless otherwise mentioned, the sign bit of 0.0 or -0.0
+ input operands can be non-deterministically flipped. This does not imply
+ that -0.0 is poison and/or guaranteed to not exist in the operation.
Note: For :ref:`phi <i_phi>`, :ref:`select <i_select>`, and :ref:`call <i_call>`
instructions, the following return types are considered to be floating-point
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 3585c787bb880..55a70115feb36 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3126,10 +3126,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
CallInst *AbsT = Builder.CreateCall(II->getCalledFunction(), {TVal});
CallInst *AbsF = Builder.CreateCall(II->getCalledFunction(), {FVal});
SelectInst *SI = SelectInst::Create(Cond, AbsT, AbsF);
- FastMathFlags FMF1 = II->getFastMathFlags();
- FastMathFlags FMF2 = cast<SelectInst>(Arg)->getFastMathFlags();
- FMF2.setNoSignedZeros(false);
- SI->setFastMathFlags(FMF1 | FMF2);
+ SI->setFastMathFlags(II->getFastMathFlags() |
+ cast<SelectInst>(Arg)->getFastMathFlags());
+ // Can't copy nsz to select, as even with the nsz flag the fabs result
+ // always has the sign bit unset.
+ SI->setHasNoSignedZeros(false);
return SI;
}
// fabs (select Cond, -FVal, FVal) --> fabs FVal
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-select.ll b/llvm/test/Transforms/InstCombine/intrinsic-select.ll
index aa4168918d939..5678a964b6be8 100644
--- a/llvm/test/Transforms/InstCombine/intrinsic-select.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsic-select.ll
@@ -337,7 +337,7 @@ define double @test_fabs_select_fmf1(i1 %cond, double %a) {
define double @test_fabs_select_fmf2(i1 %cond, double %a) {
; CHECK-LABEL: @test_fabs_select_fmf2(
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
-; CHECK-NEXT: [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]
+; CHECK-NEXT: [[SEL1:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]
; CHECK-NEXT: ret double [[SEL1]]
;
%sel1 = select i1 %cond, double 0.0, double %a
More information about the llvm-commits
mailing list