diff options
author | Chris Lattner <sabre@nondot.org> | 2005-08-07 07:03:10 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-08-07 07:03:10 +0000 |
commit | 2b83af2d0f3ab05f0d87a5b5110b2c572275da43 (patch) | |
tree | 56057b6b1203d42e3ad2a4e3cdec40f7e053ff0f /lib/Transforms | |
parent | 4c0e4cdc40bbf94766242294fe386f4eb2d32d2e (diff) |
Add some simple folds that occur in bitfield cases. Fix a minor bug in
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
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 4ee833bf6f..b9113a4460 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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() < |