<div class="gmail_quote">On 25 January 2011 01:38, Duncan Sands <span dir="ltr"><<a href="mailto:baldrick@free.fr">baldrick@free.fr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

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

<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
and<br>
  (x | 1) != 0 -> true<br>
Instcombine knows about the second one of course, but only does it if X|1<br>
has only one use.  These fire thousands of times in the testsuite.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/Analysis/ValueTracking.h<br>
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp<br>
    llvm/trunk/lib/Analysis/ValueTracking.cpp<br>
    llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll<br>
<br>
Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=124183&r1=124182&r2=124183&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=124183&r1=124182&r2=124183&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Tue Jan 25 03:38:29 2011<br>
@@ -39,6 +39,23 @@<br>
                          APInt &KnownOne, const TargetData *TD = 0,<br>
                          unsigned Depth = 0);<br>
<br>
+  /// ComputeSignBit - Determine whether the sign bit is known to be zero or<br>
+  /// one.  Convenience wrapper around ComputeMaskedBits.<br>
+  void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,<br>
+                      const TargetData *TD = 0, unsigned Depth = 0);<br>
+<br>
+  /// isPowerOfTwo - Return true if the given value is known to have exactly one<br>
+  /// bit set when defined. For vectors return true if every element is known to<br>
+  /// be a power of two when defined.  Supports values with integer or pointer<br>
+  /// type and vectors of integers.<br>
+  bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0);<br>
+<br>
+  /// isKnownNonZero - Return true if the given value is known to be non-zero<br>
+  /// when defined.  For vectors return true if every element is known to be<br>
+  /// non-zero when defined.  Supports values with integer or pointer type and<br>
+  /// vectors of integers.<br>
+  bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0);<br>
+<br>
   /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.  We use<br>
   /// this predicate to simplify operations downstream.  Mask is known to be<br>
   /// zero for bits that V cannot have.<br>
<br>
Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=124183&r1=124182&r2=124183&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=124183&r1=124182&r2=124183&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Tue Jan 25 03:38:29 2011<br>
@@ -22,6 +22,7 @@<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
 #include "llvm/Analysis/ConstantFolding.h"<br>
 #include "llvm/Analysis/Dominators.h"<br>
+#include "llvm/Analysis/ValueTracking.h"<br>
 #include "llvm/Support/PatternMatch.h"<br>
 #include "llvm/Support/ValueHandle.h"<br>
 #include "llvm/Target/TargetData.h"<br>
@@ -1153,7 +1154,69 @@<br>
     }<br>
   }<br>
<br>
-  // See if we are doing a comparison with a constant.<br>
+  // icmp <alloca*>, <global/alloca*/null> - Different stack variables have<br>
+  // different addresses, and what's more the address of a stack variable is<br>
+  // never null or equal to the address of a global.  Note that generalizing<br>
+  // to the case where LHS is a global variable address or null is pointless,<br>
+  // since if both LHS and RHS are constants then we already constant folded<br>
+  // the compare, and if only one of them is then we moved it to RHS already.<br>
+  if (isa<AllocaInst>(LHS) && (isa<GlobalValue>(RHS) || isa<AllocaInst>(RHS) ||<br>
+                               isa<ConstantPointerNull>(RHS)))<br>
+    // We already know that LHS != LHS.<br>
+    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));<br>
+<br>
+  // If we are comparing with zero then try hard since this is a common case.<br>
+  if (match(RHS, m_Zero())) {<br>
+    bool LHSKnownNonNegative, LHSKnownNegative;<br>
+    switch (Pred) {<br>
+    default:<br>
+      assert(false && "Unknown ICmp predicate!");<br>
+    case ICmpInst::ICMP_ULT:<br>
+      return ConstantInt::getFalse(LHS->getContext());<br>
+    case ICmpInst::ICMP_UGE:<br>
+      return ConstantInt::getTrue(LHS->getContext());<br>
+    case ICmpInst::ICMP_EQ:<br>
+    case ICmpInst::ICMP_ULE:<br>
+      if (isKnownNonZero(LHS, TD))<br>
+        return ConstantInt::getFalse(LHS->getContext());<br>
+      break;<br>
+    case ICmpInst::ICMP_NE:<br>
+    case ICmpInst::ICMP_UGT:<br>
+      if (isKnownNonZero(LHS, TD))<br>
+        return ConstantInt::getTrue(LHS->getContext());<br>
+      break;<br>
+    case ICmpInst::ICMP_SLT:<br>
+      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);<br>
+      if (LHSKnownNegative)<br>
+        return ConstantInt::getTrue(LHS->getContext());<br>
+      if (LHSKnownNonNegative)<br>
+        return ConstantInt::getFalse(LHS->getContext());<br>
+      break;<br>
+    case ICmpInst::ICMP_SLE:<br>
+      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);<br>
+      if (LHSKnownNegative)<br>
+        return ConstantInt::getTrue(LHS->getContext());<br>
+      if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))<br>
+        return ConstantInt::getFalse(LHS->getContext());<br>
+      break;<br>
+    case ICmpInst::ICMP_SGE:<br>
+      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);<br>
+      if (LHSKnownNegative)<br>
+        return ConstantInt::getFalse(LHS->getContext());<br>
+      if (LHSKnownNonNegative)<br>
+        return ConstantInt::getTrue(LHS->getContext());<br>
+      break;<br>
+    case ICmpInst::ICMP_SGT:<br>
+      ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);<br>
+      if (LHSKnownNegative)<br>
+        return ConstantInt::getFalse(LHS->getContext());<br>
+      if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))<br>
+        return ConstantInt::getTrue(LHS->getContext());<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  // See if we are doing a comparison with a constant integer.<br>
   if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {<br>
     switch (Pred) {<br>
     default: break;<br>
@@ -1192,17 +1255,6 @@<br>
     }<br>
   }<br>
