mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-24 20:44:51 +00:00
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:
parent
3d0c010ee4
commit
7f9ddaf7e3
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user