llvm.org GIT mirror llvm / a9bc2db
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331085 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Lebedev 1 year, 5 months ago
7 changed file(s) with 109 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
488488 /// Match if we have a specific specified value.
489489 inline specificval_ty m_Specific(const Value *V) { return V; }
490490
491 /// Stores a reference to the Value *, not the Value * itself,
492 /// thus can be used in commutative matchers.
493 template struct deferredval_ty {
494 Class *const &Val;
495
496 deferredval_ty(Class *const &V) : Val(V) {}
497
498 template bool match(ITy *const V) { return V == Val; }
499 };
500
501 /// A commutative-friendly version of m_Specific().
502 inline deferredval_ty m_Deferred(Value *const &V) { return V; }
503 inline deferredval_ty m_Deferred(const Value *const &V) {
504 return V;
505 }
506
491507 /// Match a specified floating point value or vector of all elements of
492508 /// that value.
493509 struct specific_fpval {
561577 LHS_t L;
562578 RHS_t R;
563579
580 // The evaluation order is always stable, regardless of Commutability.
581 // The LHS is always matched first.
564582 AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
565583
566584 template bool match(OpTy *V) {
567585 if (auto *I = dyn_cast(V))
568586 return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
569 (Commutable && R.match(I->getOperand(0)) &&
570 L.match(I->getOperand(1)));
587 (Commutable && L.match(I->getOperand(1)) &&
588 R.match(I->getOperand(0)));
571589 return false;
572590 }
573591 };
587605 LHS_t L;
588606 RHS_t R;
589607
608 // The evaluation order is always stable, regardless of Commutability.
609 // The LHS is always matched first.
590610 BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
591611
592612 template bool match(OpTy *V) {
593613 if (V->getValueID() == Value::InstructionVal + Opcode) {
594614 auto *I = cast(V);
595615 return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
596 (Commutable && R.match(I->getOperand(0)) &&
597 L.match(I->getOperand(1)));
616 (Commutable && L.match(I->getOperand(1)) &&
617 R.match(I->getOperand(0)));
598618 }
599619 if (auto *CE = dyn_cast(V))
600620 return CE->getOpcode() == Opcode &&
601621 ((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) ||
602 (Commutable && R.match(CE->getOperand(0)) &&
603 L.match(CE->getOperand(1))));
622 (Commutable && L.match(CE->getOperand(1)) &&
623 R.match(CE->getOperand(0))));
604624 return false;
605625 }
606626 };
925945 LHS_t L;
926946 RHS_t R;
927947
948 // The evaluation order is always stable, regardless of Commutability.
949 // The LHS is always matched first.
928950 CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
929951 : Predicate(Pred), L(LHS), R(RHS) {}
930952
931953 template bool match(OpTy *V) {
932954 if (auto *I = dyn_cast(V))
933955 if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
934 (Commutable && R.match(I->getOperand(0)) &&
935 L.match(I->getOperand(1)))) {
956 (Commutable && L.match(I->getOperand(1)) &&
957 R.match(I->getOperand(0)))) {
936958 Predicate = I->getPredicate();
937959 return true;
938960 }
12501272 LHS_t L;
12511273 RHS_t R;
12521274
1275 // The evaluation order is always stable, regardless of Commutability.
1276 // The LHS is always matched first.
12531277 MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
12541278
12551279 template bool match(OpTy *V) {
12761300 return false;
12771301 // It does! Bind the operands.
12781302 return (L.match(LHS) && R.match(RHS)) ||
1279 (Commutable && R.match(LHS) && L.match(RHS));
1303 (Commutable && L.match(RHS) && R.match(LHS));
12801304 }
12811305 };
12821306
981981 // matching the form add(x, add(x, y)) where y is odd.
982982 // TODO: This could be generalized to clearing any bit set in y where the
983983 // following bit is known to be unset in y.
984 Value *Y = nullptr;
984 Value *X = nullptr, *Y = nullptr;
985985 if (!Known.Zero[0] && !Known.One[0] &&
986 (match(I->getOperand(0), m_Add(m_Specific(I->getOperand(1)),
987 m_Value(Y))) ||
988 match(I->getOperand(1), m_Add(m_Specific(I->getOperand(0)),
989 m_Value(Y))))) {
986 match(I, m_c_BinOp(m_Value(X), m_Add(m_Deferred(X), m_Value(Y))))) {
990987 Known2.resetAll();
991988 computeKnownBits(Y, Known2, Depth + 1, Q);
992989 if (Known2.countMinTrailingOnes() > 0)
13621362 }
13631363
13641364 // (add (xor A, B) (and A, B)) --> (or A, B)
1365 if (match(LHS, m_Xor(m_Value(A), m_Value(B))) &&
1366 match(RHS, m_c_And(m_Specific(A), m_Specific(B))))
1365 // (add (and A, B) (xor A, B)) --> (or A, B)
1366 if (match(&I, m_c_BinOp(m_Xor(m_Value(A), m_Value(B)),
1367 m_c_And(m_Deferred(A), m_Deferred(B)))))
13671368 return BinaryOperator::CreateOr(A, B);
13681369
1369 // (add (and A, B) (xor A, B)) --> (or A, B)
1370 if (match(RHS, m_Xor(m_Value(A), m_Value(B))) &&
1371 match(LHS, m_c_And(m_Specific(A), m_Specific(B))))
1372 return BinaryOperator::CreateOr(A, B);
1373
13741370 // (add (or A, B) (and A, B)) --> (add A, B)
1375 if (match(LHS, m_Or(m_Value(A), m_Value(B))) &&
1376 match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) {
1377 I.setOperand(0, A);
1378 I.setOperand(1, B);
1379 return &I;
1380 }
1381
13821371 // (add (and A, B) (or A, B)) --> (add A, B)
1383 if (match(RHS, m_Or(m_Value(A), m_Value(B))) &&
1384 match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) {
1372 if (match(&I, m_c_BinOp(m_Or(m_Value(A), m_Value(B)),
1373 m_c_And(m_Deferred(A), m_Deferred(B))))) {
13851374 I.setOperand(0, A);
13861375 I.setOperand(1, B);
13871376 return &I;
12871287 // Operand complexity canonicalization guarantees that the 'or' is Op0.
12881288 // (A | B) & ~(A & B) --> A ^ B
12891289 // (A | B) & ~(B & A) --> A ^ B
1290 if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
1291 match(Op1, m_Not(m_c_And(m_Specific(A), m_Specific(B)))))
1290 if (match(&I, m_BinOp(m_Or(m_Value(A), m_Value(B)),
1291 m_Not(m_c_And(m_Deferred(A), m_Deferred(B))))))
12921292 return BinaryOperator::CreateXor(A, B);
12931293
12941294 // (A | ~B) & (~A | B) --> ~(A ^ B)
12961296 // (~B | A) & (~A | B) --> ~(A ^ B)
12971297 // (~B | A) & (B | ~A) --> ~(A ^ B)
12981298 if (Op0->hasOneUse() || Op1->hasOneUse())
1299 if (match(Op0, m_c_Or(m_Value(A), m_Not(m_Value(B)))) &&
1300 match(Op1, m_c_Or(m_Not(m_Specific(A)), m_Specific(B))))
1299 if (match(&I, m_BinOp(m_c_Or(m_Value(A), m_Not(m_Value(B))),
1300 m_c_Or(m_Not(m_Deferred(A)), m_Deferred(B)))))
13011301 return BinaryOperator::CreateNot(Builder.CreateXor(A, B));
13021302
13031303 return nullptr;
22932293 // (A & B) ^ (B | A) -> A ^ B
22942294 // (A | B) ^ (A & B) -> A ^ B
22952295 // (A | B) ^ (B & A) -> A ^ B
2296 if ((match(Op0, m_And(m_Value(A), m_Value(B))) &&
2297 match(Op1, m_c_Or(m_Specific(A), m_Specific(B)))) ||
2298 (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
2299 match(Op1, m_c_And(m_Specific(A), m_Specific(B))))) {
2296 if (match(&I, m_c_Xor(m_And(m_Value(A), m_Value(B)),
2297 m_c_Or(m_Deferred(A), m_Deferred(B))))) {
23002298 I.setOperand(0, A);
23012299 I.setOperand(1, B);
23022300 return &I;
23062304 // (~B | A) ^ (~A | B) -> A ^ B
23072305 // (~A | B) ^ (A | ~B) -> A ^ B
23082306 // (B | ~A) ^ (A | ~B) -> A ^ B
2309 if ((match(Op0, m_Or(m_Value(A), m_Not(m_Value(B)))) &&
2310 match(Op1, m_c_Or(m_Not(m_Specific(A)), m_Specific(B)))) ||
2311 (match(Op0, m_Or(m_Not(m_Value(A)), m_Value(B))) &&
2312 match(Op1, m_c_Or(m_Specific(A), m_Not(m_Specific(B)))))) {
2307 if (match(&I, m_Xor(m_c_Or(m_Value(A), m_Not(m_Value(B))),
2308 m_c_Or(m_Not(m_Deferred(A)), m_Deferred(B))))) {
23132309 I.setOperand(0, A);
23142310 I.setOperand(1, B);
23152311 return &I;
23192315 // (~B & A) ^ (~A & B) -> A ^ B
23202316 // (~A & B) ^ (A & ~B) -> A ^ B
23212317 // (B & ~A) ^ (A & ~B) -> A ^ B
2322 if ((match(Op0, m_And(m_Value(A), m_Not(m_Value(B)))) &&
2323 match(Op1, m_c_And(m_Not(m_Specific(A)), m_Specific(B)))) ||
2324 (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) &&
2325 match(Op1, m_c_And(m_Specific(A), m_Not(m_Specific(B)))))) {
2318 if (match(&I, m_Xor(m_c_And(m_Value(A), m_Not(m_Value(B))),
2319 m_c_And(m_Not(m_Deferred(A)), m_Deferred(B))))) {
23262320 I.setOperand(0, A);
23272321 I.setOperand(1, B);
23282322 return &I;
332332
333333 define i32 @xor_to_xor4(i32 %a, i32 %b) {
334334 ; CHECK-LABEL: @xor_to_xor4(
335 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
335 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
336336 ; CHECK-NEXT: ret i32 [[XOR]]
337337 ;
338338 %or = or i32 %a, %b
388388 ; CHECK-LABEL: @xor_to_xor7(
389389 ; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32
390390 ; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32
391 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
391 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]]
392392 ; CHECK-NEXT: ret i32 [[XOR]]
393393 ;
394394 %a = fptosi float %fa to i32
407407 ; CHECK-LABEL: @xor_to_xor8(
408408 ; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32
409409 ; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32
410 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
410 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]]
411411 ; CHECK-NEXT: ret i32 [[XOR]]
412412 ;
413413 %a = fptosi float %fa to i32
464464 ; CHECK-LABEL: @xor_to_xor11(
465465 ; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32
466466 ; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32
467 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
467 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]]
468468 ; CHECK-NEXT: ret i32 [[XOR]]
469469 ;
470470 %a = fptosi float %fa to i32
483483 ; CHECK-LABEL: @xor_to_xor12(
484484 ; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32
485485 ; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32
486 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
486 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]]
487487 ; CHECK-NEXT: ret i32 [[XOR]]
488488 ;
489489 %a = fptosi float %fa to i32
187187 ; ((x | ~y) ^ (~x | y)) -> x ^ y
188188 define i32 @test14(i32 %x, i32 %y) {
189189 ; CHECK-LABEL: @test14(
190 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
190 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
191191 ; CHECK-NEXT: ret i32 [[XOR]]
192192 ;
193193 %noty = xor i32 %y, -1
200200
201201 define i32 @test14_commuted(i32 %x, i32 %y) {
202202 ; CHECK-LABEL: @test14_commuted(
203 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
203 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
204204 ; CHECK-NEXT: ret i32 [[XOR]]
205205 ;
206206 %noty = xor i32 %y, -1
214214 ; ((x & ~y) ^ (~x & y)) -> x ^ y
215215 define i32 @test15(i32 %x, i32 %y) {
216216 ; CHECK-LABEL: @test15(
217 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
217 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
218218 ; CHECK-NEXT: ret i32 [[XOR]]
219219 ;
220220 %noty = xor i32 %y, -1
227227
228228 define i32 @test15_commuted(i32 %x, i32 %y) {
229229 ; CHECK-LABEL: @test15_commuted(
230 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
230 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
231231 ; CHECK-NEXT: ret i32 [[XOR]]
232232 ;
233233 %noty = xor i32 %y, -1
6262
6363 EXPECT_FALSE(m_OneUse(m_Value()).match(Two));
6464 EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf));
65 }
66
67 TEST_F(PatternMatchTest, CommutativeDeferredValue) {
68 Value *X = IRB.getInt32(1);
69 Value *Y = IRB.getInt32(2);
70
71 {
72 Value *tX = X;
73 EXPECT_TRUE(match(X, m_Deferred(tX)));
74 EXPECT_FALSE(match(Y, m_Deferred(tX)));
75 }
76 {
77 const Value *tX = X;
78 EXPECT_TRUE(match(X, m_Deferred(tX)));
79 EXPECT_FALSE(match(Y, m_Deferred(tX)));
80 }
81 {
82 Value *const tX = X;
83 EXPECT_TRUE(match(X, m_Deferred(tX)));
84 EXPECT_FALSE(match(Y, m_Deferred(tX)));
85 }
86 {
87 const Value *const tX = X;
88 EXPECT_TRUE(match(X, m_Deferred(tX)));
89 EXPECT_FALSE(match(Y, m_Deferred(tX)));
90 }
91
92 {
93 Value *tX = nullptr;
94 EXPECT_TRUE(match(IRB.CreateAnd(X, X), m_And(m_Value(tX), m_Deferred(tX))));
95 EXPECT_EQ(tX, X);
96 }
97 {
98 Value *tX = nullptr;
99 EXPECT_FALSE(
100 match(IRB.CreateAnd(X, Y), m_c_And(m_Value(tX), m_Deferred(tX))));
101 }
102
103 auto checkMatch = [X, Y](Value *Pattern) {
104 Value *tX = nullptr, *tY = nullptr;
105 EXPECT_TRUE(match(
106 Pattern, m_c_And(m_Value(tX), m_c_And(m_Deferred(tX), m_Value(tY)))));
107 EXPECT_EQ(tX, X);
108 EXPECT_EQ(tY, Y);
109 };
110
111 checkMatch(IRB.CreateAnd(X, IRB.CreateAnd(X, Y)));
112 checkMatch(IRB.CreateAnd(X, IRB.CreateAnd(Y, X)));
113 checkMatch(IRB.CreateAnd(IRB.CreateAnd(X, Y), X));
114 checkMatch(IRB.CreateAnd(IRB.CreateAnd(Y, X), X));
65115 }
66116
67117 TEST_F(PatternMatchTest, FloatingPointOrderedMin) {