<br>
-  // icmp <alloca*>, <global/alloca*/null> - Different stack variables have<br>
-  // different addresses, and what's more the address of a stack variable is<br>
-  // never null or equal to the address of a global.  Note that generalizing<br>
-  // to the case where LHS is a global variable address or null is pointless,<br>
-  // since if both LHS and RHS are constants then we already constant folded<br>
-  // the compare, and if only one of them is then we moved it to RHS already.<br>
-  if (isa<AllocaInst>(LHS) && (isa<GlobalValue>(RHS) || isa<AllocaInst>(RHS) ||<br>
-                               isa<ConstantPointerNull>(RHS)))<br>
-    // We already know that LHS != LHS.<br>
-    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));<br>
-<br>
   // Compare of cast, for example (zext X) != 0 -> X != 0<br>
   if (isa<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {<br>
     Instruction *LI = cast<CastInst>(LHS);<br>
<br>
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=124183&r1=124182&r2=124183&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=124183&r1=124182&r2=124183&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Jan 25 03:38:29 2011<br>
@@ -24,9 +24,22 @@<br>
 #include "llvm/Target/TargetData.h"<br>
 #include "llvm/Support/GetElementPtrTypeIterator.h"<br>
 #include "llvm/Support/MathExtras.h"<br>
+#include "llvm/Support/PatternMatch.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include <cstring><br>
 using namespace llvm;<br>
+using namespace llvm::PatternMatch;<br>
+<br>
+const unsigned MaxDepth = 6;<br>
+<br>
+/// getBitWidth - Returns the bitwidth of the given scalar or pointer type (if<br>
+/// unknown returns 0).  For vector types, returns the element type's bitwidth.<br>
+static unsigned getBitWidth(const Type *Ty, const TargetData *TD) {<br>
+  if (unsigned BitWidth = Ty->getScalarSizeInBits())<br>
+    return BitWidth;<br>
+  assert(isa<PointerType>(Ty) && "Expected a pointer type!");<br>
+  return TD ? TD->getPointerSizeInBits() : 0;<br>
+}<br>
<br>
 /// ComputeMaskedBits - Determine which of the bits specified in Mask are<br>
 /// known to be either zero or one and return them in the KnownZero/KnownOne<br>
@@ -47,7 +60,6 @@<br>
 void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,<br>
                              APInt &KnownZero, APInt &KnownOne,<br>
                              const TargetData *TD, unsigned Depth) {<br>
-  const unsigned MaxDepth = 6;<br>
   assert(V && "No Value?");<br>
   assert(Depth <= MaxDepth && "Limit Search Depth");<br>
   unsigned BitWidth = Mask.getBitWidth();<br>
@@ -620,6 +632,157 @@<br>
   }<br>
 }<br>
