reapply r85085 with a bugfix to avoid infinite looping.

All of the 'demorgan' related xforms need to use 
dyn_castNotVal, not m_Not.

llvm-svn: 85119
This commit is contained in:
Chris Lattner 2009-10-26 15:40:07 +00:00
parent 3d0c010ee4
commit 7f9ddaf7e3
2 changed files with 47 additions and 9 deletions

View File

@ -631,9 +631,32 @@ static inline Value *dyn_castFNegVal(Value *V) {
return 0; 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)) 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... // Constants can be considered to be not'ed values...
if (ConstantInt *C = dyn_cast<ConstantInt>(V)) if (ConstantInt *C = dyn_cast<ConstantInt>(V))
@ -641,6 +664,8 @@ static inline Value *dyn_castNotVal(Value *V) {
return 0; return 0;
} }
// dyn_castFoldableMul - If this value is a multiply that can be folded into // dyn_castFoldableMul - If this value is a multiply that can be folded into
// other computations (because it has a constant operand), return the // other computations (because it has a constant operand), return the
// non-constant operand of the multiply, and set CST to point to the multiplier. // 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 (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) && if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) &&
CastOp->getNumOperands() == 2) 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) { if (CastOp->getOpcode() == Instruction::And) {
// Change: and (cast (and X, C1) to T), C2 // Change: and (cast (and X, C1) to T), C2
// into : and (cast X to T), trunc_or_bitcast(C1)&C2 // into : and (cast X to T), trunc_or_bitcast(C1)&C2
@ -4960,14 +4985,14 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
if (Ret) return Ret; if (Ret) return Ret;
} }
if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1 if ((A = dyn_castNotVal(Op0))) { // ~A | Op1
if (A == Op1) // ~A | A == -1 if (A == Op1) // ~A | A == -1
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType())); return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
} else { } else {
A = 0; A = 0;
} }
// Note, A is still live here! // Note, A is still live here!
if (match(Op1, m_Not(m_Value(B)))) { // Op0 | ~B if ((B = dyn_castNotVal(Op1))) { // Op0 | ~B
if (Op0 == B) if (Op0 == B)
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType())); return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
@ -5064,12 +5089,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
// Is this a ~ operation? // Is this a ~ operation?
if (Value *NotOp = dyn_castNotVal(&I)) { 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 (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) {
if (Op0I->getOpcode() == Instruction::And || if (Op0I->getOpcode() == Instruction::And ||
Op0I->getOpcode() == Instruction::Or) { 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))) { if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
Value *NotY = Value *NotY =
Builder->CreateNot(Op0I->getOperand(1), Builder->CreateNot(Op0I->getOperand(1),
@ -5078,6 +5104,19 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return BinaryOperator::CreateOr(Op0NotVal, NotY); return BinaryOperator::CreateOr(Op0NotVal, NotY);
return BinaryOperator::CreateAnd(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);
}
} }
} }
} }

View File

@ -1,7 +1,6 @@
; This test makes sure that these instructions are properly eliminated. ; This test makes sure that these instructions are properly eliminated.
; ;
; RUN: opt < %s -instcombine -S | FileCheck %s ; RUN: opt < %s -instcombine -S | FileCheck %s
; XFAIL: *
define i32 @test1(i32 %A) { define i32 @test1(i32 %A) {
%B = or i32 %A, 0 %B = or i32 %A, 0