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

Benjamin Kramer benny.kra at gmail.com
Tue Feb 11 14:06:31 PST 2014


On 11.02.2014, at 22:47, Jim Grosbach <grosbach at apple.com> wrote:

> Clever. Does this help when building clang or llvm?

It does trigger here and there. The motivating example was something like

struct bit {
  unsigned x : 1;
  unsigned y : 31;
};

void qux(bit &a, bit &b) {
  if (a.x == b.x && a.y == b.y)
    bar();
}

we transformed the if into

x = a ^ b;
if (((x & 1) == 0) & (x < 2))

now we fold it down to
if (a == b) // optimal

We still get nasty code when comparing larger bitfields elementwise, but that's probably harder to fix.

- Ben

> 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