From b739a3cb651dd4af2f1a47fe1f0427fe2d9460ef Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 31 Mar 2025 21:01:28 +0100 Subject: [PATCH] [VPlan] Add m_Deferred. NFC (#133736) This copies over the implementation of m_Deferred which allows matching values that were bound in the pattern, and uses it for the (X && Y) || (X && !Y) -> X simplifcation. --- .../Transforms/Vectorize/VPlanPatternMatch.h | 18 ++++++++++++++++++ .../Transforms/Vectorize/VPlanTransforms.cpp | 5 ++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index 3b45894ebfbc..2cd23efcf3ea 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -66,6 +66,24 @@ struct specificval_ty { inline specificval_ty m_Specific(const VPValue *VPV) { return VPV; } +/// Stores a reference to the VPValue *, not the VPValue * itself, +/// thus can be used in commutative matchers. +struct deferredval_ty { + VPValue *const &Val; + + deferredval_ty(VPValue *const &V) : Val(V) {} + + bool match(VPValue *const V) const { return V == Val; } +}; + +/// Like m_Specific(), but works if the specific value to match is determined +/// as part of the same match() expression. For example: +/// m_Mul(m_VPValue(X), m_Specific(X)) is incorrect, because m_Specific() will +/// bind X before the pattern match starts. +/// m_Mul(m_VPValue(X), m_Deferred(X)) is correct, and will check against +/// whichever value m_VPValue(X) populated. +inline deferredval_ty m_Deferred(VPValue *const &V) { return V; } + /// Match a specified integer value or vector of all elements of that /// value. \p BitWidth optionally specifies the bitwidth the matched constant /// must have. If it is 0, the matched constant can have any bitwidth. diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index 3ebd844d6a5a..b0aaf7870c54 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -1053,11 +1053,10 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { // TODO: Split up into simpler, modular combines: (X && Y) || (X && Z) into X // && (Y || Z) and (X || !X) into true. This requires queuing newly created // recipes to be visited during simplification. - VPValue *X, *Y, *X1, *Y1; + VPValue *X, *Y; if (match(&R, m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)), - m_LogicalAnd(m_VPValue(X1), m_Not(m_VPValue(Y1))))) && - X == X1 && Y == Y1) { + m_LogicalAnd(m_Deferred(X), m_Not(m_Deferred(Y)))))) { R.getVPSingleValue()->replaceAllUsesWith(X); R.eraseFromParent(); return;