summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2018-04-27 21:23:20 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2018-04-27 21:23:20 +0000
commit6959b8e76f18f63aacaaf24dd74b11d733b57314 (patch)
treee14f715a8e8b9ce45a52d0203f22666e403267a2 /llvm/include
parent8ee7d01dcfd394bd9836e104b8f8fe9d9625dda1 (diff)
downloadbcm5719-llvm-6959b8e76f18f63aacaaf24dd74b11d733b57314.tar.gz
bcm5719-llvm-6959b8e76f18f63aacaaf24dd74b11d733b57314.zip
[PatternMatch] Stabilize the matching order of commutative matchers
Summary: Currently, we 1. match `LHS` matcher to the `first` operand of binary operator, 2. and then match `RHS` matcher to the `second` operand of binary operator. If that does not match, we swap the `LHS` and `RHS` matchers: 1. match `RHS` matcher to the `first` operand of binary operator, 2. and then match `LHS` matcher to the `second` operand of binary operator. This works ok. But it complicates writing of commutative matchers, where one would like to match (`m_Value()`) the value on one side, and use (`m_Specific()`) it on the other side. This is additionally complicated by the fact that `m_Specific()` stores the `Value *`, not `Value **`, so it won't work at all out of the box. The last problem is trivially solved by adding a new `m_c_Specific()` that stores the `Value **`, not `Value *`. I'm choosing to add a new matcher, not change the existing one because i guess all the current users are ok with existing behavior, and this additional pointer indirection may have performance drawbacks. Also, i'm storing pointer, not reference, because for some mysterious-to-me reason it did not work with the reference. The first one appears trivial, too. Currently, we 1. match `LHS` matcher to the `first` operand of binary operator, 2. and then match `RHS` matcher to the `second` operand of binary operator. If that does not match, we swap the ~~`LHS` and `RHS` matchers~~ **operands**: 1. match ~~`RHS`~~ **`LHS`** matcher to the ~~`first`~~ **`second`** operand of binary operator, 2. and then match ~~`LHS`~~ **`RHS`** matcher to the ~~`second`~ **`first`** operand of binary operator. Surprisingly, `$ ninja check-llvm` still passes with this. But i expect the bots will disagree.. The motivational unittest is included. I'd like to use this in D45664. Reviewers: spatel, craig.topper, arsenm, RKSimon Reviewed By: craig.topper Subscribers: xbolva00, wdng, llvm-commits Differential Revision: https://reviews.llvm.org/D45828 llvm-svn: 331085
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/IR/PatternMatch.h42
1 files changed, 33 insertions, 9 deletions
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 8b1c6b2f350..dcca931b16d 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -489,6 +489,22 @@ struct specificval_ty {
/// Match if we have a specific specified value.
inline specificval_ty m_Specific(const Value *V) { return V; }
+/// Stores a reference to the Value *, not the Value * 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; }
+};
+
+/// A commutative-friendly version of m_Specific().
+inline deferredval_ty<Value> m_Deferred(Value *const &V) { return V; }
+inline deferredval_ty<const Value> m_Deferred(const Value *const &V) {
+ return V;
+}
+
/// Match a specified floating point value or vector of all elements of
/// that value.
struct specific_fpval {
@@ -562,13 +578,15 @@ struct AnyBinaryOp_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<BinaryOperator>(V))
return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)));
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)));
return false;
}
};
@@ -588,20 +606,22 @@ struct BinaryOp_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
auto *I = cast<BinaryOperator>(V);
return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)));
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)));
}
if (auto *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode &&
((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) ||
- (Commutable && R.match(CE->getOperand(0)) &&
- L.match(CE->getOperand(1))));
+ (Commutable && L.match(CE->getOperand(1)) &&
+ R.match(CE->getOperand(0))));
return false;
}
};
@@ -926,14 +946,16 @@ struct CmpClass_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V))
if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)))) {
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)))) {
Predicate = I->getPredicate();
return true;
}
@@ -1251,6 +1273,8 @@ struct MaxMin_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
@@ -1277,7 +1301,7 @@ struct MaxMin_match {
return false;
// It does! Bind the operands.
return (L.match(LHS) && R.match(RHS)) ||
- (Commutable && R.match(LHS) && L.match(RHS));
+ (Commutable && L.match(RHS) && R.match(LHS));
}
};
OpenPOWER on IntegriCloud