-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[VPlan] Add m_Deferred. NFC #133736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[VPlan] Add m_Deferred. NFC #133736
Conversation
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.
@llvm/pr-subscribers-vectorizers @llvm/pr-subscribers-llvm-transforms Author: Luke Lau (lukel97) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/133736.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index 3a727866a2875..24d1a16d617cf 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -66,6 +66,27 @@ 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.
+template <typename Class> struct deferredval_ty {
+ Class *const &Val;
+
+ deferredval_ty(Class *const &V) : Val(V) {}
+
+ template <typename ITy> bool match(ITy *const V) { 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<VPValue> m_Deferred(VPValue *const &V) { return V; }
+inline deferredval_ty<const VPValue> m_Deferred(const 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 a2e6182cf16e2..372cc5d88ce6c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1049,11 +1049,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;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits; looks good otherwise.
|
||
deferredval_ty(Class *const &V) : Val(V) {} | ||
|
||
template <typename ITy> bool match(ITy *const V) { return V == Val; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mark match function const?
/// Stores a reference to the VPValue *, not the VPValue * itself, | ||
/// thus can be used in commutative matchers. | ||
template <typename Class> struct deferredval_ty { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to match over anything else other than VPValue? Doesn't the name deferredval_ty imply that we're matching a value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The template is to allow matching both VPValue and const VPValue, which ties into your review comment below. If we don't think we'll ever need to match a const VPValue I can remove that overload and untemplate this struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, we don't have a const matcher for m_VPValue(), and considering that m_Deferred() is supposed to be used along with m_VPValue(), I think it's safe to remove the const variant, and un-templatize this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about there not being a const m_VPValue(), I've untemplated it now
/// 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<VPValue> m_Deferred(VPValue *const &V) { return V; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this variant is unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
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.