Push LLVMContext through the PatternMatch API.

llvm-svn: 75255
This commit is contained in:
Owen Anderson 2009-07-10 17:35:01 +00:00
parent 81cdd21dcb
commit 16e7674f4b
4 changed files with 193 additions and 164 deletions

View File

@ -30,7 +30,10 @@ namespace llvm {
/// NoFolder - Create "constants" (actually, values) with no folding. /// NoFolder - Create "constants" (actually, values) with no folding.
class NoFolder { class NoFolder {
LLVMContext &Context;
public: public:
NoFolder(LLVMContext &C) : Context(C) { }
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Binary Operators // Binary Operators
@ -113,7 +116,7 @@ public:
Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList,
unsigned NumIdx) const { unsigned NumIdx) const {
return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); return Context.getConstantExprGetElementPtr(C, IdxList, NumIdx);
} }
Value *CreateGetElementPtr(Constant *C, Value* const *IdxList, Value *CreateGetElementPtr(Constant *C, Value* const *IdxList,
unsigned NumIdx) const { unsigned NumIdx) const {

View File

@ -31,19 +31,20 @@
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
namespace llvm { namespace llvm {
namespace PatternMatch { namespace PatternMatch {
template<typename Val, typename Pattern> template<typename Val, typename Pattern>
bool match(Val *V, const Pattern &P) { bool match(Val *V, const Pattern &P, LLVMContext &Context) {
return const_cast<Pattern&>(P).match(V); return const_cast<Pattern&>(P).match(V, Context);
} }
template<typename Class> template<typename Class>
struct leaf_ty { struct leaf_ty {
template<typename ITy> template<typename ITy>
bool match(ITy *V) { return isa<Class>(V); } bool match(ITy *V, LLVMContext&) { return isa<Class>(V); }
}; };
/// m_Value() - Match an arbitrary value and ignore it. /// m_Value() - Match an arbitrary value and ignore it.
@ -54,7 +55,7 @@ inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); }
template<int64_t Val> template<int64_t Val>
struct constantint_ty { struct constantint_ty {
template<typename ITy> template<typename ITy>
bool match(ITy *V) { bool match(ITy *V, LLVMContext&) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
const APInt &CIV = CI->getValue(); const APInt &CIV = CI->getValue();
if (Val >= 0) if (Val >= 0)
@ -77,7 +78,7 @@ inline constantint_ty<Val> m_ConstantInt() {
struct zero_ty { struct zero_ty {
template<typename ITy> template<typename ITy>
bool match(ITy *V) { bool match(ITy *V, LLVMContext&) {
if (const Constant *C = dyn_cast<Constant>(V)) if (const Constant *C = dyn_cast<Constant>(V))
return C->isNullValue(); return C->isNullValue();
return false; return false;
@ -94,7 +95,7 @@ struct bind_ty {
bind_ty(Class *&V) : VR(V) {} bind_ty(Class *&V) : VR(V) {}
template<typename ITy> template<typename ITy>
bool match(ITy *V) { bool match(ITy *V, LLVMContext&) {
if (Class *CV = dyn_cast<Class>(V)) { if (Class *CV = dyn_cast<Class>(V)) {
VR = CV; VR = CV;
return true; return true;
@ -115,7 +116,7 @@ struct specificval_ty {
specificval_ty(const Value *V) : Val(V) {} specificval_ty(const Value *V) : Val(V) {}
template<typename ITy> template<typename ITy>
bool match(ITy *V) { bool match(ITy *V, LLVMContext&) {
return V == Val; return V == Val;
} }
}; };
@ -137,15 +138,15 @@ struct BinaryOp_match {
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (V->getValueID() == Value::InstructionVal + Opcode) { if (V->getValueID() == Value::InstructionVal + Opcode) {
ConcreteTy *I = cast<ConcreteTy>(V); ConcreteTy *I = cast<ConcreteTy>(V);
return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && return I->getOpcode() == Opcode && L.match(I->getOperand(0), Context) &&
R.match(I->getOperand(1)); R.match(I->getOperand(1), Context);
} }
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && return CE->getOpcode() == Opcode && L.match(CE->getOperand(0), Context) &&
R.match(CE->getOperand(1)); R.match(CE->getOperand(1), Context);
return false; return false;
} }
}; };
@ -269,20 +270,20 @@ struct Shr_match {
Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (V->getValueID() == Value::InstructionVal + Instruction::LShr || if (V->getValueID() == Value::InstructionVal + Instruction::LShr ||
V->getValueID() == Value::InstructionVal + Instruction::AShr) { V->getValueID() == Value::InstructionVal + Instruction::AShr) {
ConcreteTy *I = cast<ConcreteTy>(V); ConcreteTy *I = cast<ConcreteTy>(V);
return (I->getOpcode() == Instruction::AShr || return (I->getOpcode() == Instruction::AShr ||
I->getOpcode() == Instruction::LShr) && I->getOpcode() == Instruction::LShr) &&
L.match(I->getOperand(0)) && L.match(I->getOperand(0), Context) &&
R.match(I->getOperand(1)); R.match(I->getOperand(1), Context);
} }
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
return (CE->getOpcode() == Instruction::LShr || return (CE->getOpcode() == Instruction::LShr ||
CE->getOpcode() == Instruction::AShr) && CE->getOpcode() == Instruction::AShr) &&
L.match(CE->getOperand(0)) && L.match(CE->getOperand(0), Context) &&
R.match(CE->getOperand(1)); R.match(CE->getOperand(1), Context);
return false; return false;
} }
}; };
@ -309,9 +310,10 @@ struct BinaryOpClass_match {
: Opcode(0), L(LHS), R(RHS) {} : Opcode(0), L(LHS), R(RHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Class *I = dyn_cast<Class>(V)) if (Class *I = dyn_cast<Class>(V))
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { if (L.match(I->getOperand(0), Context) &&
R.match(I->getOperand(1), Context)) {
if (Opcode) if (Opcode)
*Opcode = I->getOpcode(); *Opcode = I->getOpcode();
return true; return true;
@ -354,9 +356,10 @@ struct CmpClass_match {
: Predicate(Pred), L(LHS), R(RHS) {} : Predicate(Pred), L(LHS), R(RHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Class *I = dyn_cast<Class>(V)) if (Class *I = dyn_cast<Class>(V))
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { if (L.match(I->getOperand(0), Context) &&
R.match(I->getOperand(1), Context)) {
Predicate = I->getPredicate(); Predicate = I->getPredicate();
return true; return true;
} }
@ -393,11 +396,11 @@ struct SelectClass_match {
: C(Cond), L(LHS), R(RHS) {} : C(Cond), L(LHS), R(RHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (SelectInst *I = dyn_cast<SelectInst>(V)) if (SelectInst *I = dyn_cast<SelectInst>(V))
return C.match(I->getOperand(0)) && return C.match(I->getOperand(0), Context) &&
L.match(I->getOperand(1)) && L.match(I->getOperand(1), Context) &&
R.match(I->getOperand(2)); R.match(I->getOperand(2), Context);
return false; return false;
} }
}; };
@ -430,9 +433,9 @@ struct CastClass_match {
CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Class *I = dyn_cast<Class>(V)) if (Class *I = dyn_cast<Class>(V))
return Op.match(I->getOperand(0)); return Op.match(I->getOperand(0), Context);
return false; return false;
} }
}; };
@ -454,27 +457,27 @@ struct not_match {
not_match(const LHS_t &LHS) : L(LHS) {} not_match(const LHS_t &LHS) : L(LHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Instruction *I = dyn_cast<Instruction>(V)) if (Instruction *I = dyn_cast<Instruction>(V))
if (I->getOpcode() == Instruction::Xor) if (I->getOpcode() == Instruction::Xor)
return matchIfNot(I->getOperand(0), I->getOperand(1)); return matchIfNot(I->getOperand(0), I->getOperand(1), Context);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::Xor) if (CE->getOpcode() == Instruction::Xor)
return matchIfNot(CE->getOperand(0), CE->getOperand(1)); return matchIfNot(CE->getOperand(0), CE->getOperand(1), Context);
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
return L.match(ConstantExpr::getNot(CI)); return L.match(Context.getConstantExprNot(CI), Context);
return false; return false;
} }
private: private:
bool matchIfNot(Value *LHS, Value *RHS) { bool matchIfNot(Value *LHS, Value *RHS, LLVMContext &Context) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS))
return CI->isAllOnesValue() && L.match(LHS); return CI->isAllOnesValue() && L.match(LHS, Context);
if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS)) if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS))
return CI->isAllOnesValue() && L.match(RHS); return CI->isAllOnesValue() && L.match(RHS, Context);
if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS)) if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS))
return CV->isAllOnesValue() && L.match(LHS); return CV->isAllOnesValue() && L.match(LHS, Context);
if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS)) if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS))
return CV->isAllOnesValue() && L.match(RHS); return CV->isAllOnesValue() && L.match(RHS, Context);
return false; return false;
} }
}; };
@ -490,21 +493,21 @@ struct neg_match {
neg_match(const LHS_t &LHS) : L(LHS) {} neg_match(const LHS_t &LHS) : L(LHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Instruction *I = dyn_cast<Instruction>(V)) if (Instruction *I = dyn_cast<Instruction>(V))
if (I->getOpcode() == Instruction::Sub) if (I->getOpcode() == Instruction::Sub)
return matchIfNeg(I->getOperand(0), I->getOperand(1)); return matchIfNeg(I->getOperand(0), I->getOperand(1), Context);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::Sub) if (CE->getOpcode() == Instruction::Sub)
return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); return matchIfNeg(CE->getOperand(0), CE->getOperand(1), Context);
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
return L.match(ConstantExpr::getNeg(CI)); return L.match(Context.getConstantExprNeg(CI), Context);
return false; return false;
} }
private: private:
bool matchIfNeg(Value *LHS, Value *RHS) { bool matchIfNeg(Value *LHS, Value *RHS, LLVMContext &Context) {
return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) && return LHS == Context.getZeroValueForNegation(LHS->getType()) &&
L.match(RHS); L.match(RHS, Context);
} }
}; };
@ -519,21 +522,21 @@ struct fneg_match {
fneg_match(const LHS_t &LHS) : L(LHS) {} fneg_match(const LHS_t &LHS) : L(LHS) {}
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (Instruction *I = dyn_cast<Instruction>(V)) if (Instruction *I = dyn_cast<Instruction>(V))
if (I->getOpcode() == Instruction::FSub) if (I->getOpcode() == Instruction::FSub)
return matchIfFNeg(I->getOperand(0), I->getOperand(1)); return matchIfFNeg(I->getOperand(0), I->getOperand(1), Context);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::FSub) if (CE->getOpcode() == Instruction::FSub)
return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); return matchIfFNeg(CE->getOperand(0), CE->getOperand(1), Context);
if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) if (ConstantFP *CF = dyn_cast<ConstantFP>(V))
return L.match(ConstantExpr::getFNeg(CF)); return L.match(Context.getConstantExprFNeg(CF), Context);
return false; return false;
} }
private: private:
bool matchIfFNeg(Value *LHS, Value *RHS) { bool matchIfFNeg(Value *LHS, Value *RHS, LLVMContext &Context) {
return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) && return LHS == Context.getZeroValueForNegation(LHS->getType()) &&
L.match(RHS); L.match(RHS, Context);
} }
}; };
@ -554,10 +557,10 @@ struct brc_match {
} }
template<typename OpTy> template<typename OpTy>
bool match(OpTy *V) { bool match(OpTy *V, LLVMContext &Context) {
if (BranchInst *BI = dyn_cast<BranchInst>(V)) if (BranchInst *BI = dyn_cast<BranchInst>(V))
if (BI->isConditional()) { if (BI->isConditional()) {
if (Cond.match(BI->getCondition())) { if (Cond.match(BI->getCondition(), Context)) {
T = BI->getSuccessor(0); T = BI->getSuccessor(0);
F = BI->getSuccessor(1); F = BI->getSuccessor(1);
return true; return true;

View File

@ -1889,7 +1889,7 @@ struct AddMaskingAnd {
AddMaskingAnd(Constant *c, LLVMContext *C) : C2(c), Context(C) {} AddMaskingAnd(Constant *c, LLVMContext *C) : C2(c), Context(C) {}
bool shouldApply(Value *LHS) const { bool shouldApply(Value *LHS) const {
ConstantInt *C1; ConstantInt *C1;
return match(LHS, m_And(m_Value(), m_ConstantInt(C1))) && return match(LHS, m_And(m_Value(), m_ConstantInt(C1)), *Context) &&
Context->getConstantExprAnd(C1, C2)->isNullValue(); Context->getConstantExprAnd(C1, C2)->isNullValue();
} }
Instruction *apply(BinaryOperator &Add) const { Instruction *apply(BinaryOperator &Add) const {
@ -2114,7 +2114,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
ConstantInt *XorRHS = 0; ConstantInt *XorRHS = 0;
Value *XorLHS = 0; Value *XorLHS = 0;
if (isa<ConstantInt>(RHSC) && if (isa<ConstantInt>(RHSC) &&
match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) { match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)), *Context)) {
uint32_t TySizeBits = I.getType()->getScalarSizeInBits(); uint32_t TySizeBits = I.getType()->getScalarSizeInBits();
const APInt& RHSVal = cast<ConstantInt>(RHSC)->getValue(); const APInt& RHSVal = cast<ConstantInt>(RHSC)->getValue();
@ -2220,7 +2220,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0 // (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0
if (match(RHS, m_And(m_Value(), m_ConstantInt(C2)))) if (match(RHS, m_And(m_Value(), m_ConstantInt(C2)), *Context))
if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2, Context), Context)) if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2, Context), Context))
return R; return R;
@ -2244,8 +2244,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// W*X + Y*Z --> W * (X+Z) iff W == Y // W*X + Y*Z --> W * (X+Z) iff W == Y
if (I.getType()->isIntOrIntVector()) { if (I.getType()->isIntOrIntVector()) {
Value *W, *X, *Y, *Z; Value *W, *X, *Y, *Z;
if (match(LHS, m_Mul(m_Value(W), m_Value(X))) && if (match(LHS, m_Mul(m_Value(W), m_Value(X)), *Context) &&
match(RHS, m_Mul(m_Value(Y), m_Value(Z)))) { match(RHS, m_Mul(m_Value(Y), m_Value(Z)), *Context)) {
if (W != Y) { if (W != Y) {
if (W == Z) { if (W == Z) {
std::swap(Y, Z); std::swap(Y, Z);
@ -2267,11 +2267,12 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) { if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
Value *X = 0; Value *X = 0;
if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X if (match(LHS, m_Not(m_Value(X)), *Context)) // ~X + C --> (C-1) - X
return BinaryOperator::CreateSub(SubOne(CRHS, Context), X); return BinaryOperator::CreateSub(SubOne(CRHS, Context), X);
// (X & FF00) + xx00 -> (X+xx00) & FF00 // (X & FF00) + xx00 -> (X+xx00) & FF00
if (LHS->hasOneUse() && match(LHS, m_And(m_Value(X), m_ConstantInt(C2)))) { if (LHS->hasOneUse() &&
match(LHS, m_And(m_Value(X), m_ConstantInt(C2)), *Context)) {
Constant *Anded = Context->getConstantExprAnd(CRHS, C2); Constant *Anded = Context->getConstantExprAnd(CRHS, C2);
if (Anded == CRHS) { if (Anded == CRHS) {
// See if all bits from the first bit set in the Add RHS up are included // See if all bits from the first bit set in the Add RHS up are included
@ -2336,10 +2337,12 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// Can we fold the add into the argument of the select? // Can we fold the add into the argument of the select?
// We check both true and false select arguments for a matching subtract. // We check both true and false select arguments for a matching subtract.
if (match(FV, m_Zero()) && match(TV, m_Sub(m_Value(N), m_Specific(A)))) if (match(FV, m_Zero(), *Context) &&
match(TV, m_Sub(m_Value(N), m_Specific(A)), *Context))
// Fold the add into the true select value. // Fold the add into the true select value.
return SelectInst::Create(SI->getCondition(), N, A); return SelectInst::Create(SI->getCondition(), N, A);
if (match(TV, m_Zero()) && match(FV, m_Sub(m_Value(N), m_Specific(A)))) if (match(TV, m_Zero(), *Context) &&
match(FV, m_Sub(m_Value(N), m_Specific(A)), *Context))
// Fold the add into the false select value. // Fold the add into the false select value.
return SelectInst::Create(SI->getCondition(), A, N); return SelectInst::Create(SI->getCondition(), A, N);
} }
@ -2483,7 +2486,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
// C - ~X == X + (1+C) // C - ~X == X + (1+C)
Value *X = 0; Value *X = 0;
if (match(Op1, m_Not(m_Value(X)))) if (match(Op1, m_Not(m_Value(X)), *Context))
return BinaryOperator::CreateAdd(X, AddOne(C, Context)); return BinaryOperator::CreateAdd(X, AddOne(C, Context));
// -(X >>u 31) -> (X >>s 31) // -(X >>u 31) -> (X >>s 31)
@ -3786,8 +3789,10 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I,
ICmpInst::Predicate LHSCC, RHSCC; ICmpInst::Predicate LHSCC, RHSCC;
// This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2). // This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2).
if (!match(LHS, m_ICmp(LHSCC, m_Value(Val), m_ConstantInt(LHSCst))) || if (!match(LHS, m_ICmp(LHSCC, m_Value(Val),
!match(RHS, m_ICmp(RHSCC, m_Value(Val2), m_ConstantInt(RHSCst)))) m_ConstantInt(LHSCst)), *Context) ||
!match(RHS, m_ICmp(RHSCC, m_Value(Val2),
m_ConstantInt(RHSCst)), *Context))
return 0; return 0;
// (icmp ult A, C) & (icmp ult B, C) --> (icmp ult (A|B), C) // (icmp ult A, C) & (icmp ult B, C) --> (icmp ult (A|B), C)
@ -4120,30 +4125,30 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
{ {
Value *A = 0, *B = 0, *C = 0, *D = 0; Value *A = 0, *B = 0, *C = 0, *D = 0;
if (match(Op0, m_Or(m_Value(A), m_Value(B)))) { if (match(Op0, m_Or(m_Value(A), m_Value(B)), *Context)) {
if (A == Op1 || B == Op1) // (A | ?) & A --> A if (A == Op1 || B == Op1) // (A | ?) & A --> A
return ReplaceInstUsesWith(I, Op1); return ReplaceInstUsesWith(I, Op1);
// (A|B) & ~(A&B) -> A^B // (A|B) & ~(A&B) -> A^B
if (match(Op1, m_Not(m_And(m_Value(C), m_Value(D))))) { if (match(Op1, m_Not(m_And(m_Value(C), m_Value(D))), *Context)) {
if ((A == C && B == D) || (A == D && B == C)) if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B); return BinaryOperator::CreateXor(A, B);
} }
} }
if (match(Op1, m_Or(m_Value(A), m_Value(B)))) { if (match(Op1, m_Or(m_Value(A), m_Value(B)), *Context)) {
if (A == Op0 || B == Op0) // A & (A | ?) --> A if (A == Op0 || B == Op0) // A & (A | ?) --> A
return ReplaceInstUsesWith(I, Op0); return ReplaceInstUsesWith(I, Op0);
// ~(A&B) & (A|B) -> A^B // ~(A&B) & (A|B) -> A^B
if (match(Op0, m_Not(m_And(m_Value(C), m_Value(D))))) { if (match(Op0, m_Not(m_And(m_Value(C), m_Value(D))), *Context)) {
if ((A == C && B == D) || (A == D && B == C)) if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B); return BinaryOperator::CreateXor(A, B);
} }
} }
if (Op0->hasOneUse() && if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_Value(B)))) { match(Op0, m_Xor(m_Value(A), m_Value(B)), *Context)) {
if (A == Op1) { // (A^B)&A -> A&(A^B) if (A == Op1) { // (A^B)&A -> A&(A^B)
I.swapOperands(); // Simplify below I.swapOperands(); // Simplify below
std::swap(Op0, Op1); std::swap(Op0, Op1);
@ -4155,7 +4160,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
} }
if (Op1->hasOneUse() && if (Op1->hasOneUse() &&
match(Op1, m_Xor(m_Value(A), m_Value(B)))) { match(Op1, m_Xor(m_Value(A), m_Value(B)), *Context)) {
if (B == Op0) { // B&(A^B) -> B&(B^A) if (B == Op0) { // B&(A^B) -> B&(B^A)
cast<BinaryOperator>(Op1)->swapOperands(); cast<BinaryOperator>(Op1)->swapOperands();
std::swap(A, B); std::swap(A, B);
@ -4168,11 +4173,11 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
} }
// (A&((~A)|B)) -> A&B // (A&((~A)|B)) -> A&B
if (match(Op0, m_Or(m_Not(m_Specific(Op1)), m_Value(A))) || if (match(Op0, m_Or(m_Not(m_Specific(Op1)), m_Value(A)), *Context) ||
match(Op0, m_Or(m_Value(A), m_Not(m_Specific(Op1))))) match(Op0, m_Or(m_Value(A), m_Not(m_Specific(Op1))), *Context))
return BinaryOperator::CreateAnd(A, Op1); return BinaryOperator::CreateAnd(A, Op1);
if (match(Op1, m_Or(m_Not(m_Specific(Op0)), m_Value(A))) || if (match(Op1, m_Or(m_Not(m_Specific(Op0)), m_Value(A)), *Context) ||
match(Op1, m_Or(m_Value(A), m_Not(m_Specific(Op0))))) match(Op1, m_Or(m_Value(A), m_Not(m_Specific(Op0))), *Context))
return BinaryOperator::CreateAnd(A, Op0); return BinaryOperator::CreateAnd(A, Op0);
} }
@ -4238,8 +4243,10 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
} else { } else {
Value *Op0LHS, *Op0RHS, *Op1LHS, *Op1RHS; Value *Op0LHS, *Op0RHS, *Op1LHS, *Op1RHS;
FCmpInst::Predicate Op0CC, Op1CC; FCmpInst::Predicate Op0CC, Op1CC;
if (match(Op0, m_FCmp(Op0CC, m_Value(Op0LHS), m_Value(Op0RHS))) && if (match(Op0, m_FCmp(Op0CC, m_Value(Op0LHS),
match(Op1, m_FCmp(Op1CC, m_Value(Op1LHS), m_Value(Op1RHS)))) { m_Value(Op0RHS)), *Context) &&
match(Op1, m_FCmp(Op1CC, m_Value(Op1LHS),
m_Value(Op1RHS)), *Context)) {
if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) { if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) {
// Swap RHS operands to match LHS. // Swap RHS operands to match LHS.
Op1CC = FCmpInst::getSwappedPredicate(Op1CC); Op1CC = FCmpInst::getSwappedPredicate(Op1CC);
@ -4452,21 +4459,22 @@ Instruction *InstCombiner::MatchBSwap(BinaryOperator &I) {
/// If A is (cond?-1:0) and either B or D is ~(cond?-1,0) or (cond?0,-1), then /// If A is (cond?-1:0) and either B or D is ~(cond?-1,0) or (cond?0,-1), then
/// we can simplify this expression to "cond ? C : D or B". /// we can simplify this expression to "cond ? C : D or B".
static Instruction *MatchSelectFromAndOr(Value *A, Value *B, static Instruction *MatchSelectFromAndOr(Value *A, Value *B,
Value *C, Value *D) { Value *C, Value *D,
LLVMContext *Context) {
// If A is not a select of -1/0, this cannot match. // If A is not a select of -1/0, this cannot match.
Value *Cond = 0; Value *Cond = 0;
if (!match(A, m_SelectCst<-1, 0>(m_Value(Cond)))) if (!match(A, m_SelectCst<-1, 0>(m_Value(Cond)), *Context))
return 0; return 0;
// ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B. // ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B.
if (match(D, m_SelectCst<0, -1>(m_Specific(Cond)))) if (match(D, m_SelectCst<0, -1>(m_Specific(Cond)), *Context))
return SelectInst::Create(Cond, C, B); return SelectInst::Create(Cond, C, B);
if (match(D, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) if (match(D, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))), *Context))
return SelectInst::Create(Cond, C, B); return SelectInst::Create(Cond, C, B);
// ((cond?-1:0)&C) | ((cond?0:-1)&D) -> cond ? C : D. // ((cond?-1:0)&C) | ((cond?0:-1)&D) -> cond ? C : D.
if (match(B, m_SelectCst<0, -1>(m_Specific(Cond)))) if (match(B, m_SelectCst<0, -1>(m_Specific(Cond)), *Context))
return SelectInst::Create(Cond, C, D); return SelectInst::Create(Cond, C, D);
if (match(B, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) if (match(B, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))), *Context))
return SelectInst::Create(Cond, C, D); return SelectInst::Create(Cond, C, D);
return 0; return 0;
} }
@ -4479,8 +4487,10 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I,
ICmpInst::Predicate LHSCC, RHSCC; ICmpInst::Predicate LHSCC, RHSCC;
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2). // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
if (!match(LHS, m_ICmp(LHSCC, m_Value(Val), m_ConstantInt(LHSCst))) || if (!match(LHS, m_ICmp(LHSCC, m_Value(Val),
!match(RHS, m_ICmp(RHSCC, m_Value(Val2), m_ConstantInt(RHSCst)))) m_ConstantInt(LHSCst)), *Context) ||
!match(RHS, m_ICmp(RHSCC, m_Value(Val2),
m_ConstantInt(RHSCst)), *Context))
return 0; return 0;
// From here on, we only handle: // From here on, we only handle:
@ -4651,7 +4661,7 @@ Instruction *InstCombiner::FoldOrWithConstants(BinaryOperator &I, Value *Op,
Value *V1 = 0; Value *V1 = 0;
ConstantInt *CI2 = 0; ConstantInt *CI2 = 0;
if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)))) return 0; if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)), *Context)) return 0;
APInt Xor = CI1->getValue() ^ CI2->getValue(); APInt Xor = CI1->getValue() ^ CI2->getValue();
if (!Xor.isAllOnesValue()) return 0; if (!Xor.isAllOnesValue()) return 0;
@ -4693,7 +4703,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) { if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
ConstantInt *C1 = 0; Value *X = 0; ConstantInt *C1 = 0; Value *X = 0;
// (X & C1) | C2 --> (X | C2) & (C1|C2) // (X & C1) | C2 --> (X | C2) & (C1|C2)
if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) && isOnlyUse(Op0)) { if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1)), *Context) &&
isOnlyUse(Op0)) {
Instruction *Or = BinaryOperator::CreateOr(X, RHS); Instruction *Or = BinaryOperator::CreateOr(X, RHS);
InsertNewInstBefore(Or, I); InsertNewInstBefore(Or, I);
Or->takeName(Op0); Or->takeName(Op0);
@ -4702,7 +4713,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
// (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2) // (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
if (match(Op0, m_Xor(m_Value(X), m_ConstantInt(C1))) && isOnlyUse(Op0)) { if (match(Op0, m_Xor(m_Value(X), m_ConstantInt(C1)), *Context) &&
isOnlyUse(Op0)) {
Instruction *Or = BinaryOperator::CreateOr(X, RHS); Instruction *Or = BinaryOperator::CreateOr(X, RHS);
InsertNewInstBefore(Or, I); InsertNewInstBefore(Or, I);
Or->takeName(Op0); Or->takeName(Op0);
@ -4722,25 +4734,26 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
Value *A = 0, *B = 0; Value *A = 0, *B = 0;
ConstantInt *C1 = 0, *C2 = 0; ConstantInt *C1 = 0, *C2 = 0;
if (match(Op0, m_And(m_Value(A), m_Value(B)))) if (match(Op0, m_And(m_Value(A), m_Value(B)), *Context))
if (A == Op1 || B == Op1) // (A & ?) | A --> A if (A == Op1 || B == Op1) // (A & ?) | A --> A
return ReplaceInstUsesWith(I, Op1); return ReplaceInstUsesWith(I, Op1);
if (match(Op1, m_And(m_Value(A), m_Value(B)))) if (match(Op1, m_And(m_Value(A), m_Value(B)), *Context))
if (A == Op0 || B == Op0) // A | (A & ?) --> A if (A == Op0 || B == Op0) // A | (A & ?) --> A
return ReplaceInstUsesWith(I, Op0); return ReplaceInstUsesWith(I, Op0);
// (A | B) | C and A | (B | C) -> bswap if possible. // (A | B) | C and A | (B | C) -> bswap if possible.
// (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible. // (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
if (match(Op0, m_Or(m_Value(), m_Value())) || if (match(Op0, m_Or(m_Value(), m_Value()), *Context) ||
match(Op1, m_Or(m_Value(), m_Value())) || match(Op1, m_Or(m_Value(), m_Value()), *Context) ||
(match(Op0, m_Shift(m_Value(), m_Value())) && (match(Op0, m_Shift(m_Value(), m_Value()), *Context) &&
match(Op1, m_Shift(m_Value(), m_Value())))) { match(Op1, m_Shift(m_Value(), m_Value()), *Context))) {
if (Instruction *BSwap = MatchBSwap(I)) if (Instruction *BSwap = MatchBSwap(I))
return BSwap; return BSwap;
} }
// (X^C)|Y -> (X|Y)^C iff Y&C == 0 // (X^C)|Y -> (X|Y)^C iff Y&C == 0
if (Op0->hasOneUse() && match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) && if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1)), *Context) &&
MaskedValueIsZero(Op1, C1->getValue())) { MaskedValueIsZero(Op1, C1->getValue())) {
Instruction *NOr = BinaryOperator::CreateOr(A, Op1); Instruction *NOr = BinaryOperator::CreateOr(A, Op1);
InsertNewInstBefore(NOr, I); InsertNewInstBefore(NOr, I);
@ -4749,7 +4762,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
// Y|(X^C) -> (X|Y)^C iff Y&C == 0 // Y|(X^C) -> (X|Y)^C iff Y&C == 0
if (Op1->hasOneUse() && match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) && if (Op1->hasOneUse() &&
match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1)), *Context) &&
MaskedValueIsZero(Op0, C1->getValue())) { MaskedValueIsZero(Op0, C1->getValue())) {
Instruction *NOr = BinaryOperator::CreateOr(A, Op0); Instruction *NOr = BinaryOperator::CreateOr(A, Op0);
InsertNewInstBefore(NOr, I); InsertNewInstBefore(NOr, I);
@ -4759,8 +4773,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
// (A & C)|(B & D) // (A & C)|(B & D)
Value *C = 0, *D = 0; Value *C = 0, *D = 0;
if (match(Op0, m_And(m_Value(A), m_Value(C))) && if (match(Op0, m_And(m_Value(A), m_Value(C)), *Context) &&
match(Op1, m_And(m_Value(B), m_Value(D)))) { match(Op1, m_And(m_Value(B), m_Value(D)), *Context)) {
Value *V1 = 0, *V2 = 0, *V3 = 0; Value *V1 = 0, *V2 = 0, *V3 = 0;
C1 = dyn_cast<ConstantInt>(C); C1 = dyn_cast<ConstantInt>(C);
C2 = dyn_cast<ConstantInt>(D); C2 = dyn_cast<ConstantInt>(D);
@ -4770,7 +4784,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
// replace with V+N. // replace with V+N.
if (C1->getValue() == ~C2->getValue()) { if (C1->getValue() == ~C2->getValue()) {
if ((C2->getValue() & (C2->getValue()+1)) == 0 && // C2 == 0+1+ if ((C2->getValue() & (C2->getValue()+1)) == 0 && // C2 == 0+1+
match(A, m_Add(m_Value(V1), m_Value(V2)))) { match(A, m_Add(m_Value(V1), m_Value(V2)), *Context)) {
// Add commutes, try both ways. // Add commutes, try both ways.
if (V1 == B && MaskedValueIsZero(V2, C2->getValue())) if (V1 == B && MaskedValueIsZero(V2, C2->getValue()))
return ReplaceInstUsesWith(I, A); return ReplaceInstUsesWith(I, A);
@ -4779,7 +4793,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
// Or commutes, try both ways. // Or commutes, try both ways.
if ((C1->getValue() & (C1->getValue()+1)) == 0 && if ((C1->getValue() & (C1->getValue()+1)) == 0 &&
match(B, m_Add(m_Value(V1), m_Value(V2)))) { match(B, m_Add(m_Value(V1), m_Value(V2)), *Context)) {
// Add commutes, try both ways. // Add commutes, try both ways.
if (V1 == A && MaskedValueIsZero(V2, C1->getValue())) if (V1 == A && MaskedValueIsZero(V2, C1->getValue()))
return ReplaceInstUsesWith(I, B); return ReplaceInstUsesWith(I, B);
@ -4810,30 +4824,30 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
// (A & (C0?-1:0)) | (B & ~(C0?-1:0)) -> C0 ? A : B, and commuted variants // (A & (C0?-1:0)) | (B & ~(C0?-1:0)) -> C0 ? A : B, and commuted variants
if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D)) if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D, Context))
return Match; return Match;
if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C)) if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C, Context))
return Match; return Match;
if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D)) if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D, Context))
return Match; return Match;
if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C)) if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C, Context))
return Match; return Match;
// ((A&~B)|(~A&B)) -> A^B // ((A&~B)|(~A&B)) -> A^B
if ((match(C, m_Not(m_Specific(D))) && if ((match(C, m_Not(m_Specific(D)), *Context) &&
match(B, m_Not(m_Specific(A))))) match(B, m_Not(m_Specific(A)), *Context)))
return BinaryOperator::CreateXor(A, D); return BinaryOperator::CreateXor(A, D);
// ((~B&A)|(~A&B)) -> A^B // ((~B&A)|(~A&B)) -> A^B
if ((match(A, m_Not(m_Specific(D))) && if ((match(A, m_Not(m_Specific(D)), *Context) &&
match(B, m_Not(m_Specific(C))))) match(B, m_Not(m_Specific(C)), *Context)))
return BinaryOperator::CreateXor(C, D); return BinaryOperator::CreateXor(C, D);
// ((A&~B)|(B&~A)) -> A^B // ((A&~B)|(B&~A)) -> A^B
if ((match(C, m_Not(m_Specific(B))) && if ((match(C, m_Not(m_Specific(B)), *Context) &&
match(D, m_Not(m_Specific(A))))) match(D, m_Not(m_Specific(A)), *Context)))
return BinaryOperator::CreateXor(A, B); return BinaryOperator::CreateXor(A, B);
// ((~B&A)|(B&~A)) -> A^B // ((~B&A)|(B&~A)) -> A^B
if ((match(A, m_Not(m_Specific(B))) && if ((match(A, m_Not(m_Specific(B)), *Context) &&
match(D, m_Not(m_Specific(C))))) match(D, m_Not(m_Specific(C)), *Context)))
return BinaryOperator::CreateXor(C, B); return BinaryOperator::CreateXor(C, B);
} }
@ -4853,26 +4867,26 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
// ((A|B)&1)|(B&-2) -> (A&1) | B // ((A|B)&1)|(B&-2) -> (A&1) | B
if (match(Op0, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) || if (match(Op0, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C)), *Context) ||
match(Op0, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) { match(Op0, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))), *Context)) {
Instruction *Ret = FoldOrWithConstants(I, Op1, A, B, C); Instruction *Ret = FoldOrWithConstants(I, Op1, A, B, C);
if (Ret) return Ret; if (Ret) return Ret;
} }
// (B&-2)|((A|B)&1) -> (A&1) | B // (B&-2)|((A|B)&1) -> (A&1) | B
if (match(Op1, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) || if (match(Op1, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C)), *Context) ||
match(Op1, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) { match(Op1, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))), *Context)) {
Instruction *Ret = FoldOrWithConstants(I, Op0, A, B, C); Instruction *Ret = FoldOrWithConstants(I, Op0, A, B, C);
if (Ret) return Ret; if (Ret) return Ret;
} }
if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1 if (match(Op0, m_Not(m_Value(A)), *Context)) { // ~A | Op1
if (A == Op1) // ~A | A == -1 if (A == Op1) // ~A | A == -1
return ReplaceInstUsesWith(I, Context->getAllOnesValue(I.getType())); return ReplaceInstUsesWith(I, Context->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 (match(Op1, m_Not(m_Value(B)), *Context)) { // Op0 | ~B
if (Op0 == B) if (Op0 == B)
return ReplaceInstUsesWith(I, Context->getAllOnesValue(I.getType())); return ReplaceInstUsesWith(I, Context->getAllOnesValue(I.getType()));
@ -4940,8 +4954,10 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} else { } else {
Value *Op0LHS, *Op0RHS, *Op1LHS, *Op1RHS; Value *Op0LHS, *Op0RHS, *Op1LHS, *Op1RHS;
FCmpInst::Predicate Op0CC, Op1CC; FCmpInst::Predicate Op0CC, Op1CC;
if (match(Op0, m_FCmp(Op0CC, m_Value(Op0LHS), m_Value(Op0RHS))) && if (match(Op0, m_FCmp(Op0CC, m_Value(Op0LHS),
match(Op1, m_FCmp(Op1CC, m_Value(Op1LHS), m_Value(Op1RHS)))) { m_Value(Op0RHS)), *Context) &&
match(Op1, m_FCmp(Op1CC, m_Value(Op1LHS),
m_Value(Op1RHS)), *Context)) {
if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) { if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) {
// Swap RHS operands to match LHS. // Swap RHS operands to match LHS.
Op1CC = FCmpInst::getSwappedPredicate(Op1CC); Op1CC = FCmpInst::getSwappedPredicate(Op1CC);
@ -5143,7 +5159,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1); BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
if (Op1I) { if (Op1I) {
Value *A, *B; Value *A, *B;
if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) { if (match(Op1I, m_Or(m_Value(A), m_Value(B)), *Context)) {
if (A == Op0) { // B^(B|A) == (A|B)^B if (A == Op0) { // B^(B|A) == (A|B)^B
Op1I->swapOperands(); Op1I->swapOperands();
I.swapOperands(); I.swapOperands();
@ -5152,11 +5168,12 @@ 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)))) { } else if (match(Op1I, m_Xor(m_Specific(Op0), m_Value(B)), *Context)) {
return ReplaceInstUsesWith(I, B); // A^(A^B) == B return ReplaceInstUsesWith(I, B); // A^(A^B) == B
} else if (match(Op1I, m_Xor(m_Value(A), m_Specific(Op0)))) { } else if (match(Op1I, m_Xor(m_Value(A), m_Specific(Op0)), *Context)) {
return ReplaceInstUsesWith(I, A); // A^(B^A) == B return ReplaceInstUsesWith(I, A); // A^(B^A) == B
} else if (match(Op1I, m_And(m_Value(A), m_Value(B))) && Op1I->hasOneUse()){ } else if (match(Op1I, m_And(m_Value(A), m_Value(B)), *Context) &&
Op1I->hasOneUse()){
if (A == Op0) { // A^(A&B) -> A^(B&A) if (A == Op0) { // A^(A&B) -> A^(B&A)
Op1I->swapOperands(); Op1I->swapOperands();
std::swap(A, B); std::swap(A, B);
@ -5171,7 +5188,8 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0); BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0);
if (Op0I) { if (Op0I) {
Value *A, *B; Value *A, *B;
if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && Op0I->hasOneUse()) { if (match(Op0I, m_Or(m_Value(A), m_Value(B)), *Context) &&
Op0I->hasOneUse()) {
if (A == Op1) // (B|A)^B == (A|B)^B if (A == Op1) // (B|A)^B == (A|B)^B
std::swap(A, B); std::swap(A, B);
if (B == Op1) { // (A|B)^B == A & ~B if (B == Op1) { // (A|B)^B == A & ~B
@ -5179,11 +5197,12 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
InsertNewInstBefore(BinaryOperator::CreateNot(Op1, "tmp"), I); InsertNewInstBefore(BinaryOperator::CreateNot(Op1, "tmp"), I);
return BinaryOperator::CreateAnd(A, NotB); return BinaryOperator::CreateAnd(A, NotB);
} }
} else if (match(Op0I, m_Xor(m_Specific(Op1), m_Value(B)))) { } else if (match(Op0I, m_Xor(m_Specific(Op1), m_Value(B)), *Context)) {
return ReplaceInstUsesWith(I, B); // (A^B)^A == B return ReplaceInstUsesWith(I, B); // (A^B)^A == B
} else if (match(Op0I, m_Xor(m_Value(A), m_Specific(Op1)))) { } else if (match(Op0I, m_Xor(m_Value(A), m_Specific(Op1)), *Context)) {
return ReplaceInstUsesWith(I, A); // (B^A)^A == B return ReplaceInstUsesWith(I, A); // (B^A)^A == B
} else if (match(Op0I, m_And(m_Value(A), m_Value(B))) && Op0I->hasOneUse()){ } else if (match(Op0I, m_And(m_Value(A), m_Value(B)), *Context) &&
Op0I->hasOneUse()){
if (A == Op1) // (A&B)^A -> (B&A)^A if (A == Op1) // (A&B)^A -> (B&A)^A
std::swap(A, B); std::swap(A, B);
if (B == Op1 && // (B&A)^A == ~B & A if (B == Op1 && // (B&A)^A == ~B & A
@ -5211,22 +5230,22 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (Op0I && Op1I) { if (Op0I && Op1I) {
Value *A, *B, *C, *D; Value *A, *B, *C, *D;
// (A & B)^(A | B) -> A ^ B // (A & B)^(A | B) -> A ^ B
if (match(Op0I, m_And(m_Value(A), m_Value(B))) && if (match(Op0I, m_And(m_Value(A), m_Value(B)), *Context) &&
match(Op1I, m_Or(m_Value(C), m_Value(D)))) { match(Op1I, m_Or(m_Value(C), m_Value(D)), *Context)) {
if ((A == C && B == D) || (A == D && B == C)) if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B); return BinaryOperator::CreateXor(A, B);
} }
// (A | B)^(A & B) -> A ^ B // (A | B)^(A & B) -> A ^ B
if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && if (match(Op0I, m_Or(m_Value(A), m_Value(B)), *Context) &&
match(Op1I, m_And(m_Value(C), m_Value(D)))) { match(Op1I, m_And(m_Value(C), m_Value(D)), *Context)) {
if ((A == C && B == D) || (A == D && B == C)) if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B); return BinaryOperator::CreateXor(A, B);
} }
// (A & B)^(C & D) // (A & B)^(C & D)
if ((Op0I->hasOneUse() || Op1I->hasOneUse()) && if ((Op0I->hasOneUse() || Op1I->hasOneUse()) &&
match(Op0I, m_And(m_Value(A), m_Value(B))) && match(Op0I, m_And(m_Value(A), m_Value(B)), *Context) &&
match(Op1I, m_And(m_Value(C), m_Value(D)))) { match(Op1I, m_And(m_Value(C), m_Value(D)), *Context)) {
// (X & Y)^(X & Y) -> (Y^Z) & X // (X & Y)^(X & Y) -> (Y^Z) & X
Value *X = 0, *Y = 0, *Z = 0; Value *X = 0, *Y = 0, *Z = 0;
if (A == C) if (A == C)
@ -6033,7 +6052,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// (icmp ne/eq (sub A B) 0) -> (icmp ne/eq A, B) // (icmp ne/eq (sub A B) 0) -> (icmp ne/eq A, B)
if (I.isEquality() && CI->isNullValue() && if (I.isEquality() && CI->isNullValue() &&
match(Op0, m_Sub(m_Value(A), m_Value(B)))) { match(Op0, m_Sub(m_Value(A), m_Value(B)), *Context)) {
// (icmp cond A B) if cond is equality // (icmp cond A B) if cond is equality
return new ICmpInst(*Context, I.getPredicate(), A, B); return new ICmpInst(*Context, I.getPredicate(), A, B);
} }
@ -6431,8 +6450,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// ~x < ~y --> y < x // ~x < ~y --> y < x
{ Value *A, *B; { Value *A, *B;
if (match(Op0, m_Not(m_Value(A))) && if (match(Op0, m_Not(m_Value(A)), *Context) &&
match(Op1, m_Not(m_Value(B)))) match(Op1, m_Not(m_Value(B)), *Context))
return new ICmpInst(*Context, I.getPredicate(), B, A); return new ICmpInst(*Context, I.getPredicate(), B, A);
} }
@ -6440,22 +6459,22 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
Value *A, *B, *C, *D; Value *A, *B, *C, *D;
// -x == -y --> x == y // -x == -y --> x == y
if (match(Op0, m_Neg(m_Value(A))) && if (match(Op0, m_Neg(m_Value(A)), *Context) &&
match(Op1, m_Neg(m_Value(B)))) match(Op1, m_Neg(m_Value(B)), *Context))
return new ICmpInst(*Context, I.getPredicate(), A, B); return new ICmpInst(*Context, I.getPredicate(), A, B);
if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) { if (match(Op0, m_Xor(m_Value(A), m_Value(B)), *Context)) {
if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0 if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0
Value *OtherVal = A == Op1 ? B : A; Value *OtherVal = A == Op1 ? B : A;
return new ICmpInst(*Context, I.getPredicate(), OtherVal, return new ICmpInst(*Context, I.getPredicate(), OtherVal,
Context->getNullValue(A->getType())); Context->getNullValue(A->getType()));
} }
if (match(Op1, m_Xor(m_Value(C), m_Value(D)))) { if (match(Op1, m_Xor(m_Value(C), m_Value(D)), *Context)) {
// A^c1 == C^c2 --> A == C^(c1^c2) // A^c1 == C^c2 --> A == C^(c1^c2)
ConstantInt *C1, *C2; ConstantInt *C1, *C2;
if (match(B, m_ConstantInt(C1)) && if (match(B, m_ConstantInt(C1), *Context) &&
match(D, m_ConstantInt(C2)) && Op1->hasOneUse()) { match(D, m_ConstantInt(C2), *Context) && Op1->hasOneUse()) {
Constant *NC = Constant *NC =
Context->getConstantInt(C1->getValue() ^ C2->getValue()); Context->getConstantInt(C1->getValue() ^ C2->getValue());
Instruction *Xor = BinaryOperator::CreateXor(C, NC, "tmp"); Instruction *Xor = BinaryOperator::CreateXor(C, NC, "tmp");
@ -6471,7 +6490,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
} }
} }
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && if (match(Op1, m_Xor(m_Value(A), m_Value(B)), *Context) &&
(A == Op0 || B == Op0)) { (A == Op0 || B == Op0)) {
// A == (A^B) -> B == 0 // A == (A^B) -> B == 0
Value *OtherVal = A == Op0 ? B : A; Value *OtherVal = A == Op0 ? B : A;
@ -6480,19 +6499,19 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
} }
// (A-B) == A -> B == 0 // (A-B) == A -> B == 0
if (match(Op0, m_Sub(m_Specific(Op1), m_Value(B)))) if (match(Op0, m_Sub(m_Specific(Op1), m_Value(B)), *Context))
return new ICmpInst(*Context, I.getPredicate(), B, return new ICmpInst(*Context, I.getPredicate(), B,
Context->getNullValue(B->getType())); Context->getNullValue(B->getType()));
// A == (A-B) -> B == 0 // A == (A-B) -> B == 0
if (match(Op1, m_Sub(m_Specific(Op0), m_Value(B)))) if (match(Op1, m_Sub(m_Specific(Op0), m_Value(B)), *Context))
return new ICmpInst(*Context, I.getPredicate(), B, return new ICmpInst(*Context, I.getPredicate(), B,
Context->getNullValue(B->getType())); Context->getNullValue(B->getType()));
// (X&Z) == (Y&Z) -> (X^Y) & Z == 0 // (X&Z) == (Y&Z) -> (X^Y) & Z == 0
if (Op0->hasOneUse() && Op1->hasOneUse() && if (Op0->hasOneUse() && Op1->hasOneUse() &&
match(Op0, m_And(m_Value(A), m_Value(B))) && match(Op0, m_And(m_Value(A), m_Value(B)), *Context) &&
match(Op1, m_And(m_Value(C), m_Value(D)))) { match(Op1, m_And(m_Value(C), m_Value(D)), *Context)) {
Value *X = 0, *Y = 0, *Z = 0; Value *X = 0, *Y = 0, *Z = 0;
if (A == C) { if (A == C) {
@ -7458,7 +7477,8 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
// These operators commute. // These operators commute.
// Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C) // Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C)
if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
match(Op0BO->getOperand(1), m_Shr(m_Value(V1), m_Specific(Op1)))){ match(Op0BO->getOperand(1), m_Shr(m_Value(V1),
m_Specific(Op1)), *Context)){
Instruction *YS = BinaryOperator::CreateShl( Instruction *YS = BinaryOperator::CreateShl(
Op0BO->getOperand(0), Op1, Op0BO->getOperand(0), Op1,
Op0BO->getName()); Op0BO->getName());
@ -7477,7 +7497,7 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
if (isLeftShift && Op0BOOp1->hasOneUse() && if (isLeftShift && Op0BOOp1->hasOneUse() &&
match(Op0BOOp1, match(Op0BOOp1,
m_And(m_Shr(m_Value(V1), m_Specific(Op1)), m_And(m_Shr(m_Value(V1), m_Specific(Op1)),
m_ConstantInt(CC))) && m_ConstantInt(CC)), *Context) &&
cast<BinaryOperator>(Op0BOOp1)->getOperand(0)->hasOneUse()) { cast<BinaryOperator>(Op0BOOp1)->getOperand(0)->hasOneUse()) {
Instruction *YS = BinaryOperator::CreateShl( Instruction *YS = BinaryOperator::CreateShl(
Op0BO->getOperand(0), Op1, Op0BO->getOperand(0), Op1,
@ -7497,7 +7517,8 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
case Instruction::Sub: { case Instruction::Sub: {
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
match(Op0BO->getOperand(0), m_Shr(m_Value(V1), m_Specific(Op1)))){ match(Op0BO->getOperand(0), m_Shr(m_Value(V1),
m_Specific(Op1)), *Context)){
Instruction *YS = BinaryOperator::CreateShl( Instruction *YS = BinaryOperator::CreateShl(
Op0BO->getOperand(1), Op1, Op0BO->getOperand(1), Op1,
Op0BO->getName()); Op0BO->getName());
@ -7515,7 +7536,7 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
match(Op0BO->getOperand(0), match(Op0BO->getOperand(0),
m_And(m_Shr(m_Value(V1), m_Value(V2)), m_And(m_Shr(m_Value(V1), m_Value(V2)),
m_ConstantInt(CC))) && V2 == Op1 && m_ConstantInt(CC)), *Context) && V2 == Op1 &&
cast<BinaryOperator>(Op0BO->getOperand(0)) cast<BinaryOperator>(Op0BO->getOperand(0))
->getOperand(0)->hasOneUse()) { ->getOperand(0)->hasOneUse()) {
Instruction *YS = BinaryOperator::CreateShl( Instruction *YS = BinaryOperator::CreateShl(
@ -8476,7 +8497,7 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
ConstantInt *ShAmtV = 0; ConstantInt *ShAmtV = 0;
Value *ShiftOp = 0; Value *ShiftOp = 0;
if (Src->hasOneUse() && if (Src->hasOneUse() &&
match(Src, m_LShr(m_Value(ShiftOp), m_ConstantInt(ShAmtV)))) { match(Src, m_LShr(m_Value(ShiftOp), m_ConstantInt(ShAmtV)), *Context)) {
uint32_t ShAmt = ShAmtV->getLimitedValue(SrcBitWidth); uint32_t ShAmt = ShAmtV->getLimitedValue(SrcBitWidth);
// Get a mask for the bits shifting in. // Get a mask for the bits shifting in.
@ -8736,7 +8757,7 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
Value *A = 0; Value *A = 0;
ConstantInt *BA = 0, *CA = 0; ConstantInt *BA = 0, *CA = 0;
if (match(Src, m_AShr(m_Shl(m_Value(A), m_ConstantInt(BA)), if (match(Src, m_AShr(m_Shl(m_Value(A), m_ConstantInt(BA)),
m_ConstantInt(CA))) && m_ConstantInt(CA)), *Context) &&
BA == CA && isa<TruncInst>(A)) { BA == CA && isa<TruncInst>(A)) {
Value *I = cast<TruncInst>(A)->getOperand(0); Value *I = cast<TruncInst>(A)->getOperand(0);
if (I->getType() == CI.getType()) { if (I->getType() == CI.getType()) {
@ -8923,7 +8944,7 @@ Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) {
ConstantInt *Cst; ConstantInt *Cst;
Value *X; Value *X;
if (match(CI.getOperand(0), m_Add(m_Cast<PtrToIntInst>(m_Value(X)), if (match(CI.getOperand(0), m_Add(m_Cast<PtrToIntInst>(m_Value(X)),
m_ConstantInt(Cst)))) { m_ConstantInt(Cst)), *Context)) {
// If the source and destination operands have the same type, see if this // If the source and destination operands have the same type, see if this
// is a single-index GEP. // is a single-index GEP.
if (X->getType() == CI.getType()) { if (X->getType() == CI.getType()) {
@ -8943,7 +8964,8 @@ Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) {
// TODO: Could handle other cases, e.g. where add is indexing into field of // TODO: Could handle other cases, e.g. where add is indexing into field of
// struct etc. // struct etc.
} else if (CI.getOperand(0)->hasOneUse() && } else if (CI.getOperand(0)->hasOneUse() &&
match(CI.getOperand(0), m_Add(m_Value(X), m_ConstantInt(Cst)))) { match(CI.getOperand(0), m_Add(m_Value(X),
m_ConstantInt(Cst)), *Context)) {
// Otherwise, if this is inttoptr(add x, cst), try to turn this into an // Otherwise, if this is inttoptr(add x, cst), try to turn this into an
// "inttoptr+GEP" instead of "add+intptr". // "inttoptr+GEP" instead of "add+intptr".
@ -9319,11 +9341,11 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
// (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed // (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed
// (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed
CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
if (match(TrueVal, m_ConstantInt<-1>()) && if (match(TrueVal, m_ConstantInt<-1>(), *Context) &&
match(FalseVal, m_ConstantInt<0>())) match(FalseVal, m_ConstantInt<0>(), *Context))
Pred = ICI->getPredicate(); Pred = ICI->getPredicate();
else if (match(TrueVal, m_ConstantInt<0>()) && else if (match(TrueVal, m_ConstantInt<0>(), *Context) &&
match(FalseVal, m_ConstantInt<-1>())) match(FalseVal, m_ConstantInt<-1>(), *Context))
Pred = CmpInst::getInversePredicate(ICI->getPredicate()); Pred = CmpInst::getInversePredicate(ICI->getPredicate());
if (Pred != CmpInst::BAD_ICMP_PREDICATE) { if (Pred != CmpInst::BAD_ICMP_PREDICATE) {
@ -12101,7 +12123,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
Value *X = 0; Value *X = 0;
BasicBlock *TrueDest; BasicBlock *TrueDest;
BasicBlock *FalseDest; BasicBlock *FalseDest;
if (match(&BI, m_Br(m_Not(m_Value(X)), TrueDest, FalseDest)) && if (match(&BI, m_Br(m_Not(m_Value(X)), TrueDest, FalseDest), *Context) &&
!isa<Constant>(X)) { !isa<Constant>(X)) {
// Swap Destinations and condition... // Swap Destinations and condition...
BI.setCondition(X); BI.setCondition(X);
@ -12113,7 +12135,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
// Cannonicalize fcmp_one -> fcmp_oeq // Cannonicalize fcmp_one -> fcmp_oeq
FCmpInst::Predicate FPred; Value *Y; FCmpInst::Predicate FPred; Value *Y;
if (match(&BI, m_Br(m_FCmp(FPred, m_Value(X), m_Value(Y)), if (match(&BI, m_Br(m_FCmp(FPred, m_Value(X), m_Value(Y)),
TrueDest, FalseDest))) TrueDest, FalseDest), *Context))
if ((FPred == FCmpInst::FCMP_ONE || FPred == FCmpInst::FCMP_OLE || if ((FPred == FCmpInst::FCMP_ONE || FPred == FCmpInst::FCMP_OLE ||
FPred == FCmpInst::FCMP_OGE) && BI.getCondition()->hasOneUse()) { FPred == FCmpInst::FCMP_OGE) && BI.getCondition()->hasOneUse()) {
FCmpInst *I = cast<FCmpInst>(BI.getCondition()); FCmpInst *I = cast<FCmpInst>(BI.getCondition());
@ -12133,7 +12155,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
// Cannonicalize icmp_ne -> icmp_eq // Cannonicalize icmp_ne -> icmp_eq
ICmpInst::Predicate IPred; ICmpInst::Predicate IPred;
if (match(&BI, m_Br(m_ICmp(IPred, m_Value(X), m_Value(Y)), if (match(&BI, m_Br(m_ICmp(IPred, m_Value(X), m_Value(Y)),
TrueDest, FalseDest))) TrueDest, FalseDest), *Context))
if ((IPred == ICmpInst::ICMP_NE || IPred == ICmpInst::ICMP_ULE || if ((IPred == ICmpInst::ICMP_NE || IPred == ICmpInst::ICMP_ULE ||
IPred == ICmpInst::ICMP_SLE || IPred == ICmpInst::ICMP_UGE || IPred == ICmpInst::ICMP_SLE || IPred == ICmpInst::ICMP_UGE ||
IPred == ICmpInst::ICMP_SGE) && BI.getCondition()->hasOneUse()) { IPred == ICmpInst::ICMP_SGE) && BI.getCondition()->hasOneUse()) {

View File

@ -96,7 +96,8 @@ bool AddressingModeMatcher::MatchScaledValue(Value *ScaleReg, int64_t Scale,
// X*Scale + C*Scale to addr mode. // X*Scale + C*Scale to addr mode.
ConstantInt *CI = 0; Value *AddLHS = 0; ConstantInt *CI = 0; Value *AddLHS = 0;
if (isa<Instruction>(ScaleReg) && // not a constant expr. if (isa<Instruction>(ScaleReg) && // not a constant expr.
match(ScaleReg, m_Add(m_Value(AddLHS), m_ConstantInt(CI)))) { match(ScaleReg, m_Add(m_Value(AddLHS), m_ConstantInt(CI)),
*MemoryInst->getParent()->getContext())) {
TestAddrMode.ScaledReg = AddLHS; TestAddrMode.ScaledReg = AddLHS;
TestAddrMode.BaseOffs += CI->getSExtValue()*TestAddrMode.Scale; TestAddrMode.BaseOffs += CI->getSExtValue()*TestAddrMode.Scale;