<br>
+/// ComputeSignBit - Determine whether the sign bit is known to be zero or<br>
+/// one.  Convenience wrapper around ComputeMaskedBits.<br>
+void llvm::ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,<br>
+                          const TargetData *TD, unsigned Depth) {<br>
+  unsigned BitWidth = getBitWidth(V->getType(), TD);<br>
+  if (!BitWidth) {<br>
+    KnownZero = false;<br>
+    KnownOne = false;<br>
+    return;<br>
+  }<br>
+  APInt ZeroBits(BitWidth, 0);<br>
+  APInt OneBits(BitWidth, 0);<br>
+  ComputeMaskedBits(V, APInt::getSignBit(BitWidth), ZeroBits, OneBits, TD,<br>
+                    Depth);<br>
+  KnownOne = OneBits[BitWidth - 1];<br>
+  KnownZero = ZeroBits[BitWidth - 1];<br>
+}<br>
+<br>
+/// isPowerOfTwo - Return true if the given value is known to have exactly one<br>
+/// bit set when defined. For vectors return true if every element is known to<br>
+/// be a power of two when defined.  Supports values with integer or pointer<br>
+/// types and vectors of integers.<br>
+bool llvm::isPowerOfTwo(Value *V, const TargetData *TD, unsigned Depth) {<br>
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(V))<br>
+    return CI->getValue().countPopulation() == 1;<br>
+  // TODO: Handle vector constants.<br>
+<br>
+  // 1 << X is clearly a power of two if the one is not shifted off the end.  If<br>
+  // it is shifted off the end then the result is undefined.<br>
+  if (match(V, m_Shl(m_One(), m_Value())))<br>
+    return true;<br>
+<br>
+  // (signbit) >>l X is clearly a power of two if the one is not shifted off the<br>
+  // bottom.  If it is shifted off the bottom then the result is undefined.<br>
+  ConstantInt *CI;<br>
+  if (match(V, m_LShr(m_ConstantInt(CI), m_Value())) &&<br>
+      CI->getValue().isSignBit())<br>
+    return true;<br>
+<br>
+  // The remaining tests are all recursive, so bail out if we hit the limit.<br>
+  if (Depth++ == MaxDepth)<br>
+    return false;<br>
+<br>
+  if (ZExtInst *ZI = dyn_cast<ZExtInst>(V))<br>
+    return isPowerOfTwo(ZI->getOperand(0), TD, Depth);<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">+<br>
+  if (SelectInst *SI = dyn_cast<SelectInst>(V))<br>
+    return isPowerOfTwo(SI->getTrueValue(), TD, Depth) &&<br>
+      isPowerOfTwo(SI->getFalseValue(), TD, Depth);<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+/// isKnownNonZero - Return true if the given value is known to be non-zero<br>
+/// when defined.  For vectors return true if every element is known to be<br>
+/// non-zero when defined.  Supports values with integer or pointer type and<br>
+/// vectors of integers.<br>
+bool llvm::isKnownNonZero(Value *V, const TargetData *TD, unsigned Depth) {<br>
+  if (Constant *C = dyn_cast<Constant>(V)) {<br>
+    if (C->isNullValue())<br>
+      return false;<br>
+    if (isa<ConstantInt>(C))<br>
+      // Must be non-zero due to null test above.<br>
+      return true;<br>
+    // TODO: Handle vectors<br>
+    return false;<br>
+  }<br>
+<br>
+  // The remaining tests are all recursive, so bail out if we hit the limit.<br>
+  if (Depth++ == MaxDepth)<br>
+    return false;<br>
+<br>
+  unsigned BitWidth = getBitWidth(V->getType(), TD);<br>
+<br>
+  // X | Y != 0 if X != 0 or Y != 0.<br>
+  Value *X = 0, *Y = 0;<br>
+  if (match(V, m_Or(m_Value(X), m_Value(Y))))<br>
+    return isKnownNonZero(X, TD, Depth) || isKnownNonZero(Y, TD, Depth);<br>
+<br>
+  // ext X != 0 if X != 0.<br>
+  if (isa<SExtInst>(V) || isa<ZExtInst>(V))<br>
+    return isKnownNonZero(cast<Instruction>(V)->getOperand(0), TD, Depth);<br>
+<br>
+  // shl X, A != 0 if X is odd.  Note that the value of the shift is undefined<br>
+  // if the lowest bit is shifted off the end.<br></blockquote><div><br></div><div>This is also true when A < BitWidth-CountTrailingZeros(X), but sadly we don't have ctz function in value tracking yet.</div><div>

<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+  if (BitWidth && match(V, m_Shl(m_Value(X), m_Value(Y)))) {<br>
+    APInt KnownZero(BitWidth, 0);<br>
+    APInt KnownOne(BitWidth, 0);<br>
+    ComputeMaskedBits(V, APInt(BitWidth, 1), KnownZero, KnownOne, TD, Depth);<br>
+    if (KnownOne[0])<br>
+      return true;<br>
+  }<br>
+  // shr X, A != 0 if X is negative.  Note that the value of the shift is not<br>
+  // defined if the sign bit is shifted off the end.<br></blockquote><div><br></div><div>As above, this is true when A < BitWidth-ComputeNumSignBits() and X is negative, except that this time we do have a ComputeNumSignBits function.</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+  else if (match(V, m_Shr(m_Value(X), m_Value(Y)))) {<br>
+    bool XKnownNonNegative, XKnownNegative;<br>
+    ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth);<br>
+    if (XKnownNegative)<br>
+      return true;<br>
+  }<br>
+  // X + Y.<br>
+  else if (match(V, m_Add(m_Value(X), m_Value(Y)))) {<br></blockquote><div><br></div><div>This could handle subtraction too without much difficulty right?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">


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

<div><br></div><div>Nick</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+<br>
+  if (!BitWidth) return false;<br>
+  APInt KnownZero(BitWidth, 0);<br>
+  APInt KnownOne(BitWidth, 0);<br>
+  ComputeMaskedBits(V, APInt::getAllOnesValue(BitWidth), KnownZero, KnownOne,<br>
+                    TD, Depth);<br>
+  return KnownOne != 0;<br>
+}<br>
+<br>
 /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.  We use<br>
 /// this predicate to simplify operations downstream.  Mask is known to be zero<br>
 /// for bits that V cannot have.<br>
