mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-03 19:15:30 +00:00
Move some those Xor simplifications which don't require creating new
instructions out of InstCombine and into InstructionSimplify. While there, introduce an m_AllOnes pattern to simplify matching with integers and vectors with all bits equal to one. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119536 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
89e14c7579
commit
2b749870d0
@ -37,6 +37,11 @@ namespace llvm {
|
|||||||
Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||||
const DominatorTree *DT = 0);
|
const DominatorTree *DT = 0);
|
||||||
|
|
||||||
|
/// SimplifyXorInst - Given operands for a Xor, see if we can
|
||||||
|
/// fold the result. If not, this returns null.
|
||||||
|
Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||||
|
const DominatorTree *DT = 0);
|
||||||
|
|
||||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||||
/// fold the result. If not, this returns null.
|
/// fold the result. If not, this returns null.
|
||||||
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||||
|
@ -96,9 +96,23 @@ struct one_ty {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// m_One() - Match a an integer 1.
|
/// m_One() - Match an integer 1.
|
||||||
inline one_ty m_One() { return one_ty(); }
|
inline one_ty m_One() { return one_ty(); }
|
||||||
|
|
||||||
|
struct all_ones_ty {
|
||||||
|
template<typename ITy>
|
||||||
|
bool match(ITy *V) {
|
||||||
|
if (const ConstantInt *C = dyn_cast<ConstantInt>(V))
|
||||||
|
return C->isAllOnesValue();
|
||||||
|
if (const ConstantVector *C = dyn_cast<ConstantVector>(V))
|
||||||
|
return C->isAllOnesValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// m_AllOnes() - Match an integer or vector with all bits set to true.
|
||||||
|
inline all_ones_ty m_AllOnes() { return all_ones_ty(); }
|
||||||
|
|
||||||
|
|
||||||
template<typename Class>
|
template<typename Class>
|
||||||
struct bind_ty {
|
struct bind_ty {
|
||||||
|
@ -276,23 +276,13 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
|
|||||||
if (Op0 == Op1)
|
if (Op0 == Op1)
|
||||||
return Op0;
|
return Op0;
|
||||||
|
|
||||||
// X & <0,0> = <0,0>
|
// X & 0 = 0
|
||||||
if (isa<ConstantAggregateZero>(Op1))
|
if (match(Op1, m_Zero()))
|
||||||
return Op1;
|
return Op1;
|
||||||
|
|
||||||
// X & <-1,-1> = X
|
// X & -1 = X
|
||||||
if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
|
if (match(Op1, m_AllOnes()))
|
||||||
if (CP->isAllOnesValue())
|
return Op0;
|
||||||
return Op0;
|
|
||||||
|
|
||||||
if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
|
|
||||||
// X & 0 = 0
|
|
||||||
if (Op1CI->isZero())
|
|
||||||
return Op1CI;
|
|
||||||
// X & -1 = X
|
|
||||||
if (Op1CI->isAllOnesValue())
|
|
||||||
return Op0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A & ~A = ~A & A = 0
|
// A & ~A = ~A & A = 0
|
||||||
Value *A, *B;
|
Value *A, *B;
|
||||||
@ -365,23 +355,13 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
|||||||
if (Op0 == Op1)
|
if (Op0 == Op1)
|
||||||
return Op0;
|
return Op0;
|
||||||
|
|
||||||
// X | <0,0> = X
|
// X | 0 = X
|
||||||
if (isa<ConstantAggregateZero>(Op1))
|
if (match(Op1, m_Zero()))
|
||||||
return Op0;
|
return Op0;
|
||||||
|
|
||||||
// X | <-1,-1> = <-1,-1>
|
// X | -1 = -1
|
||||||
if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
|
if (match(Op1, m_AllOnes()))
|
||||||
if (CP->isAllOnesValue())
|
return Op1;
|
||||||
return Op1;
|
|
||||||
|
|
||||||
if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
|
|
||||||
// X | 0 = X
|
|
||||||
if (Op1CI->isZero())
|
|
||||||
return Op0;
|
|
||||||
// X | -1 = -1
|
|
||||||
if (Op1CI->isAllOnesValue())
|
|
||||||
return Op1CI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A | ~A = ~A | A = -1
|
// A | ~A = ~A | A = -1
|
||||||
Value *A, *B;
|
Value *A, *B;
|
||||||
@ -431,6 +411,71 @@ Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
|||||||
return ::SimplifyOrInst(Op0, Op1, TD, DT, RecursionLimit);
|
return ::SimplifyOrInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SimplifyXorInst - Given operands for a Xor, see if we can
|
||||||
|
/// fold the result. If not, this returns null.
|
||||||
|
static Value *SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||||
|
const DominatorTree *DT, unsigned MaxRecurse) {
|
||||||
|
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
|
||||||
|
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
|
||||||
|
Constant *Ops[] = { CLHS, CRHS };
|
||||||
|
return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(),
|
||||||
|
Ops, 2, TD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonicalize the constant to the RHS.
|
||||||
|
std::swap(Op0, Op1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ^ undef -> undef
|
||||||
|
if (isa<UndefValue>(Op1))
|
||||||
|
return UndefValue::get(Op0->getType());
|
||||||
|
|
||||||
|
// A ^ 0 = A
|
||||||
|
if (match(Op1, m_Zero()))
|
||||||
|
return Op0;
|
||||||
|
|
||||||
|
// A ^ A = 0
|
||||||
|
if (Op0 == Op1)
|
||||||
|
return Constant::getNullValue(Op0->getType());
|
||||||
|
|
||||||
|
// A ^ ~A = ~A ^ A = -1
|
||||||
|
Value *A, *B;
|
||||||
|
if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
|
||||||
|
(match(Op1, m_Not(m_Value(A))) && A == Op0))
|
||||||
|
return Constant::getAllOnesValue(Op0->getType());
|
||||||
|
|
||||||
|
// (A ^ B) ^ A = B
|
||||||
|
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
|
||||||
|
(A == Op1 || B == Op1))
|
||||||
|
return A == Op1 ? B : A;
|
||||||
|
|
||||||
|
// A ^ (A ^ B) = B
|
||||||
|
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
|
||||||
|
(A == Op0 || B == Op0))
|
||||||
|
return A == Op0 ? B : A;
|
||||||
|
|
||||||
|
// If the operation is with the result of a select instruction, check whether
|
||||||
|
// operating on either branch of the select always yields the same value.
|
||||||
|
if (MaxRecurse && (isa<SelectInst>(Op0) || isa<SelectInst>(Op1)))
|
||||||
|
if (Value *V = ThreadBinOpOverSelect(Instruction::Xor, Op0, Op1, TD, DT,
|
||||||
|
MaxRecurse-1))
|
||||||
|
return V;
|
||||||
|
|
||||||
|
// If the operation is with the result of a phi instruction, check whether
|
||||||
|
// operating on all incoming values of the phi always yields the same value.
|
||||||
|
if (MaxRecurse && (isa<PHINode>(Op0) || isa<PHINode>(Op1)))
|
||||||
|
if (Value *V = ThreadBinOpOverPHI(Instruction::Xor, Op0, Op1, TD, DT,
|
||||||
|
MaxRecurse-1))
|
||||||
|
return V;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *llvm::SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||||
|
const DominatorTree *DT) {
|
||||||
|
return ::SimplifyXorInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||||
|
}
|
||||||
|
|
||||||
static const Type *GetCompareTy(Value *Op) {
|
static const Type *GetCompareTy(Value *Op) {
|
||||||
return CmpInst::makeCmpResultType(Op->getType());
|
return CmpInst::makeCmpResultType(Op->getType());
|
||||||
}
|
}
|
||||||
@ -774,6 +819,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
|||||||
case Instruction::Or:
|
case Instruction::Or:
|
||||||
Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||||
break;
|
break;
|
||||||
|
case Instruction::Xor:
|
||||||
|
Result = SimplifyXorInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||||
|
break;
|
||||||
case Instruction::ICmp:
|
case Instruction::ICmp:
|
||||||
Result = SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
|
Result = SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
|
||||||
I->getOperand(0), I->getOperand(1), TD, DT);
|
I->getOperand(0), I->getOperand(1), TD, DT);
|
||||||
|
@ -1976,25 +1976,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
bool Changed = SimplifyAssociativeOrCommutative(I);
|
bool Changed = SimplifyAssociativeOrCommutative(I);
|
||||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||||
|
|
||||||
if (isa<UndefValue>(Op1)) {
|
if (Value *V = SimplifyXorInst(Op0, Op1, TD))
|
||||||
if (isa<UndefValue>(Op0))
|
return ReplaceInstUsesWith(I, V);
|
||||||
// Handle undef ^ undef -> 0 special case. This is a common
|
|
||||||
// idiom (misuse).
|
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
||||||
return ReplaceInstUsesWith(I, Op1); // X ^ undef -> undef
|
|
||||||
}
|
|
||||||
|
|
||||||
// xor X, X = 0
|
|
||||||
if (Op0 == Op1)
|
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
||||||
|
|
||||||
// See if we can simplify any instructions used by the instruction whose sole
|
// See if we can simplify any instructions used by the instruction whose sole
|
||||||
// purpose is to compute bits we don't care about.
|
// purpose is to compute bits we don't care about.
|
||||||
if (SimplifyDemandedInstructionBits(I))
|
if (SimplifyDemandedInstructionBits(I))
|
||||||
return &I;
|
return &I;
|
||||||
if (I.getType()->isVectorTy())
|
|
||||||
if (isa<ConstantAggregateZero>(Op1))
|
|
||||||
return ReplaceInstUsesWith(I, Op0); // X ^ <0,0> -> X
|
|
||||||
|
|
||||||
// Is this a ~ operation?
|
// Is this a ~ operation?
|
||||||
if (Value *NotOp = dyn_castNotVal(&I)) {
|
if (Value *NotOp = dyn_castNotVal(&I)) {
|
||||||
@ -2113,15 +2101,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
return NV;
|
return NV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Value *X = dyn_castNotVal(Op0)) // ~A ^ A == -1
|
|
||||||
if (X == Op1)
|
|
||||||
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
|
|
||||||
|
|
||||||
if (Value *X = dyn_castNotVal(Op1)) // A ^ ~A == -1
|
|
||||||
if (X == Op0)
|
|
||||||
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
|
|
||||||
|
|
||||||
|
|
||||||
BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
|
BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
|
||||||
if (Op1I) {
|
if (Op1I) {
|
||||||
Value *A, *B;
|
Value *A, *B;
|
||||||
@ -2134,10 +2113,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
I.swapOperands(); // Simplified below.
|
I.swapOperands(); // Simplified below.
|
||||||
std::swap(Op0, Op1);
|
std::swap(Op0, Op1);
|
||||||
}
|
}
|
||||||
} else if (match(Op1I, m_Xor(m_Specific(Op0), m_Value(B)))) {
|
|
||||||
return ReplaceInstUsesWith(I, B); // A^(A^B) == B
|
|
||||||
} else if (match(Op1I, m_Xor(m_Value(A), m_Specific(Op0)))) {
|
|
||||||
return ReplaceInstUsesWith(I, A); // A^(B^A) == B
|
|
||||||
} else if (match(Op1I, m_And(m_Value(A), m_Value(B))) &&
|
} else if (match(Op1I, m_And(m_Value(A), m_Value(B))) &&
|
||||||
Op1I->hasOneUse()){
|
Op1I->hasOneUse()){
|
||||||
if (A == Op0) { // A^(A&B) -> A^(B&A)
|
if (A == Op0) { // A^(A&B) -> A^(B&A)
|
||||||
@ -2160,10 +2135,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
std::swap(A, B);
|
std::swap(A, B);
|
||||||
if (B == Op1) // (A|B)^B == A & ~B
|
if (B == Op1) // (A|B)^B == A & ~B
|
||||||
return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1, "tmp"));
|
return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1, "tmp"));
|
||||||
} else if (match(Op0I, m_Xor(m_Specific(Op1), m_Value(B)))) {
|
|
||||||
return ReplaceInstUsesWith(I, B); // (A^B)^A == B
|
|
||||||
} else if (match(Op0I, m_Xor(m_Value(A), m_Specific(Op1)))) {
|
|
||||||
return ReplaceInstUsesWith(I, A); // (B^A)^A == B
|
|
||||||
} else if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
|
} else if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
|
||||||
Op0I->hasOneUse()){
|
Op0I->hasOneUse()){
|
||||||
if (A == Op1) // (A&B)^A -> (B&A)^A
|
if (A == Op1) // (A&B)^A -> (B&A)^A
|
||||||
|
Loading…
x
Reference in New Issue
Block a user