[llvm-commits] [llvm] r124183 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/InstructionSimplify.cpp lib/Analysis/ValueTracking.cpp test/Transforms/InstSimplify/2011-01-18-Compare.ll

Nick Lewycky nlewycky at google.com
Tue Jan 25 10:52:27 PST 2011


On 25 January 2011 01:38, Duncan Sands <baldrick at free.fr> wrote:

> Author: baldrick
> Date: Tue Jan 25 03:38:29 2011
> New Revision: 124183
>
> URL: http://llvm.org/viewvc/llvm-project?rev=124183&view=rev
> Log:
> According to my auto-simplifier the most common missed simplifications in
> optimized code are:
>  (non-negative number)+(power-of-two) != 0 -> true
>

i1 1 (non-negative number) + i1 1 (power-of-two) != 0 -> false. You probably
don't see this because we transform i1 add to xor very early on, but please
make sure we don't get it wrong when someone does create it.

and
>  (x | 1) != 0 -> true
> Instcombine knows about the second one of course, but only does it if X|1
> has only one use.  These fire thousands of times in the testsuite.
>
> Modified:
>    llvm/trunk/include/llvm/Analysis/ValueTracking.h
>    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
>    llvm/trunk/lib/Analysis/ValueTracking.cpp
>    llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll
>
> Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=124183&r1=124182&r2=124183&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)
> +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Tue Jan 25 03:38:29
> 2011
> @@ -39,6 +39,23 @@
>                          APInt &KnownOne, const TargetData *TD = 0,
>                          unsigned Depth = 0);
>
> +  /// ComputeSignBit - Determine whether the sign bit is known to be zero
> or
> +  /// one.  Convenience wrapper around ComputeMaskedBits.
> +  void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
> +                      const TargetData *TD = 0, unsigned Depth = 0);
> +
> +  /// isPowerOfTwo - Return true if the given value is known to have
> exactly one
> +  /// bit set when defined. For vectors return true if every element is
> known to
> +  /// be a power of two when defined.  Supports values with integer or
> pointer
> +  /// type and vectors of integers.
> +  bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth =
> 0);
> +
> +  /// isKnownNonZero - Return true if the given value is known to be
> non-zero
> +  /// when defined.  For vectors return true if every element is known to
> be
> +  /// non-zero when defined.  Supports values with integer or pointer type
> and
> +  /// vectors of integers.
> +  bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth =
> 0);
> +
>   /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.
>  We use
>   /// this predicate to simplify operations downstream.  Mask is known to
> be
>   /// zero for bits that V cannot have.
>
> Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=124183&r1=124182&r2=124183&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Tue Jan 25 03:38:29
> 2011
> @@ -22,6 +22,7 @@
>  #include "llvm/Analysis/InstructionSimplify.h"
>  #include "llvm/Analysis/ConstantFolding.h"
>  #include "llvm/Analysis/Dominators.h"
> +#include "llvm/Analysis/ValueTracking.h"
>  #include "llvm/Support/PatternMatch.h"
>  #include "llvm/Support/ValueHandle.h"
>  #include "llvm/Target/TargetData.h"
> @@ -1153,7 +1154,69 @@
>     }
>   }
>
> -  // See if we are doing a comparison with a constant.
> +  // icmp <alloca*>, <global/alloca*/null> - Different stack variables
> have
> +  // different addresses, and what's more the address of a stack variable
> is
> +  // never null or equal to the address of a global.  Note that
> generalizing
> +  // to the case where LHS is a global variable address or null is
> pointless,
> +  // since if both LHS and RHS are constants then we already constant
> folded
> +  // the compare, and if only one of them is then we moved it to RHS
> already.
> +  if (isa<AllocaInst>(LHS) && (isa<GlobalValue>(RHS) ||
> isa<AllocaInst>(RHS) ||
> +                               isa<ConstantPointerNull>(RHS)))
> +    // We already know that LHS != LHS.
> +    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
> +
> +  // If we are comparing with zero then try hard since this is a common
> case.
> +  if (match(RHS, m_Zero())) {
> +    bool LHSKnownNonNegative, LHSKnownNegative;
> +    switch (Pred) {
> +    default:
> +      assert(false && "Unknown ICmp predicate!");
> +    case ICmpInst::ICMP_ULT:
> +      return ConstantInt::getFalse(LHS->getContext());
> +    case ICmpInst::ICMP_UGE:
> +      return ConstantInt::getTrue(LHS->getContext());
> +    case ICmpInst::ICMP_EQ:
> +    case ICmpInst::ICMP_ULE:
> +      if (isKnownNonZero(LHS, TD))
> +        return ConstantInt::getFalse(LHS->getContext());
> +      break;
> +    case ICmpInst::ICMP_NE:
> +    case ICmpInst::ICMP_UGT:
> +      if (isKnownNonZero(LHS, TD))
> +        return ConstantInt::getTrue(LHS->getContext());
> +      break;
> +    case ICmpInst::ICMP_SLT:
> +      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
> +      if (LHSKnownNegative)
> +        return ConstantInt::getTrue(LHS->getContext());
> +      if (LHSKnownNonNegative)
> +        return ConstantInt::getFalse(LHS->getContext());
> +      break;
> +    case ICmpInst::ICMP_SLE:
> +      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
> +      if (LHSKnownNegative)
> +        return ConstantInt::getTrue(LHS->getContext());
> +      if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))
> +        return ConstantInt::getFalse(LHS->getContext());
> +      break;
> +    case ICmpInst::ICMP_SGE:
> +      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
> +      if (LHSKnownNegative)
> +        return ConstantInt::getFalse(LHS->getContext());
> +      if (LHSKnownNonNegative)
> +        return ConstantInt::getTrue(LHS->getContext());
> +      break;
> +    case ICmpInst::ICMP_SGT:
> +      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
> +      if (LHSKnownNegative)
> +        return ConstantInt::getFalse(LHS->getContext());
> +      if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))
> +        return ConstantInt::getTrue(LHS->getContext());
> +      break;
> +    }
> +  }
> +
> +  // See if we are doing a comparison with a constant integer.
>   if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
>     switch (Pred) {
>     default: break;
> @@ -1192,17 +1255,6 @@
>     }
>   }
>
> -  // icmp <alloca*>, <global/alloca*/null> - Different stack variables
> have
> -  // different addresses, and what's more the address of a stack variable
> is
> -  // never null or equal to the address of a global.  Note that
> generalizing
> -  // to the case where LHS is a global variable address or null is
> pointless,
> -  // since if both LHS and RHS are constants then we already constant
> folded
> -  // the compare, and if only one of them is then we moved it to RHS
> already.
> -  if (isa<AllocaInst>(LHS) && (isa<GlobalValue>(RHS) ||
> isa<AllocaInst>(RHS) ||
> -                               isa<ConstantPointerNull>(RHS)))
> -    // We already know that LHS != LHS.
> -    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
> -
>   // Compare of cast, for example (zext X) != 0 -> X != 0
>   if (isa<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {
>     Instruction *LI = cast<CastInst>(LHS);
>
> Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=124183&r1=124182&r2=124183&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
> +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Jan 25 03:38:29 2011
> @@ -24,9 +24,22 @@
>  #include "llvm/Target/TargetData.h"
>  #include "llvm/Support/GetElementPtrTypeIterator.h"
>  #include "llvm/Support/MathExtras.h"
> +#include "llvm/Support/PatternMatch.h"
>  #include "llvm/ADT/SmallPtrSet.h"
>  #include <cstring>
>  using namespace llvm;
> +using namespace llvm::PatternMatch;
> +
> +const unsigned MaxDepth = 6;
> +
> +/// getBitWidth - Returns the bitwidth of the given scalar or pointer type
> (if
> +/// unknown returns 0).  For vector types, returns the element type's
> bitwidth.
> +static unsigned getBitWidth(const Type *Ty, const TargetData *TD) {
> +  if (unsigned BitWidth = Ty->getScalarSizeInBits())
> +    return BitWidth;
> +  assert(isa<PointerType>(Ty) && "Expected a pointer type!");
> +  return TD ? TD->getPointerSizeInBits() : 0;
> +}
>
>  /// ComputeMaskedBits - Determine which of the bits specified in Mask are
>  /// known to be either zero or one and return them in the
> KnownZero/KnownOne
> @@ -47,7 +60,6 @@
>  void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
>                              APInt &KnownZero, APInt &KnownOne,
>                              const TargetData *TD, unsigned Depth) {
> -  const unsigned MaxDepth = 6;
>   assert(V && "No Value?");
>   assert(Depth <= MaxDepth && "Limit Search Depth");
>   unsigned BitWidth = Mask.getBitWidth();
> @@ -620,6 +632,157 @@
>   }
>  }
>
> +/// ComputeSignBit - Determine whether the sign bit is known to be zero or
> +/// one.  Convenience wrapper around ComputeMaskedBits.
> +void llvm::ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
> +                          const TargetData *TD, unsigned Depth) {
> +  unsigned BitWidth = getBitWidth(V->getType(), TD);
> +  if (!BitWidth) {
> +    KnownZero = false;
> +    KnownOne = false;
> +    return;
> +  }
> +  APInt ZeroBits(BitWidth, 0);
> +  APInt OneBits(BitWidth, 0);
> +  ComputeMaskedBits(V, APInt::getSignBit(BitWidth), ZeroBits, OneBits, TD,
> +                    Depth);
> +  KnownOne = OneBits[BitWidth - 1];
> +  KnownZero = ZeroBits[BitWidth - 1];
> +}
> +
> +/// isPowerOfTwo - Return true if the given value is known to have exactly
> one
> +/// bit set when defined. For vectors return true if every element is
> known to
> +/// be a power of two when defined.  Supports values with integer or
> pointer
> +/// types and vectors of integers.
> +bool llvm::isPowerOfTwo(Value *V, const TargetData *TD, unsigned Depth) {
> +  if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
> +    return CI->getValue().countPopulation() == 1;
> +  // TODO: Handle vector constants.
> +
> +  // 1 << X is clearly a power of two if the one is not shifted off the
> end.  If
> +  // it is shifted off the end then the result is undefined.
> +  if (match(V, m_Shl(m_One(), m_Value())))
> +    return true;
> +
> +  // (signbit) >>l X is clearly a power of two if the one is not shifted
> off the
> +  // bottom.  If it is shifted off the bottom then the result is
> undefined.
> +  ConstantInt *CI;
> +  if (match(V, m_LShr(m_ConstantInt(CI), m_Value())) &&
> +      CI->getValue().isSignBit())
> +    return true;
> +
> +  // The remaining tests are all recursive, so bail out if we hit the
> limit.
> +  if (Depth++ == MaxDepth)
> +    return false;
> +
> +  if (ZExtInst *ZI = dyn_cast<ZExtInst>(V))
> +    return isPowerOfTwo(ZI->getOperand(0), TD, Depth);
>
+
> +  if (SelectInst *SI = dyn_cast<SelectInst>(V))
> +    return isPowerOfTwo(SI->getTrueValue(), TD, Depth) &&
> +      isPowerOfTwo(SI->getFalseValue(), TD, Depth);
> +
> +  return false;
> +}
> +
> +/// isKnownNonZero - Return true if the given value is known to be
> non-zero
> +/// when defined.  For vectors return true if every element is known to be
> +/// non-zero when defined.  Supports values with integer or pointer type
> and
> +/// vectors of integers.
> +bool llvm::isKnownNonZero(Value *V, const TargetData *TD, unsigned Depth)
> {
> +  if (Constant *C = dyn_cast<Constant>(V)) {
> +    if (C->isNullValue())
> +      return false;
> +    if (isa<ConstantInt>(C))
> +      // Must be non-zero due to null test above.
> +      return true;
> +    // TODO: Handle vectors
> +    return false;
> +  }
> +
> +  // The remaining tests are all recursive, so bail out if we hit the
> limit.
> +  if (Depth++ == MaxDepth)
> +    return false;
> +
> +  unsigned BitWidth = getBitWidth(V->getType(), TD);
> +
> +  // X | Y != 0 if X != 0 or Y != 0.
> +  Value *X = 0, *Y = 0;
> +  if (match(V, m_Or(m_Value(X), m_Value(Y))))
> +    return isKnownNonZero(X, TD, Depth) || isKnownNonZero(Y, TD, Depth);
> +
> +  // ext X != 0 if X != 0.
> +  if (isa<SExtInst>(V) || isa<ZExtInst>(V))
> +    return isKnownNonZero(cast<Instruction>(V)->getOperand(0), TD, Depth);
> +
> +  // shl X, A != 0 if X is odd.  Note that the value of the shift is
> undefined
> +  // if the lowest bit is shifted off the end.
>

This is also true when A < BitWidth-CountTrailingZeros(X), but sadly we
don't have ctz function in value tracking yet.

+  if (BitWidth && match(V, m_Shl(m_Value(X), m_Value(Y)))) {
> +    APInt KnownZero(BitWidth, 0);
> +    APInt KnownOne(BitWidth, 0);
> +    ComputeMaskedBits(V, APInt(BitWidth, 1), KnownZero, KnownOne, TD,
> Depth);
> +    if (KnownOne[0])
> +      return true;
> +  }
> +  // shr X, A != 0 if X is negative.  Note that the value of the shift is
> not
> +  // defined if the sign bit is shifted off the end.
>

As above, this is true when A < BitWidth-ComputeNumSignBits() and X is
negative, except that this time we do have a ComputeNumSignBits function.


> +  else if (match(V, m_Shr(m_Value(X), m_Value(Y)))) {
> +    bool XKnownNonNegative, XKnownNegative;
> +    ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth);
> +    if (XKnownNegative)
> +      return true;
> +  }
> +  // X + Y.
> +  else if (match(V, m_Add(m_Value(X), m_Value(Y)))) {
>

This could handle subtraction too without much difficulty right?


> +    bool XKnownNonNegative, XKnownNegative;
> +    bool YKnownNonNegative, YKnownNegative;
> +    ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth);
> +    ComputeSignBit(Y, YKnownNonNegative, YKnownNegative, TD, Depth);
> +
> +    // If X and Y are both non-negative (as signed values) then their sum
> is not
> +    // zero.
> +    if (XKnownNonNegative && YKnownNonNegative)
> +      return true;
> +
> +    // If X and Y are both negative (as signed values) then their sum is
> not
> +    // zero unless both X and Y equal INT_MIN.
> +    if (BitWidth && XKnownNegative && YKnownNegative) {
> +      APInt KnownZero(BitWidth, 0);
> +      APInt KnownOne(BitWidth, 0);
> +      APInt Mask = APInt::getSignedMaxValue(BitWidth);
> +      // The sign bit of X is set.  If some other bit is set then X is not
> equal
> +      // to INT_MIN.
> +      ComputeMaskedBits(X, Mask, KnownZero, KnownOne, TD, Depth);
> +      if ((KnownOne & Mask) != 0)
> +        return true;
> +      // The sign bit of Y is set.  If some other bit is set then Y is not
> equal
> +      // to INT_MIN.
> +      ComputeMaskedBits(Y, Mask, KnownZero, KnownOne, TD, Depth);
> +      if ((KnownOne & Mask) != 0)
> +        return true;
> +    }
> +
> +    // The sum of a non-negative number and a power of two is not zero.
> +    if (XKnownNonNegative && isPowerOfTwo(Y, TD, Depth))
> +      return true;
> +    if (YKnownNonNegative && isPowerOfTwo(X, TD, Depth))
> +      return true;
> +  }
> +  // (C ? X : Y) != 0 if X != 0 and Y != 0.
> +  else if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
> +    if (isKnownNonZero(SI->getTrueValue(), TD, Depth) &&
> +        isKnownNonZero(SI->getFalseValue(), TD, Depth))
> +      return true;
> +  }
>

