[llvm] r201176 - InstCombine: Teach icmp merging about the equivalence of bit tests and UGE/ULT with a power of 2.

Jim Grosbach grosbach at apple.com
Tue Feb 11 13:47:14 PST 2014


Clever. Does this help when building clang or llvm?

-Jim


On Feb 11, 2014, at 1:09 PM, Benjamin Kramer <benny.kra at googlemail.com> wrote:

> Author: d0k
> Date: Tue Feb 11 15:09:03 2014
> New Revision: 201176
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=201176&view=rev
> Log:
> InstCombine: Teach icmp merging about the equivalence of bit tests and UGE/ULT with a power of 2.
> 
> This happens in bitfield code. While there reorganize the existing code
> a bit.
> 
> Modified:
>    llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
>    llvm/trunk/test/Transforms/InstCombine/sign-test-and-or.ll
> 
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=201176&r1=201175&r2=201176&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Tue Feb 11 15:09:03 2014
> @@ -503,31 +503,46 @@ static unsigned conjugateICmpMask(unsign
> /// decomposition fails.
> static bool decomposeBitTestICmp(const ICmpInst *I, ICmpInst::Predicate &Pred,
>                                  Value *&X, Value *&Y, Value *&Z) {
> -  // X < 0 is equivalent to (X & SignBit) != 0.
> -  if (I->getPredicate() == ICmpInst::ICMP_SLT)
> -    if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1)))
> -      if (C->isZero()) {
> -        X = I->getOperand(0);
> -        Y = ConstantInt::get(I->getContext(),
> -                             APInt::getSignBit(C->getBitWidth()));
> -        Pred = ICmpInst::ICMP_NE;
> -        Z = C;
> -        return true;
> -      }
> +  ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1));
> +  if (!C)
> +    return false;
> 
> -  // X > -1 is equivalent to (X & SignBit) == 0.
> -  if (I->getPredicate() == ICmpInst::ICMP_SGT)
> -    if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1)))
> -      if (C->isAllOnesValue()) {
> -        X = I->getOperand(0);
> -        Y = ConstantInt::get(I->getContext(),
> -                             APInt::getSignBit(C->getBitWidth()));
> -        Pred = ICmpInst::ICMP_EQ;
> -        Z = ConstantInt::getNullValue(C->getType());
> -        return true;
> -      }
> +  switch (I->getPredicate()) {
> +  default:
> +    return false;
> +  case ICmpInst::ICMP_SLT:
> +    // X < 0 is equivalent to (X & SignBit) != 0.
> +    if (!C->isZero())
> +      return false;
> +    Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
> +    Pred = ICmpInst::ICMP_NE;
> +    break;
> +  case ICmpInst::ICMP_SGT:
> +    // X > -1 is equivalent to (X & SignBit) == 0.
> +    if (!C->isAllOnesValue())
> +      return false;
> +    Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
> +    Pred = ICmpInst::ICMP_EQ;
> +    break;
> +  case ICmpInst::ICMP_ULT:
> +    // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
> +    if (!C->getValue().isPowerOf2())
> +      return false;
> +    Y = ConstantInt::get(I->getContext(), -C->getValue());
> +    Pred = ICmpInst::ICMP_EQ;
> +    break;
> +  case ICmpInst::ICMP_UGT:
> +    // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
> +    if (!(C->getValue() + 1).isPowerOf2())
> +      return false;
> +    Y = ConstantInt::get(I->getContext(), ~C->getValue());
> +    Pred = ICmpInst::ICMP_NE;
> +    break;
> +  }
> 
> -  return false;
> +  X = I->getOperand(0);
> +  Z = ConstantInt::getNullValue(C->getType());
> +  return true;
> }
> 
> /// foldLogOpOfMaskedICmpsHelper:
> 
> Modified: llvm/trunk/test/Transforms/InstCombine/sign-test-and-or.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sign-test-and-or.ll?rev=201176&r1=201175&r2=201176&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/sign-test-and-or.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/sign-test-and-or.ll Tue Feb 11 15:09:03 2014
> @@ -177,3 +177,41 @@ if.then:
> if.end:
>   ret void
> }
> +
> +define void @test10(i32 %a) nounwind {
> +  %1 = and i32 %a, 2
> +  %2 = icmp eq i32 %1, 0
> +  %3 = icmp ult i32 %a, 4
> +  %or.cond = and i1 %2, %3
> +  br i1 %or.cond, label %if.then, label %if.end
> +
> +; CHECK-LABEL: @test10(
> +; CHECK-NEXT: %1 = icmp ult i32 %a, 2
> +; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
> +
> +if.then:
> +  tail call void @foo() nounwind
> +  ret void
> +
> +if.end:
> +  ret void
> +}
> +
> +define void @test11(i32 %a) nounwind {
> +  %1 = and i32 %a, 2
> +  %2 = icmp ne i32 %1, 0
> +  %3 = icmp ugt i32 %a, 3
> +  %or.cond = or i1 %2, %3
> +  br i1 %or.cond, label %if.then, label %if.end
> +
> +; CHECK-LABEL: @test11(
> +; CHECK-NEXT: %1 = icmp ugt i32 %a, 1
> +; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
> +
> +if.then:
> +  tail call void @foo() nounwind
> +  ret void
> +
> +if.end:
> +  ret void
> +}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list