[llvm] [VPlan] Introduce m_c_Logical(And|Or) (NFC) (PR #180048)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 06:00:28 PST 2026
https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/180048
>From c9fe86d342a406801a2aea2cbb4f723e50843f51 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 5 Feb 2026 21:41:41 +0000
Subject: [PATCH] [VPlan] Introduce m_c_Logical(And|Or)
---
.../Transforms/Vectorize/VPlanPatternMatch.h | 48 +++++++++++++++++--
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 5 +-
.../Transforms/Vectorize/VPlanTransforms.cpp | 8 ++--
3 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index c0b736de1bc51..9dc14b635f3eb 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -364,12 +364,23 @@ template <unsigned Opcode, typename... OpTys>
using VPInstruction_match = Recipe_match<std::tuple<OpTys...>, Opcode,
/*Commutative*/ false, VPInstruction>;
+template <unsigned Opcode, typename... OpTys>
+using VPInstruction_commutative_match =
+ Recipe_match<std::tuple<OpTys...>, Opcode,
+ /*Commutative*/ true, VPInstruction>;
+
template <unsigned Opcode, typename... OpTys>
inline VPInstruction_match<Opcode, OpTys...>
m_VPInstruction(const OpTys &...Ops) {
return VPInstruction_match<Opcode, OpTys...>(Ops...);
}
+template <unsigned Opcode, typename Op0_t, typename Op1_t>
+inline VPInstruction_commutative_match<Opcode, Op0_t, Op1_t>
+m_c_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) {
+ return VPInstruction_commutative_match<Opcode, Op0_t, Op1_t>(Op0, Op1);
+}
+
/// BuildVector is matches only its opcode, w/o matching its operands as the
/// number of operands is not fixed.
inline VPInstruction_match<VPInstruction::BuildVector> m_BuildVector() {
@@ -791,14 +802,27 @@ m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
}
template <typename Op0_t>
-inline match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
- AllRecipe_commutative_match<
- Instruction::Xor, int_pred_ty<is_all_ones>, Op0_t>>
-m_Not(const Op0_t &Op0) {
+using Not_match =
+ match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
+ AllRecipe_commutative_match<
+ Instruction::Xor, int_pred_ty<is_all_ones>, Op0_t>>;
+
+template <typename Op0_t> inline Not_match<Op0_t> m_Not(const Op0_t &Op0) {
return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
m_c_Binary<Instruction::Xor>(m_AllOnes(), Op0));
}
+template <typename Op0_t, typename Op1_t, typename Op2_t>
+using Select_commutative_match = match_combine_or<
+ AllRecipe_match<Instruction::Select, Op0_t, Op1_t, Op2_t>,
+ AllRecipe_match<Instruction::Select, Not_match<Op0_t>, Op2_t, Op1_t>>;
+
+template <typename Op0_t, typename Op1_t, typename Op2_t>
+inline Select_commutative_match<Op0_t, Op1_t, Op2_t>
+m_c_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
+ return m_CombineOr(m_Select(Op0, Op1, Op2), m_Select(m_Not(Op0), Op2, Op1));
+}
+
template <typename Op0_t, typename Op1_t>
inline match_combine_or<
VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
@@ -809,12 +833,28 @@ m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
m_Select(Op0, Op1, m_False()));
}
+template <typename Op0_t, typename Op1_t>
+inline match_combine_or<
+ VPInstruction_commutative_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
+ Select_commutative_match<Op0_t, Op1_t, specific_intval<1>>>
+m_c_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
+ return m_CombineOr(
+ m_c_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
+ m_c_Select(Op0, Op1, m_False()));
+}
+
template <typename Op0_t, typename Op1_t>
inline AllRecipe_match<Instruction::Select, Op0_t, specific_intval<1>, Op1_t>
m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
return m_Select(Op0, m_True(), Op1);
}
+template <typename Op0_t, typename Op1_t>
+inline Select_commutative_match<Op0_t, specific_intval<1>, Op1_t>
+m_c_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
+ return m_c_Select(Op0, m_True(), Op1);
+}
+
template <typename Op0_t, typename Op1_t, typename Op2_t>
using VPScalarIVSteps_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0,
false, VPScalarIVStepsRecipe>;
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 5708abfaf6f5b..89a270d1219e7 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1064,8 +1064,9 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
VPValue *Op0, *Op1;
bool IsLogicalAnd =
- match(this, m_LogicalAnd(m_VPValue(Op0), m_VPValue(Op1)));
- bool IsLogicalOr = match(this, m_LogicalOr(m_VPValue(Op0), m_VPValue(Op1)));
+ match(this, m_c_LogicalAnd(m_VPValue(Op0), m_VPValue(Op1)));
+ bool IsLogicalOr =
+ match(this, m_c_LogicalOr(m_VPValue(Op0), m_VPValue(Op1)));
// Also match the inverted forms:
// select x, false, y --> !x & y (still AND)
// select x, y, true --> !x | y (still OR)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index a99641c472b9f..60ec4408da950 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1295,11 +1295,11 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
return Def->replaceAllUsesWith(X);
// x && false -> false
- if (match(Def, m_LogicalAnd(m_VPValue(X), m_False())))
- return Def->replaceAllUsesWith(Def->getOperand(1));
+ if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_False())))
+ return Def->replaceAllUsesWith(Plan->getFalse());
- // true && x -> x
- if (match(Def, m_LogicalAnd(m_True(), m_VPValue(X))))
+ // x && true -> x
+ if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_True())))
return Def->replaceAllUsesWith(X);
// (x && y) | (x && z) -> x && (y | z)
More information about the llvm-commits
mailing list