[llvm] [VPlan] Simplify (X && Y) || (X && !Y) -> X. (PR #89386)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 21 23:30:03 PDT 2024


================
@@ -192,6 +191,47 @@ using AllBinaryRecipe_match =
     BinaryRecipe_match<Op0_t, Op1_t, Opcode, VPWidenRecipe, VPReplicateRecipe,
                        VPWidenCastRecipe, VPInstruction>;
 
+template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutable,
+          typename... RecipeTys>
+struct LogicalRecipe_match {
+  Op0_t LHS;
+  Op1_t RHS;
+
+  LogicalRecipe_match(Op0_t LHS, Op1_t RHS) : LHS(LHS), RHS(RHS) {}
+
+  bool match(const VPValue *V) {
+    auto *DefR = V->getDefiningRecipe();
+    return DefR && match(DefR);
+  }
+
+  bool match(const VPSingleDefRecipe *R) {
+    return match(static_cast<const VPRecipeBase *>(R));
+  }
+
+  bool match(const VPRecipeBase *R) {
+    if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R)) {
+      if (!detail::MatchRecipeAndOpcode<Instruction::Select,
+                                        RecipeTys...>::match(R))
+        return false;
+      if (Opcode == Instruction::And) {
+        if (!m_False().match(R->getOperand(2)))
----------------
ayalz wrote:

>> Independently, should createBlockInMask() generate logical OR's using selects as well, possibly by recipes that target IRBuilder::CreateLogicalOr(), rather than plain bitwise OR's via IRBuilder's CreateBinOp()?

> Hmm, I am not sure. Would probably warrant a separate look.

Looking at the original issue https://bugs.llvm.org/show_bug.cgi?id=48832 and its fix, it appears that masks of unreachable edges can no longer convey poison, so ORing them to produce block-in-masks should continue to be bitwise rather than logical. OTOH, logical ORs require their operands to be suitably ordered, whereas predecessors are in general unordered (unlike employing a logical AND for edge masks where the mask of the block naturally precedes the condition of its terminal branch).


>> Perhaps Not should also become a LogicalNot, generating a select %c, false, true instead of the natural xor %c, true?

> I am not entirely sure about changing the IR we generate here, the XOR variant appears to be the canonical for expected by other passes (i.e. that's what IRBuilder.CreateNot generates)

The condition of a terminal branch may be poison, so may its negating NOT, provided the edge mask uses a logical AND to avoid propagating it in case the block is unreachable (has a false block-in-mask).


Note: better eliminate dead edges and nodes from the CFG prior to applying predication, once this is done via VPlan-to-VPlan transformation. Doing so may allow to use bitwise ANDs rather than logical ones, as before.

https://github.com/llvm/llvm-project/pull/89386


More information about the llvm-commits mailing list