[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 cddb5700a83998cfab5df8818c1b207909fa3513..0bcb7cda76dbf0d1329334713a07e89627354c7e 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 3d1e627e3df9e55d2159667ef9a3e31e972f2102..b02a4d236e996008a3dcc8fe6022ff0830ef899c 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 a53d6ff6982c2cb9a29dfb3f1a1faa4d3d46b571..2eea3efb1cd11006869338c3d099e6889b887c84 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)