LCOV - code coverage report
Current view: top level - test/unittests/compiler - control-equivalence-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 155 158 98.1 %
Date: 2019-02-19 Functions: 29 40 72.5 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/control-equivalence.h"
       6             : #include "src/bit-vector.h"
       7             : #include "src/compiler/compiler-source-position-table.h"
       8             : #include "src/compiler/graph-visualizer.h"
       9             : #include "src/compiler/node-origin-table.h"
      10             : #include "src/compiler/node-properties.h"
      11             : #include "src/zone/zone-containers.h"
      12             : #include "test/unittests/compiler/graph-unittest.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace compiler {
      17             : 
      18             : #define ASSERT_EQUIVALENCE(...)                           \
      19             :   do {                                                    \
      20             :     Node* __n[] = {__VA_ARGS__};                          \
      21             :     ASSERT_TRUE(IsEquivalenceClass(arraysize(__n), __n)); \
      22             :   } while (false)
      23             : 
      24           9 : class ControlEquivalenceTest : public GraphTest {
      25             :  public:
      26           9 :   ControlEquivalenceTest() : all_nodes_(zone()), classes_(zone()) {
      27           9 :     Store(graph()->start());
      28           9 :   }
      29             : 
      30             :  protected:
      31           9 :   void ComputeEquivalence(Node* node) {
      32           9 :     graph()->SetEnd(graph()->NewNode(common()->End(1), node));
      33           9 :     if (FLAG_trace_turbo) {
      34           0 :       SourcePositionTable table(graph());
      35           0 :       NodeOriginTable table2(graph());
      36           0 :       StdoutStream{} << AsJSON(*graph(), &table, &table2);
      37             :     }
      38           9 :     ControlEquivalence equivalence(zone(), graph());
      39           9 :     equivalence.Run(node);
      40          77 :     classes_.resize(graph()->NodeCount());
      41          77 :     for (Node* node : all_nodes_) {
      42         118 :       classes_[node->id()] = equivalence.ClassOf(node);
      43             :     }
      44           9 :   }
      45             : 
      46          37 :   bool IsEquivalenceClass(size_t length, Node** nodes) {
      47          74 :     BitVector in_class(static_cast<int>(graph()->NodeCount()), zone());
      48         459 :     size_t expected_class = classes_[nodes[0]->id()];
      49          96 :     for (size_t i = 0; i < length; ++i) {
      50         118 :       in_class.Add(nodes[i]->id());
      51             :     }
      52         422 :     for (Node* node : all_nodes_) {
      53         696 :       if (in_class.Contains(node->id())) {
      54         118 :         if (classes_[node->id()] != expected_class) return false;
      55             :       } else {
      56         578 :         if (classes_[node->id()] == expected_class) return false;
      57             :       }
      58             :     }
      59             :     return true;
      60             :   }
      61             : 
      62          12 :   Node* Value() { return NumberConstant(0.0); }
      63             : 
      64          12 :   Node* Branch(Node* control) {
      65          24 :     return Store(graph()->NewNode(common()->Branch(), Value(), control));
      66             :   }
      67             : 
      68          12 :   Node* IfTrue(Node* control) {
      69          24 :     return Store(graph()->NewNode(common()->IfTrue(), control));
      70             :   }
      71             : 
      72          12 :   Node* IfFalse(Node* control) {
      73          24 :     return Store(graph()->NewNode(common()->IfFalse(), control));
      74             :   }
      75             : 
      76           1 :   Node* Merge1(Node* control) {
      77           2 :     return Store(graph()->NewNode(common()->Merge(1), control));
      78             :   }
      79             : 
      80          10 :   Node* Merge2(Node* control1, Node* control2) {
      81          20 :     return Store(graph()->NewNode(common()->Merge(2), control1, control2));
      82             :   }
      83             : 
      84           3 :   Node* Loop2(Node* control) {
      85           6 :     return Store(graph()->NewNode(common()->Loop(2), control, control));
      86             :   }
      87             : 
      88             :   Node* End(Node* control) {
      89             :     return Store(graph()->NewNode(common()->End(1), control));
      90             :   }
      91             : 
      92             :  private:
      93             :   Node* Store(Node* node) {
      94          59 :     all_nodes_.push_back(node);
      95          50 :     return node;
      96             :   }
      97             : 
      98             :   ZoneVector<Node*> all_nodes_;
      99             :   ZoneVector<size_t> classes_;
     100             : };
     101             : 
     102             : 
     103             : // -----------------------------------------------------------------------------
     104             : // Test cases.
     105             : 
     106             : 
     107       15189 : TEST_F(ControlEquivalenceTest, Empty1) {
     108           1 :   Node* start = graph()->start();
     109           1 :   ComputeEquivalence(start);
     110             : 
     111           3 :   ASSERT_EQUIVALENCE(start);
     112             : }
     113             : 
     114             : 
     115       15189 : TEST_F(ControlEquivalenceTest, Empty2) {
     116           1 :   Node* start = graph()->start();
     117           1 :   Node* merge1 = Merge1(start);
     118           1 :   ComputeEquivalence(merge1);
     119             : 
     120           3 :   ASSERT_EQUIVALENCE(start, merge1);
     121             : }
     122             : 
     123             : 
     124       15189 : TEST_F(ControlEquivalenceTest, Diamond1) {
     125           1 :   Node* start = graph()->start();
     126           1 :   Node* b = Branch(start);
     127           1 :   Node* t = IfTrue(b);
     128           1 :   Node* f = IfFalse(b);
     129           1 :   Node* m = Merge2(t, f);
     130           1 :   ComputeEquivalence(m);
     131             : 
     132           2 :   ASSERT_EQUIVALENCE(b, m, start);
     133           2 :   ASSERT_EQUIVALENCE(f);
     134           2 :   ASSERT_EQUIVALENCE(t);
     135             : }
     136             : 
     137             : 
     138       15189 : TEST_F(ControlEquivalenceTest, Diamond2) {
     139           1 :   Node* start = graph()->start();
     140           1 :   Node* b1 = Branch(start);
     141           1 :   Node* t1 = IfTrue(b1);
     142           1 :   Node* f1 = IfFalse(b1);
     143           1 :   Node* b2 = Branch(f1);
     144           1 :   Node* t2 = IfTrue(b2);
     145           1 :   Node* f2 = IfFalse(b2);
     146           1 :   Node* m2 = Merge2(t2, f2);
     147           1 :   Node* m1 = Merge2(t1, m2);
     148           1 :   ComputeEquivalence(m1);
     149             : 
     150           2 :   ASSERT_EQUIVALENCE(b1, m1, start);
     151           2 :   ASSERT_EQUIVALENCE(t1);
     152           2 :   ASSERT_EQUIVALENCE(f1, b2, m2);
     153           2 :   ASSERT_EQUIVALENCE(t2);
     154           2 :   ASSERT_EQUIVALENCE(f2);
     155             : }
     156             : 
     157             : 
     158       15189 : TEST_F(ControlEquivalenceTest, Diamond3) {
     159           1 :   Node* start = graph()->start();
     160           1 :   Node* b1 = Branch(start);
     161           1 :   Node* t1 = IfTrue(b1);
     162           1 :   Node* f1 = IfFalse(b1);
     163           1 :   Node* m1 = Merge2(t1, f1);
     164           1 :   Node* b2 = Branch(m1);
     165           1 :   Node* t2 = IfTrue(b2);
     166           1 :   Node* f2 = IfFalse(b2);
     167           1 :   Node* m2 = Merge2(t2, f2);
     168           1 :   ComputeEquivalence(m2);
     169             : 
     170           2 :   ASSERT_EQUIVALENCE(b1, m1, b2, m2, start);
     171           2 :   ASSERT_EQUIVALENCE(t1);
     172           2 :   ASSERT_EQUIVALENCE(f1);
     173           2 :   ASSERT_EQUIVALENCE(t2);
     174           2 :   ASSERT_EQUIVALENCE(f2);
     175             : }
     176             : 
     177             : 
     178       15189 : TEST_F(ControlEquivalenceTest, Switch1) {
     179           1 :   Node* start = graph()->start();
     180           1 :   Node* b1 = Branch(start);
     181           1 :   Node* t1 = IfTrue(b1);
     182           1 :   Node* f1 = IfFalse(b1);
     183           1 :   Node* b2 = Branch(f1);
     184           1 :   Node* t2 = IfTrue(b2);
     185           1 :   Node* f2 = IfFalse(b2);
     186           1 :   Node* b3 = Branch(f2);
     187           1 :   Node* t3 = IfTrue(b3);
     188           1 :   Node* f3 = IfFalse(b3);
     189           1 :   Node* m1 = Merge2(t1, t2);
     190           1 :   Node* m2 = Merge2(m1, t3);
     191           1 :   Node* m3 = Merge2(m2, f3);
     192           1 :   ComputeEquivalence(m3);
     193             : 
     194           2 :   ASSERT_EQUIVALENCE(b1, m3, start);
     195           2 :   ASSERT_EQUIVALENCE(t1);
     196           2 :   ASSERT_EQUIVALENCE(f1, b2);
     197           2 :   ASSERT_EQUIVALENCE(t2);
     198           2 :   ASSERT_EQUIVALENCE(f2, b3);
     199           2 :   ASSERT_EQUIVALENCE(t3);
     200           2 :   ASSERT_EQUIVALENCE(f3);
     201           2 :   ASSERT_EQUIVALENCE(m1);
     202           2 :   ASSERT_EQUIVALENCE(m2);
     203             : }
     204             : 
     205             : 
     206       15189 : TEST_F(ControlEquivalenceTest, Loop1) {
     207           1 :   Node* start = graph()->start();
     208           1 :   Node* l = Loop2(start);
     209           1 :   l->ReplaceInput(1, l);
     210           1 :   ComputeEquivalence(l);
     211             : 
     212           2 :   ASSERT_EQUIVALENCE(start);
     213           2 :   ASSERT_EQUIVALENCE(l);
     214             : }
     215             : 
     216             : 
     217       15189 : TEST_F(ControlEquivalenceTest, Loop2) {
     218           1 :   Node* start = graph()->start();
     219           1 :   Node* l = Loop2(start);
     220           1 :   Node* b = Branch(l);
     221           1 :   Node* t = IfTrue(b);
     222           1 :   Node* f = IfFalse(b);
     223           1 :   l->ReplaceInput(1, t);
     224           1 :   ComputeEquivalence(f);
     225             : 
     226           2 :   ASSERT_EQUIVALENCE(f, start);
     227           2 :   ASSERT_EQUIVALENCE(t);
     228           2 :   ASSERT_EQUIVALENCE(l, b);
     229             : }
     230             : 
     231             : 
     232       15189 : TEST_F(ControlEquivalenceTest, Irreducible) {
     233           1 :   Node* start = graph()->start();
     234           1 :   Node* b1 = Branch(start);
     235           1 :   Node* t1 = IfTrue(b1);
     236           1 :   Node* f1 = IfFalse(b1);
     237           1 :   Node* lp = Loop2(f1);
     238           1 :   Node* m1 = Merge2(t1, lp);
     239           1 :   Node* b2 = Branch(m1);
     240           1 :   Node* t2 = IfTrue(b2);
     241           1 :   Node* f2 = IfFalse(b2);
     242           1 :   Node* m2 = Merge2(t2, f2);
     243           1 :   Node* b3 = Branch(m2);
     244           1 :   Node* t3 = IfTrue(b3);
     245           1 :   Node* f3 = IfFalse(b3);
     246           1 :   lp->ReplaceInput(1, f3);
     247           1 :   ComputeEquivalence(t3);
     248             : 
     249           2 :   ASSERT_EQUIVALENCE(b1, t3, start);
     250           2 :   ASSERT_EQUIVALENCE(t1);
     251           2 :   ASSERT_EQUIVALENCE(f1);
     252           2 :   ASSERT_EQUIVALENCE(m1, b2, m2, b3);
     253           2 :   ASSERT_EQUIVALENCE(t2);
     254           2 :   ASSERT_EQUIVALENCE(f2);
     255           2 :   ASSERT_EQUIVALENCE(f3);
     256           2 :   ASSERT_EQUIVALENCE(lp);
     257             : }
     258             : 
     259             : 
     260             : }  // namespace compiler
     261             : }  // namespace internal
     262        9111 : }  // namespace v8

Generated by: LCOV version 1.10