Home | History | Annotate | Download | only in compiler
      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/v8.h"
      6 #include "test/cctest/cctest.h"
      7 
      8 #include "src/compiler/common-operator.h"
      9 #include "src/compiler/graph-inl.h"
     10 #include "src/compiler/phi-reducer.h"
     11 
     12 using namespace v8::internal;
     13 using namespace v8::internal::compiler;
     14 
     15 class PhiReducerTester : HandleAndZoneScope {
     16  public:
     17   explicit PhiReducerTester(int num_parameters = 0)
     18       : isolate(main_isolate()),
     19         common(main_zone()),
     20         graph(main_zone()),
     21         self(graph.NewNode(common.Start(num_parameters))),
     22         dead(graph.NewNode(common.Dead())) {
     23     graph.SetStart(self);
     24   }
     25 
     26   Isolate* isolate;
     27   CommonOperatorBuilder common;
     28   Graph graph;
     29   Node* self;
     30   Node* dead;
     31 
     32   void CheckReduce(Node* expect, Node* phi) {
     33     PhiReducer reducer;
     34     Reduction reduction = reducer.Reduce(phi);
     35     if (expect == phi) {
     36       CHECK(!reduction.Changed());
     37     } else {
     38       CHECK(reduction.Changed());
     39       CHECK_EQ(expect, reduction.replacement());
     40     }
     41   }
     42 
     43   Node* Int32Constant(int32_t val) {
     44     return graph.NewNode(common.Int32Constant(val));
     45   }
     46 
     47   Node* Float64Constant(double val) {
     48     return graph.NewNode(common.Float64Constant(val));
     49   }
     50 
     51   Node* Parameter(int32_t index = 0) {
     52     return graph.NewNode(common.Parameter(index), graph.start());
     53   }
     54 
     55   Node* Phi(Node* a) {
     56     return SetSelfReferences(graph.NewNode(common.Phi(kMachAnyTagged, 1), a));
     57   }
     58 
     59   Node* Phi(Node* a, Node* b) {
     60     return SetSelfReferences(
     61         graph.NewNode(common.Phi(kMachAnyTagged, 2), a, b));
     62   }
     63 
     64   Node* Phi(Node* a, Node* b, Node* c) {
     65     return SetSelfReferences(
     66         graph.NewNode(common.Phi(kMachAnyTagged, 3), a, b, c));
     67   }
     68 
     69   Node* Phi(Node* a, Node* b, Node* c, Node* d) {
     70     return SetSelfReferences(
     71         graph.NewNode(common.Phi(kMachAnyTagged, 4), a, b, c, d));
     72   }
     73 
     74   Node* PhiWithControl(Node* a, Node* control) {
     75     return SetSelfReferences(
     76         graph.NewNode(common.Phi(kMachAnyTagged, 1), a, control));
     77   }
     78 
     79   Node* PhiWithControl(Node* a, Node* b, Node* control) {
     80     return SetSelfReferences(
     81         graph.NewNode(common.Phi(kMachAnyTagged, 2), a, b, control));
     82   }
     83 
     84   Node* SetSelfReferences(Node* node) {
     85     Node::Inputs inputs = node->inputs();
     86     for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
     87          ++iter) {
     88       Node* input = *iter;
     89       if (input == self) node->ReplaceInput(iter.index(), node);
     90     }
     91     return node;
     92   }
     93 };
     94 
     95 
     96 TEST(PhiReduce1) {
     97   PhiReducerTester R;
     98   Node* zero = R.Int32Constant(0);
     99   Node* one = R.Int32Constant(1);
    100   Node* oneish = R.Float64Constant(1.1);
    101   Node* param = R.Parameter();
    102 
    103   Node* singles[] = {zero, one, oneish, param};
    104   for (size_t i = 0; i < arraysize(singles); i++) {
    105     R.CheckReduce(singles[i], R.Phi(singles[i]));
    106   }
    107 }
    108 
    109 
    110 TEST(PhiReduce2) {
    111   PhiReducerTester R;
    112   Node* zero = R.Int32Constant(0);
    113   Node* one = R.Int32Constant(1);
    114   Node* oneish = R.Float64Constant(1.1);
    115   Node* param = R.Parameter();
    116 
    117   Node* singles[] = {zero, one, oneish, param};
    118   for (size_t i = 0; i < arraysize(singles); i++) {
    119     Node* a = singles[i];
    120     R.CheckReduce(a, R.Phi(a, a));
    121   }
    122 
    123   for (size_t i = 0; i < arraysize(singles); i++) {
    124     Node* a = singles[i];
    125     R.CheckReduce(a, R.Phi(R.self, a));
    126     R.CheckReduce(a, R.Phi(a, R.self));
    127   }
    128 
    129   for (size_t i = 1; i < arraysize(singles); i++) {
    130     Node* a = singles[i], *b = singles[0];
    131     Node* phi1 = R.Phi(b, a);
    132     R.CheckReduce(phi1, phi1);
    133 
    134     Node* phi2 = R.Phi(a, b);
    135     R.CheckReduce(phi2, phi2);
    136   }
    137 }
    138 
    139 
    140 TEST(PhiReduce3) {
    141   PhiReducerTester R;
    142   Node* zero = R.Int32Constant(0);
    143   Node* one = R.Int32Constant(1);
    144   Node* oneish = R.Float64Constant(1.1);
    145   Node* param = R.Parameter();
    146 
    147   Node* singles[] = {zero, one, oneish, param};
    148   for (size_t i = 0; i < arraysize(singles); i++) {
    149     Node* a = singles[i];
    150     R.CheckReduce(a, R.Phi(a, a, a));
    151   }
    152 
    153   for (size_t i = 0; i < arraysize(singles); i++) {
    154     Node* a = singles[i];
    155     R.CheckReduce(a, R.Phi(R.self, a, a));
    156     R.CheckReduce(a, R.Phi(a, R.self, a));
    157     R.CheckReduce(a, R.Phi(a, a, R.self));
    158   }
    159 
    160   for (size_t i = 1; i < arraysize(singles); i++) {
    161     Node* a = singles[i], *b = singles[0];
    162     Node* phi1 = R.Phi(b, a, a);
    163     R.CheckReduce(phi1, phi1);
    164 
    165     Node* phi2 = R.Phi(a, b, a);
    166     R.CheckReduce(phi2, phi2);
    167 
    168     Node* phi3 = R.Phi(a, a, b);
    169     R.CheckReduce(phi3, phi3);
    170   }
    171 }
    172 
    173 
    174 TEST(PhiReduce4) {
    175   PhiReducerTester R;
    176   Node* zero = R.Int32Constant(0);
    177   Node* one = R.Int32Constant(1);
    178   Node* oneish = R.Float64Constant(1.1);
    179   Node* param = R.Parameter();
    180 
    181   Node* singles[] = {zero, one, oneish, param};
    182   for (size_t i = 0; i < arraysize(singles); i++) {
    183     Node* a = singles[i];
    184     R.CheckReduce(a, R.Phi(a, a, a, a));
    185   }
    186 
    187   for (size_t i = 0; i < arraysize(singles); i++) {
    188     Node* a = singles[i];
    189     R.CheckReduce(a, R.Phi(R.self, a, a, a));
    190     R.CheckReduce(a, R.Phi(a, R.self, a, a));
    191     R.CheckReduce(a, R.Phi(a, a, R.self, a));
    192     R.CheckReduce(a, R.Phi(a, a, a, R.self));
    193 
    194     R.CheckReduce(a, R.Phi(R.self, R.self, a, a));
    195     R.CheckReduce(a, R.Phi(a, R.self, R.self, a));
    196     R.CheckReduce(a, R.Phi(a, a, R.self, R.self));
    197     R.CheckReduce(a, R.Phi(R.self, a, a, R.self));
    198   }
    199 
    200   for (size_t i = 1; i < arraysize(singles); i++) {
    201     Node* a = singles[i], *b = singles[0];
    202     Node* phi1 = R.Phi(b, a, a, a);
    203     R.CheckReduce(phi1, phi1);
    204 
    205     Node* phi2 = R.Phi(a, b, a, a);
    206     R.CheckReduce(phi2, phi2);
    207 
    208     Node* phi3 = R.Phi(a, a, b, a);
    209     R.CheckReduce(phi3, phi3);
    210 
    211     Node* phi4 = R.Phi(a, a, a, b);
    212     R.CheckReduce(phi4, phi4);
    213   }
    214 }
    215 
    216 
    217 TEST(PhiReduceShouldIgnoreControlNodes) {
    218   PhiReducerTester R;
    219   Node* zero = R.Int32Constant(0);
    220   Node* one = R.Int32Constant(1);
    221   Node* oneish = R.Float64Constant(1.1);
    222   Node* param = R.Parameter();
    223 
    224   Node* singles[] = {zero, one, oneish, param};
    225   for (size_t i = 0; i < arraysize(singles); ++i) {
    226     R.CheckReduce(singles[i], R.PhiWithControl(singles[i], R.dead));
    227     R.CheckReduce(singles[i], R.PhiWithControl(R.self, singles[i], R.dead));
    228     R.CheckReduce(singles[i], R.PhiWithControl(singles[i], R.self, R.dead));
    229   }
    230 }
    231