[llvm] [InstCombine] Support and/or in `getFreelyInvertedImpl` using DeMorgan's Law (PR #85193)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 14 08:15:57 PDT 2024
================
@@ -2596,6 +2596,45 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
return nullptr;
}
+ // De Morgan's Laws:
+ // (~(A | B)) -> (~A & ~B)
+ // (~(A & B)) -> (~A | ~B)
+ auto TryInvertAndOrUsingDeMorgan = [&](Instruction::BinaryOps Opcode,
+ bool IsLogical, Value *A,
+ Value *B) -> Value * {
+ bool LocalDoesConsume = DoesConsume;
+ if (!getFreelyInvertedImpl(B, B->hasOneUse(), /*Builder=*/nullptr,
+ LocalDoesConsume, Depth))
+ return nullptr;
+ if (auto *NotA = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ LocalDoesConsume, Depth)) {
+ auto *NotB = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ LocalDoesConsume, Depth);
+ DoesConsume = LocalDoesConsume;
+ if (IsLogical)
+ return Builder ? Builder->CreateLogicalOp(Opcode, NotA, NotB) : NonNull;
+ return Builder ? Builder->CreateBinOp(Opcode, NotA, NotB) : NonNull;
+ }
+
+ return nullptr;
+ };
+
+ if (match(V, m_Or(m_Value(A), m_Value(B))))
+ return TryInvertAndOrUsingDeMorgan(Instruction::And, /*IsLogical=*/false, A,
+ B);
+
+ if (match(V, m_And(m_Value(A), m_Value(B))))
+ return TryInvertAndOrUsingDeMorgan(Instruction::Or, /*IsLogical=*/false, A,
+ B);
+
+ if (match(V, m_LogicalOr(m_Value(A), m_Value(B))))
+ return TryInvertAndOrUsingDeMorgan(Instruction::And, /*IsLogical=*/true, A,
+ B);
+
+ if (match(V, m_LogicalAnd(m_Value(A), m_Value(B))))
+ return TryInvertAndOrUsingDeMorgan(Instruction::Or, /*IsLogical=*/true, A,
+ B);
----------------
nikic wrote:
I'd just keep the m_Logical cases and then do `bool IsLogical = isa<SelectInst>` inside the helper.
https://github.com/llvm/llvm-project/pull/85193
More information about the llvm-commits
mailing list