[ValueTracking] fix CannotBeNegativeZero() to disregard 'nsz' FMF
authorSanjay Patel <spatel@rotateright.com>
Tue, 5 May 2020 20:02:45 +0000 (16:02 -0400)
committerSanjay Patel <spatel@rotateright.com>
Tue, 5 May 2020 20:04:59 +0000 (16:04 -0400)
The 'nsz' flag is different than 'nnan' or 'ninf' in that it does not create poison.
Make that explicit in the LangRef and fix ValueTracking analysis that misinterpreted
the definition.

This manifests as bugs in InstSimplify shown in the test diffs and as discussed in
PR45778:
https://bugs.llvm.org/show_bug.cgi?id=45778

Differential Revision: https://reviews.llvm.org/D79422

llvm/docs/LangRef.rst
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/InstSimplify/fast-math.ll

index cddb570..0bcb7cd 100644 (file)
@@ -2727,7 +2727,8 @@ floating-point transformations.
 
 ``nsz``
    No Signed Zeros - Allow optimizations to treat the sign of a zero
-   argument or result as insignificant.
+   argument or result as insignificant. This does not imply that -0.0
+   is poison and/or guaranteed to not exist in the operation.
 
 ``arcp``
    Allow Reciprocal - Allow optimizations to use the reciprocal of an
index 3d1e627..b02a4d2 100644 (file)
@@ -3202,6 +3202,9 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(const CallBase &CB,
 
 /// Return true if we can prove that the specified FP value is never equal to
 /// -0.0.
+/// NOTE: Do not check 'nsz' here because that fast-math-flag does not guarantee
+///       that a value is not -0.0. It only guarantees that -0.0 may be treated
+///       the same as +0.0 in floating-point ops.
 ///
 /// NOTE: this function will need to be revisited when we support non-default
 /// rounding modes!
@@ -3218,11 +3221,6 @@ bool llvm::CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI,
   if (!Op)
     return false;
 
-  // Check if the nsz fast-math flag is set.
-  if (auto *FPO = dyn_cast<FPMathOperator>(Op))
-    if (FPO->hasNoSignedZeros())
-      return true;
-
   // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
   if (match(Op, m_FAdd(m_Value(), m_PosZeroFP())))
     return true;
index a53d6ff..2eea3ef 100644 (file)
@@ -293,10 +293,13 @@ define float @fold_fadd_nsz_x_0(float %a) {
   ret float %add
 }
 
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
 define float @fold_fadd_cannot_be_neg0_nsz_src_x_0(float %a, float %b) {
 ; CHECK-LABEL: @fold_fadd_cannot_be_neg0_nsz_src_x_0(
 ; CHECK-NEXT:    [[NSZ:%.*]] = fmul nsz float [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    ret float [[NSZ]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[NSZ]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
 ;
   %nsz = fmul nsz float %a, %b
   %add = fadd float %nsz, 0.0
@@ -313,11 +316,14 @@ define float @fold_fadd_cannot_be_neg0_fabs_src_x_0(float %a) {
   ret float %add
 }
 
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
 define float @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(float %a, float %b) {
 ; CHECK-LABEL: @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(
 ; CHECK-NEXT:    [[NSZ:%.*]] = fmul nsz float [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[NSZ]])
-; CHECK-NEXT:    ret float [[SQRT]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[SQRT]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
 ;
   %nsz = fmul nsz float %a, %b
   %sqrt = call float @llvm.sqrt.f32(float %nsz)
@@ -325,11 +331,14 @@ define float @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(float %a, float %b) {
   ret float %add
 }
 
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
 define float @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0(float %a, float %b) {
 ; CHECK-LABEL: @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0(
 ; CHECK-NEXT:    [[NSZ:%.*]] = fmul nsz float [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[NSZ]])
-; CHECK-NEXT:    ret float [[CANON]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[CANON]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
 ;
   %nsz = fmul nsz float %a, %b
   %canon = call float @llvm.canonicalize.f32(float %nsz)