diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 20 | 
1 files changed, 20 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 5493b4a85b3..467c6d9453b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3830,6 +3830,26 @@ Instruction *InstCombiner::foldICmpEquality(ICmpInst &I) {         match(Op1, m_BitReverse(m_Value(B)))))      return new ICmpInst(Pred, A, B); +  // Canonicalize checking for a power-of-2-or-zero value: +  // (A & -A) == A --> (A & (A - 1)) == 0 +  // (-A & A) == A --> (A & (A - 1)) == 0 +  // A == (A & -A) --> (A & (A - 1)) == 0 +  // A == (-A & A) --> (A & (A - 1)) == 0 +  // TODO: This could be reduced by using the popct intrinsic. +  A = nullptr; +  if (match(Op0, m_OneUse(m_c_And(m_OneUse(m_Neg(m_Specific(Op1))), +                                  m_Specific(Op1))))) +    A = Op1; +  else if (match(Op1, m_OneUse(m_c_And(m_OneUse(m_Neg(m_Specific(Op0))), +                                       m_Specific(Op0))))) +    A = Op0; +  if (A) { +    Type *Ty = A->getType(); +    Value *Dec = Builder.CreateAdd(A, ConstantInt::getAllOnesValue(Ty)); +    Value *And = Builder.CreateAnd(A, Dec); +    return new ICmpInst(Pred, And, ConstantInt::getNullValue(Ty)); +  } +    return nullptr;  }  | 

