Add some simple folds that occur in bitfield cases. Fix a minor bug in
authorChris Lattner <sabre@nondot.org>
Sun, 7 Aug 2005 07:03:10 +0000 (07:03 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 7 Aug 2005 07:03:10 +0000 (07:03 +0000)
isHighOnes, where it would consider 0 to have high ones.

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

lib/Transforms/Scalar/InstructionCombining.cpp

index 4ee833bf6f7a5e901559b19cfaa85511c27d9f22..b9113a4460043075b5141c2c80b307919d5500f7 100644 (file)
@@ -1215,6 +1215,7 @@ static bool isLowOnes(const ConstantInt *CI) {
 // This is the same as lowones(~X).
 static bool isHighOnes(const ConstantInt *CI) {
   uint64_t V = ~CI->getRawValue();
+  if (~V == 0) return false;  // 0's does not match "1+"
 
   // There won't be bits set in parts that the type doesn't contain.
   V &= ConstantInt::getAllOnesValue(CI->getType())->getRawValue();
@@ -1636,6 +1637,37 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
     } else if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
       const Type *SrcTy = CI->getOperand(0)->getType();
 
+      // If this is an integer truncation or change from signed-to-unsigned, and
+      // if the source is an and/or with immediate, transform it.  This
+      // frequently occurs for bitfield accesses.
+      if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
+        if (SrcTy->getPrimitiveSizeInBits() >= 
+              I.getType()->getPrimitiveSizeInBits() &&
+            CastOp->getNumOperands() == 2)
+          if (ConstantInt *AndCI =dyn_cast<ConstantInt>(CastOp->getOperand(1)))
+            if (CastOp->getOpcode() == Instruction::And) {
+              // Change: and (cast (and X, C1) to T), C2
+              // into  : and (cast X to T), trunc(C1)&C2
+              // This will folds the two ands together, which may allow other
+              // simplifications.
+              Instruction *NewCast =
+                new CastInst(CastOp->getOperand(0), I.getType(),
+                             CastOp->getName()+".shrunk");
+              NewCast = InsertNewInstBefore(NewCast, I);
+              
+              Constant *C3=ConstantExpr::getCast(AndCI, I.getType());//trunc(C1)
+              C3 = ConstantExpr::getAnd(C3, AndRHS);            // trunc(C1)&C2
+              return BinaryOperator::createAnd(NewCast, C3);
+            } else if (CastOp->getOpcode() == Instruction::Or) {
+              // Change: and (cast (or X, C1) to T), C2
+              // into  : trunc(C1)&C2 iff trunc(C1)&C2 == C2
+              Constant *C3=ConstantExpr::getCast(AndCI, I.getType());//trunc(C1)
+              if (ConstantExpr::getAnd(C3, AndRHS) == AndRHS)   // trunc(C1)&C2
+                return ReplaceInstUsesWith(I, AndRHS);
+            }
+      }
+
+
       // If this is an integer sign or zero extension instruction.
       if (SrcTy->isIntegral() &&
           SrcTy->getPrimitiveSizeInBits() <