// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
Value *InstCombinerImpl::foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS,
ICmpInst *RHS,
- BinaryOperator &Logic) {
- bool JoinedByAnd = Logic.getOpcode() == Instruction::And;
- assert((JoinedByAnd || Logic.getOpcode() == Instruction::Or) &&
- "Wrong opcode");
- ICmpInst::Predicate Pred = LHS->getPredicate();
- if (Pred != RHS->getPredicate())
- return nullptr;
- if (JoinedByAnd && Pred != ICmpInst::ICMP_NE)
- return nullptr;
- if (!JoinedByAnd && Pred != ICmpInst::ICMP_EQ)
+ Instruction *CxtI,
+ bool IsAnd) {
+ CmpInst::Predicate Pred = IsAnd ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
+ if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)
return nullptr;
if (!match(LHS->getOperand(1), m_Zero()) ||
!match(RHS->getOperand(1), m_Zero()))
return nullptr;
- Value *A, *B, *C, *D;
- if (match(LHS->getOperand(0), m_And(m_Value(A), m_Value(B))) &&
- match(RHS->getOperand(0), m_And(m_Value(C), m_Value(D)))) {
- if (A == D || B == D)
- std::swap(C, D);
- if (B == C)
- std::swap(A, B);
-
- if (A == C &&
- isKnownToBeAPowerOfTwo(B, false, 0, &Logic) &&
- isKnownToBeAPowerOfTwo(D, false, 0, &Logic)) {
- Value *Mask = Builder.CreateOr(B, D);
- Value *Masked = Builder.CreateAnd(A, Mask);
- auto NewPred = JoinedByAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
+ Value *L1, *L2, *R1, *R2;
+ if (match(LHS->getOperand(0), m_And(m_Value(L1), m_Value(L2))) &&
+ match(RHS->getOperand(0), m_And(m_Value(R1), m_Value(R2)))) {
+ if (L1 == R2 || L2 == R2)
+ std::swap(R1, R2);
+ if (L2 == R1)
+ std::swap(L1, L2);
+
+ if (L1 == R1 &&
+ isKnownToBeAPowerOfTwo(L2, false, 0, CxtI) &&
+ isKnownToBeAPowerOfTwo(R2, false, 0, CxtI)) {
+ Value *Mask = Builder.CreateOr(L2, R2);
+ Value *Masked = Builder.CreateAnd(L1, Mask);
+ auto NewPred = IsAnd ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE;
return Builder.CreateICmp(NewPred, Masked, Mask);
}
}
// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
// if K1 and K2 are a one-bit mask.
- if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, And))
+ if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, &And,
+ /* IsAnd */ true))
return V;
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
// if K1 and K2 are a one-bit mask.
- if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, Or))
+ if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, &Or,
+ /* IsAnd */ false))
return V;
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();