<br>
Modified: llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll?rev=124183&r1=124182&r2=124183&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll?rev=124183&r1=124182&r2=124183&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstSimplify/2011-01-18-Compare.ll Tue Jan 25 03:38:29 2011<br>
@@ -27,6 +27,14 @@<br>
 ; CHECK: ret i1 %x<br>
 }<br>
<br>
+define i1 @zext3() {<br>
+; CHECK: @zext3<br>
+  %e = zext i1 1 to i32<br>
+  %c = icmp ne i32 %e, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 true<br>
+}<br>
+<br>
 define i1 @sext(i32 %x) {<br>
 ; CHECK: @sext<br>
   %e1 = sext i32 %x to i64<br>
@@ -43,3 +51,49 @@<br>
   ret i1 %c<br>
 ; CHECK: ret i1 %x<br>
 }<br>
+<br>
+define i1 @sext3() {<br>
+; CHECK: @sext3<br>
+  %e = sext i1 1 to i32<br>
+  %c = icmp ne i32 %e, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 true<br>
+}<br>
+<br>
+define i1 @add(i32 %x, i32 %y) {<br>
+; CHECK: @add<br>
+  %l = lshr i32 %x, 1<br>
+  %r = lshr i32 %y, 1<br>
+  %s = add i32 %l, %r<br>
+  %c = icmp eq i32 %s, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 false<br>
+}<br>
+<br>
+define i1 @add2(i8 %x, i8 %y) {<br>
+; CHECK: @add2<br>
+  %l = or i8 %x, 128<br>
+  %r = or i8 %y, 129<br>
+  %s = add i8 %l, %r<br>
+  %c = icmp eq i8 %s, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 false<br>
+}<br>
+<br>
+define i1 @addpowtwo(i32 %x, i32 %y) {<br>
+; CHECK: @addpowtwo<br>
+  %l = lshr i32 %x, 1<br>
+  %r = shl i32 1, %y<br>
+  %s = add i32 %l, %r<br>
+  %c = icmp eq i32 %s, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 false<br>
+}<br>
+<br>
+define i1 @or(i32 %x) {<br>
+; CHECK: @or<br>
+  %o = or i32 %x, 1<br>
+  %c = icmp eq i32 %o, 0<br>
+  ret i1 %c<br>
+; CHECK: ret i1 false<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br>