return LogicalOp_match<LHS, RHS, Instruction::And>(L, R);
}
+/// Matches L && R where L and R are arbitrary values.
+inline auto m_LogicalAnd() { return m_LogicalAnd(m_Value(), m_Value()); }
+
/// Matches L || R either in the form of L | R or L ? true : R.
/// Note that the latter form is poison-blocking.
template <typename LHS, typename RHS>
return match(V0, m_Not(m_Value())) && match(V1, Invertible);
};
- // Don't fold i1 branches on PHIs which contain binary operators, unless one
- // of the incoming values is an 'not' and another one is freely invertible.
+ // Don't fold i1 branches on PHIs which contain binary operators or
+ // select form of or/ands, unless one of the incoming values is an 'not' and
+ // another one is freely invertible.
// These can often be turned into switches and other things.
+ auto IsBinOpOrAnd = [](Value *V) {
+ return match(
+ V, m_CombineOr(m_BinOp(), m_CombineOr(m_LogicalAnd(), m_LogicalOr())));
+ };
if (PN->getType()->isIntegerTy(1) &&
- (isa<BinaryOperator>(PN->getIncomingValue(0)) ||
- isa<BinaryOperator>(PN->getIncomingValue(1)) ||
- isa<BinaryOperator>(IfCond)) &&
+ (IsBinOpOrAnd(PN->getIncomingValue(0)) ||
+ IsBinOpOrAnd(PN->getIncomingValue(1)) || IsBinOpOrAnd(IfCond)) &&
!CanHoistNotFromBothValues(PN->getIncomingValue(0),
PN->getIncomingValue(1)))
return Changed;