diff options
author | Chris Lattner <sabre@nondot.org> | 2009-10-26 01:06:31 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-10-26 01:06:31 +0000 |
commit | 863928fc39c7f1ab86779415eb704b2f2474b995 (patch) | |
tree | 3b3a61d0d841f735be0cbb4bb83d7b1c7efd3cad /lib | |
parent | 1125f58efcfe4e93322f993aa74215e6ffacd8ea (diff) |
Implement PR3266 & PR5276, folding:
not (or (icmp, icmp)) -> and(icmp, icmp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85085 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 81423b740b..0285fb5377 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -631,9 +631,32 @@ static inline Value *dyn_castFNegVal(Value *V) { return 0; } -static inline Value *dyn_castNotVal(Value *V) { +/// isFreeToInvert - Return true if the specified value is free to invert (apply +/// ~ to). This happens in cases where the ~ can be eliminated. +static inline bool isFreeToInvert(Value *V) { + // ~(~(X)) -> X. if (BinaryOperator::isNot(V)) - return BinaryOperator::getNotArgument(V); + return true; + + // Constants can be considered to be not'ed values. + if (isa<ConstantInt>(V)) + return true; + + // Compares can be inverted if they have a single use. + if (CmpInst *CI = dyn_cast<CmpInst>(V)) + return CI->hasOneUse(); + + return false; +} + +static inline Value *dyn_castNotVal(Value *V) { + // If this is not(not(x)) don't return that this is a not: we want the two + // not's to be folded first. + if (BinaryOperator::isNot(V)) { + Value *Operand = BinaryOperator::getNotArgument(V); + if (!isFreeToInvert(Operand)) + return Operand; + } // Constants can be considered to be not'ed values... if (ConstantInt *C = dyn_cast<ConstantInt>(V)) @@ -641,6 +664,8 @@ static inline Value *dyn_castNotVal(Value *V) { return 0; } + + // dyn_castFoldableMul - If this value is a multiply that can be folded into // other computations (because it has a constant operand), return the // non-constant operand of the multiply, and set CST to point to the multiplier. @@ -4166,7 +4191,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) { if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) && CastOp->getNumOperands() == 2) - if (ConstantInt *AndCI = dyn_cast<ConstantInt>(CastOp->getOperand(1))) { + 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_or_bitcast(C1)&C2 @@ -5064,12 +5089,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { // Is this a ~ operation? if (Value *NotOp = dyn_castNotVal(&I)) { - // ~(~X & Y) --> (X | ~Y) - De Morgan's Law - // ~(~X | Y) === (X & ~Y) - De Morgan's Law if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) { if (Op0I->getOpcode() == Instruction::And || Op0I->getOpcode() == Instruction::Or) { - if (dyn_castNotVal(Op0I->getOperand(1))) Op0I->swapOperands(); + // ~(~X & Y) --> (X | ~Y) - De Morgan's Law + // ~(~X | Y) === (X & ~Y) - De Morgan's Law + if (dyn_castNotVal(Op0I->getOperand(1))) + Op0I->swapOperands(); if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) { Value *NotY = Builder->CreateNot(Op0I->getOperand(1), @@ -5078,6 +5104,19 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { return BinaryOperator::CreateOr(Op0NotVal, NotY); return BinaryOperator::CreateAnd(Op0NotVal, NotY); } + + // ~(X & Y) --> (~X | ~Y) - De Morgan's Law + // ~(X | Y) === (~X & ~Y) - De Morgan's Law + if (isFreeToInvert(Op0I->getOperand(0)) && + isFreeToInvert(Op0I->getOperand(1))) { + Value *NotX = + Builder->CreateNot(Op0I->getOperand(0), "notlhs"); + Value *NotY = + Builder->CreateNot(Op0I->getOperand(1), "notrhs"); + if (Op0I->getOpcode() == Instruction::And) + return BinaryOperator::CreateOr(NotX, NotY); + return BinaryOperator::CreateAnd(NotX, NotY); + } } } } |