[llvm-commits] [llvm] r90646 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/compare-signs.ll
Nick Lewycky
nicholas at mxc.ca
Fri Dec 4 21:00:00 PST 2009
Author: nicholas
Date: Fri Dec 4 23:00:00 2009
New Revision: 90646
URL: http://llvm.org/viewvc/llvm-project?rev=90646&view=rev
Log:
Generalize this optimization to work on equality comparisons between any two
integers that are constant except for a single bit (the same n-th bit in each).
Modified:
llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
llvm/trunk/test/Transforms/InstCombine/compare-signs.ll
Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=90646&r1=90645&r2=90646&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Fri Dec 4 23:00:00 2009
@@ -8585,25 +8585,36 @@
if (ICI->isEquality() && CI.getType() == ICI->getOperand(0)->getType()) {
if (const IntegerType *ITy = dyn_cast<IntegerType>(CI.getType())) {
uint32_t BitWidth = ITy->getBitWidth();
- if (BitWidth > 1) {
- Value *LHS = ICI->getOperand(0);
- Value *RHS = ICI->getOperand(1);
-
- APInt KnownZeroLHS(BitWidth, 0), KnownOneLHS(BitWidth, 0);
- APInt KnownZeroRHS(BitWidth, 0), KnownOneRHS(BitWidth, 0);
- APInt TypeMask(APInt::getHighBitsSet(BitWidth, BitWidth-1));
- ComputeMaskedBits(LHS, TypeMask, KnownZeroLHS, KnownOneLHS);
- ComputeMaskedBits(RHS, TypeMask, KnownZeroRHS, KnownOneRHS);
+ Value *LHS = ICI->getOperand(0);
+ Value *RHS = ICI->getOperand(1);
- if (KnownZeroLHS.countLeadingOnes() == BitWidth-1 &&
- KnownZeroRHS.countLeadingOnes() == BitWidth-1) {
+ APInt KnownZeroLHS(BitWidth, 0), KnownOneLHS(BitWidth, 0);
+ APInt KnownZeroRHS(BitWidth, 0), KnownOneRHS(BitWidth, 0);
+ APInt TypeMask(APInt::getAllOnesValue(BitWidth));
+ ComputeMaskedBits(LHS, TypeMask, KnownZeroLHS, KnownOneLHS);
+ ComputeMaskedBits(RHS, TypeMask, KnownZeroRHS, KnownOneRHS);
+
+ if (KnownZeroLHS == KnownZeroRHS && KnownOneLHS == KnownOneRHS) {
+ APInt KnownBits = KnownZeroLHS | KnownOneLHS;
+ APInt UnknownBit = ~KnownBits;
+ if (UnknownBit.countPopulation() == 1) {
if (!DoXform) return ICI;
- Value *Xor = Builder->CreateXor(LHS, RHS);
+ Value *Result = Builder->CreateXor(LHS, RHS);
+
+ // Mask off any bits that are set and won't be shifted away.
+ if (KnownOneLHS.uge(UnknownBit))
+ Result = Builder->CreateAnd(Result,
+ ConstantInt::get(ITy, UnknownBit));
+
+ // Shift the bit we're testing down to the lsb.
+ Result = Builder->CreateLShr(
+ Result, ConstantInt::get(ITy, UnknownBit.countTrailingZeros()));
+
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
- Xor = Builder->CreateXor(Xor, ConstantInt::get(ITy, 1));
- Xor->takeName(ICI);
- return ReplaceInstUsesWith(CI, Xor);
+ Result = Builder->CreateXor(Result, ConstantInt::get(ITy, 1));
+ Result->takeName(ICI);
+ return ReplaceInstUsesWith(CI, Result);
}
}
}
Modified: llvm/trunk/test/Transforms/InstCombine/compare-signs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/compare-signs.ll?rev=90646&r1=90645&r2=90646&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/compare-signs.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/compare-signs.ll Fri Dec 4 23:00:00 2009
@@ -2,7 +2,7 @@
; PR5438
; TODO: This should also optimize down.
-;define i32 @bar(i32 %a, i32 %b) nounwind readnone {
+;define i32 @test1(i32 %a, i32 %b) nounwind readnone {
;entry:
; %0 = icmp sgt i32 %a, -1 ; <i1> [#uses=1]
; %1 = icmp slt i32 %b, 0 ; <i1> [#uses=1]
@@ -11,8 +11,18 @@
; ret i32 %3
;}
-define i32 @qaz(i32 %a, i32 %b) nounwind readnone {
-; CHECK: @qaz
+; TODO: This optimizes partially but not all the way.
+;define i32 @test2(i32 %a, i32 %b) nounwind readnone {
+;entry:
+; %0 = and i32 %a, 8 ;<i32> [#uses=1]
+; %1 = and i32 %b, 8 ;<i32> [#uses=1]
+; %2 = icmp eq i32 %0, %1 ;<i1> [#uses=1]
+; %3 = zext i1 %2 to i32 ;<i32> [#uses=1]
+; ret i32 %3
+;}
+
+define i32 @test3(i32 %a, i32 %b) nounwind readnone {
+; CHECK: @test3
entry:
; CHECK: xor i32 %a, %b
; CHECK; lshr i32 %0, 31
@@ -26,3 +36,23 @@
; CHECK-NOT: zext
; CHECK: ret i32 %2
}
+
+; Variation on @test3: checking the 2nd bit in a situation where the 5th bit
+; is one, not zero.
+define i32 @test3i(i32 %a, i32 %b) nounwind readnone {
+; CHECK: @test3i
+entry:
+; CHECK: xor i32 %a, %b
+; CHECK; lshr i32 %0, 31
+; CHECK: xor i32 %1, 1
+ %0 = lshr i32 %a, 29 ; <i32> [#uses=1]
+ %1 = lshr i32 %b, 29 ; <i32> [#uses=1]
+ %2 = or i32 %0, 35
+ %3 = or i32 %1, 35
+ %4 = icmp eq i32 %2, %3 ; <i1> [#uses=1]
+ %5 = zext i1 %4 to i32 ; <i32> [#uses=1]
+ ret i32 %5
+; CHECK-NOT: icmp
+; CHECK-NOT: zext
+; CHECK: ret i32 %2
+}
More information about the llvm-commits
mailing list