[PATCH] D28927: [ValueTracking] Add comment that CannotBeOrderedLessThanZero does the wrong thing for powi.

Justin Lebar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 19 16:48:05 PST 2017

jlebar created this revision.

CannotBeOrderedLessThanZero(powi(x, exp)) returns true if
CannotBeOrderedLessThanZero(x).  But powi(-0, exp) is negative if exp is
odd, so we actually want to return SignBitMustBeZero(x).

Except that also isn't right, because we want to return true if x is
NaN, even if x has a negative sign bit.

What we really need in order to fix this is a consistent approach in
this function to handling the sign bit of NaNs.  Without this it's very
difficult to say what the correct behavior here is.



Index: llvm/lib/Analysis/ValueTracking.cpp
--- llvm/lib/Analysis/ValueTracking.cpp
+++ llvm/lib/Analysis/ValueTracking.cpp
@@ -2602,6 +2602,12 @@
                                             const TargetLibraryInfo *TLI,
                                             bool SignBitOnly,
                                             unsigned Depth) {
+  // TODO: We are not consistent about how we handle the sign bit of propagated
+  // NaNs.  IEEE 754 section 6.3 says that the sign bit of a NaN returned by an
+  // operation is unspecified.  In some but not all places in this function, we
+  // assume the sign bit is 0.  We should have a principled approach here one
+  // way or another.
   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
     return !CFP->getValueAPF().isNegative() ||
            (!SignBitOnly && CFP->getValueAPF().isZero());
@@ -2670,8 +2676,23 @@
         if (CI->getBitWidth() <= 64 && CI->getSExtValue() % 2u == 0)
           return true;
+      // TODO: This is not correct.  Given that exp is an integer, here are the
+      // ways that pow can return a negative value:
+      //
+      //   pow(x, exp)    --> negative if exp is odd and x is negative.
+      //   pow(-0, exp)   --> -inf if exp is negative odd.
+      //   pow(-0, exp)   --> -0 if exp is positive odd.
+      //   pow(-inf, exp) --> -0 if exp is negative odd.
+      //   pow(-inf, exp) --> -inf if exp is positive odd.
+      //
+      // It's therefore sufficient to prove that x is positive (or NaN) but we
+      // must exclude x == -0 even if we normally would return true for -0.
+      // Fixing this without regressing existing cases that we correctly
+      // optimize probably requires adopting a principled approach to handling
+      // the sign bits of NaNs; see the TODO at the top of this function.
       return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
                                              Depth + 1);
     case Intrinsic::fma:
     case Intrinsic::fmuladd:
       // x*x+y is non-negative if y is non-negative.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28927.85062.patch
Type: text/x-patch
Size: 2153 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170120/444bad1a/attachment.bin>

More information about the llvm-commits mailing list