From 2b749870d0488c3b049edf5d0c8875f56f5b1bed Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 17 Nov 2010 18:52:15 +0000 Subject: [PATCH] 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 --- include/llvm/Analysis/InstructionSimplify.h | 5 + include/llvm/Support/PatternMatch.h | 16 ++- lib/Analysis/InstructionSimplify.cpp | 108 +++++++++++++----- .../InstCombine/InstCombineAndOrXor.cpp | 33 +----- 4 files changed, 100 insertions(+), 62 deletions(-) diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 965e71be411..f88fc46c311 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -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, diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index bee67686378..8b5812141df 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -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 + bool match(ITy *V) { + if (const ConstantInt *C = dyn_cast(V)) + return C->isAllOnesValue(); + if (const ConstantVector *C = dyn_cast(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 struct bind_ty { diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 5ad842b38f1..7848d508665 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -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(Op1)) + // X & 0 = 0 + if (match(Op1, m_Zero())) return Op1; - // X & <-1,-1> = X - if (ConstantVector *CP = dyn_cast(Op1)) - if (CP->isAllOnesValue()) - return Op0; - - if (ConstantInt *Op1CI = dyn_cast(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(Op1)) + // X | 0 = X + if (match(Op1, m_Zero())) return Op0; - // X | <-1,-1> = <-1,-1> - if (ConstantVector *CP = dyn_cast(Op1)) - if (CP->isAllOnesValue()) - return Op1; - - if (ConstantInt *Op1CI = dyn_cast(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(Op0)) { + if (Constant *CRHS = dyn_cast(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(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(Op0) || isa(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(Op0) || isa(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(I)->getPredicate(), I->getOperand(0), I->getOperand(1), TD, DT); diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 864b47758b2..a2569be16bd 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1976,25 +1976,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { bool Changed = SimplifyAssociativeOrCommutative(I); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - if (isa(Op1)) { - if (isa(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(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(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