[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