[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