mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-05 02:07:16 +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,
|
||||
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
|
||||
/// fold the result. If not, this returns null.
|
||||
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(); }
|
||||
|
||||
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>
|
||||
struct bind_ty {
|
||||
|
@ -276,23 +276,13 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
if (Op0 == Op1)
|
||||
return Op0;
|
||||
|
||||
// X & <0,0> = <0,0>
|
||||
if (isa<ConstantAggregateZero>(Op1))
|
||||
// X & 0 = 0
|
||||
if (match(Op1, m_Zero()))
|
||||
return Op1;
|
||||
|
||||
// X & <-1,-1> = X
|
||||
if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
|
||||
if (CP->isAllOnesValue())
|
||||
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;
|
||||
}
|
||||
// X & -1 = X
|
||||
if (match(Op1, m_AllOnes()))
|
||||
return Op0;
|
||||
|
||||
// A & ~A = ~A & A = 0
|
||||
Value *A, *B;
|
||||
@ -365,23 +355,13 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
if (Op0 == Op1)
|
||||
return Op0;
|
||||
|
||||
// X | <0,0> = X
|
||||
if (isa<ConstantAggregateZero>(Op1))
|
||||
// X | 0 = X
|
||||
if (match(Op1, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// X | <-1,-1> = <-1,-1>
|
||||
if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
|
||||
if (CP->isAllOnesValue())
|
||||
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;
|
||||
}
|
||||
// X | -1 = -1
|
||||
if (match(Op1, m_AllOnes()))
|
||||
return Op1;
|
||||
|
||||
// A | ~A = ~A | A = -1
|
||||
Value *A, *B;
|
||||
@ -431,6 +411,71 @@ Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
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) {
|
||||
return CmpInst::makeCmpResultType(Op->getType());
|
||||
}
|
||||
@ -774,6 +819,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
||||
case Instruction::Or:
|
||||
Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::Xor:
|
||||
Result = SimplifyXorInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::ICmp:
|
||||
Result = SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
|
||||
I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
|
@ -1976,25 +1976,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
bool Changed = SimplifyAssociativeOrCommutative(I);
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
if (isa<UndefValue>(Op1)) {
|
||||
if (isa<UndefValue>(Op0))
|
||||
// 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
|
||||
}
|
||||
if (Value *V = SimplifyXorInst(Op0, Op1, TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
// 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
|
||||
// purpose is to compute bits we don't care about.
|
||||
if (SimplifyDemandedInstructionBits(I))
|
||||
return &I;
|
||||
if (I.getType()->isVectorTy())
|
||||
if (isa<ConstantAggregateZero>(Op1))
|
||||
return ReplaceInstUsesWith(I, Op0); // X ^ <0,0> -> X
|
||||
|
||||
// Is this a ~ operation?
|
||||
if (Value *NotOp = dyn_castNotVal(&I)) {
|
||||
@ -2113,15 +2101,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
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);
|
||||
if (Op1I) {
|
||||
Value *A, *B;
|
||||
@ -2134,10 +2113,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
I.swapOperands(); // Simplified below.
|
||||
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))) &&
|
||||
Op1I->hasOneUse()){
|
||||
if (A == Op0) { // A^(A&B) -> A^(B&A)
|
||||
@ -2160,10 +2135,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
std::swap(A, B);
|
||||
if (B == Op1) // (A|B)^B == A & ~B
|
||||
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))) &&
|
||||
Op0I->hasOneUse()){
|
||||
if (A == Op1) // (A&B)^A -> (B&A)^A
|
||||
|
Loading…
Reference in New Issue
Block a user