We went through all that trouble to compute whether it was safe to transform
authorChris Lattner <sabre@nondot.org>
Wed, 20 Sep 2006 04:44:59 +0000 (04:44 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 20 Sep 2006 04:44:59 +0000 (04:44 +0000)
this comparison, but never checked it.  Whoops, no wonder we miscompiled
177.mesa!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30511 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp

index 58d4b8ff1394c7864319c605fb04d862e7884cc9..8f6d5348e67331e5497bb90779cf018cdd28beca 100644 (file)
@@ -5713,12 +5713,51 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
         return new CastInst(NotCond, SI.getType());
       }
 
-      // If one of the constants is zero (we know they can't both be) and we
-      // have a setcc instruction with zero, and we have an 'and' with the
-      // non-constant value, eliminate this whole mess.  This corresponds to
-      // cases like this: ((X & 27) ? 27 : 0)
-      if (TrueValC->isNullValue() || FalseValC->isNullValue())
-        if (SetCondInst *IC = dyn_cast<SetCondInst>(SI.getCondition()))
+      if (SetCondInst *IC = dyn_cast<SetCondInst>(SI.getCondition())) {
+
+        // (x <s 0) ? -1 : 0 -> sra x, 31
+        // (x >u 2147483647) ? -1 : 0 -> sra x, 31
+        if (TrueValC->isAllOnesValue() && FalseValC->isNullValue())
+          if (ConstantInt *CmpCst = dyn_cast<ConstantInt>(IC->getOperand(1))) {
+            bool CanXForm = false;
+            if (CmpCst->getType()->isSigned())
+              CanXForm = CmpCst->isNullValue() && 
+                         IC->getOpcode() == Instruction::SetLT;
+            else {
+              unsigned Bits = CmpCst->getType()->getPrimitiveSizeInBits();
+              CanXForm = (CmpCst->getRawValue() == ~0ULL >> (64-Bits+1)) &&
+                         IC->getOpcode() == Instruction::SetGT;
+            }
+            
+            if (CanXForm) {
+              // The comparison constant and the result are not neccessarily the
+              // same width.  In any case, the first step to do is make sure
+              // that X is signed.
+              Value *X = IC->getOperand(0);
+              if (!X->getType()->isSigned())
+                X = InsertCastBefore(X, X->getType()->getSignedVersion(), SI);
+              
+              // Now that X is signed, we have to make the all ones value.  Do
+              // this by inserting a new SRA.
+              unsigned Bits = X->getType()->getPrimitiveSizeInBits();
+              Constant *ShAmt = ConstantUInt::get(Type::UByteTy, Bits-1);
+              Instruction *SRA = new ShiftInst(Instruction::Shr, X,
+                                               ShAmt, "ones");
+              InsertNewInstBefore(SRA, SI);
+              
+              // Finally, convert to the type of the select RHS.  If this is
+              // smaller than the compare value, it will truncate the ones to
+              // fit. If it is larger, it will sext the ones to fit.
+              return new CastInst(SRA, SI.getType());
+            }
+          }
+
+
+        // If one of the constants is zero (we know they can't both be) and we
+        // have a setcc instruction with zero, and we have an 'and' with the
+        // non-constant value, eliminate this whole mess.  This corresponds to
+        // cases like this: ((X & 27) ? 27 : 0)
+        if (TrueValC->isNullValue() || FalseValC->isNullValue())
           if (IC->isEquality() && isa<ConstantInt>(IC->getOperand(1)) &&
               cast<Constant>(IC->getOperand(1))->isNullValue())
             if (Instruction *ICA = dyn_cast<Instruction>(IC->getOperand(0)))
@@ -5738,6 +5777,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
                                   Instruction::Xor, V, ICA->getOperand(1)), SI);
                 return ReplaceInstUsesWith(SI, V);
               }
+      }
     }
 
   // See if we are selecting two values based on a comparison of the two values.