Since this function claims to support pointers, how about inttoptr
(recurse), ptrtoint (recurse), gep (non-zero when any argument is non-zero,
which is most of the time) and non-weak globals?

Nick

+
> +  if (!BitWidth) return false;
> +  APInt KnownZero(BitWidth, 0);
> +  APInt KnownOne(BitWidth, 0);
> +  ComputeMaskedBits(V, APInt::getAllOnesValue(BitWidth), KnownZero,
> KnownOne,
> +                    TD, Depth);
> +  return KnownOne != 0;
> +}
> +
>  /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.  We
> use
>  /// this predicate to simplify operations downstream.  Mask is known to be
> zero
>  /// for bits that V cannot have.
>
> Modified: llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll?rev=124183&r1=124182&r2=124183&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll
> (original)
> +++ llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll Tue Jan
> 25 03:38:29 2011
> @@ -27,6 +27,14 @@
>  ; CHECK: ret i1 %x
>  }
>
> +define i1 @zext3() {
> +; CHECK: @zext3
> +  %e = zext i1 1 to i32
> +  %c = icmp ne i32 %e, 0
> +  ret i1 %c
> +; CHECK: ret i1 true
> +}
> +
>  define i1 @sext(i32 %x) {
>  ; CHECK: @sext
>   %e1 = sext i32 %x to i64
> @@ -43,3 +51,49 @@
>   ret i1 %c
>  ; CHECK: ret i1 %x
>  }
> +
> +define i1 @sext3() {
> +; CHECK: @sext3
> +  %e = sext i1 1 to i32
> +  %c = icmp ne i32 %e, 0
> +  ret i1 %c
> +; CHECK: ret i1 true
> +}
> +
> +define i1 @add(i32 %x, i32 %y) {
> +; CHECK: @add
> +  %l = lshr i32 %x, 1
> +  %r = lshr i32 %y, 1
> +  %s = add i32 %l, %r
> +  %c = icmp eq i32 %s, 0
> +  ret i1 %c
> +; CHECK: ret i1 false
> +}
> +
> +define i1 @add2(i8 %x, i8 %y) {
> +; CHECK: @add2
> +  %l = or i8 %x, 128
> +  %r = or i8 %y, 129
> +  %s = add i8 %l, %r
> +  %c = icmp eq i8 %s, 0
> +  ret i1 %c
> +; CHECK: ret i1 false
> +}
> +
> +define i1 @addpowtwo(i32 %x, i32 %y) {
> +; CHECK: @addpowtwo
> +  %l = lshr i32 %x, 1
> +  %r = shl i32 1, %y
> +  %s = add i32 %l, %r
> +  %c = icmp eq i32 %s, 0
> +  ret i1 %c
> +; CHECK: ret i1 false
> +}
> +
> +define i1 @or(i32 %x) {
> +; CHECK: @or
> +  %o = or i32 %x, 1
> +  %c = icmp eq i32 %o, 0
> +  ret i1 %c
> +; CHECK: ret i1 false
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20110125/d90ce61f/attachment.html>


More information about the llvm-commits mailing list