constant-folding-reducer-unittest.cc 9.49 KB
Newer Older
1 2 3 4 5
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/constant-folding-reducer.h"
6
#include "src/codegen/code-factory.h"
7
#include "src/compiler/access-builder.h"
8
#include "src/compiler/compilation-dependencies.h"
9 10 11 12 13
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
14
#include "src/execution/isolate-inl.h"
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"

using testing::IsNaN;

namespace v8 {
namespace internal {
namespace compiler {
namespace constant_folding_reducer_unittest {

namespace {

const double kFloat64Values[] = {
    -V8_INFINITY,  -4.23878e+275, -5.82632e+265, -6.60355e+220,
    -6.26172e+212, -2.56222e+211, -4.82408e+201, -1.84106e+157,
    -1.63662e+127, -1.55772e+100, -1.67813e+72,  -2.3382e+55,
    -3.179e+30,    -1.441e+09,    -1.0647e+09,   -7.99361e+08,
    -5.77375e+08,  -2.20984e+08,  -32757,        -13171,
    -9970,         -3984,         -107,          -105,
    -92,           -77,           -61,           -0.000208163,
    -1.86685e-06,  -1.17296e-10,  -9.26358e-11,  -5.08004e-60,
    -1.74753e-65,  -1.06561e-71,  -5.67879e-79,  -5.78459e-130,
    -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
    -4.40497e-267, -2.19666e-273, -4.9998e-276,  -5.59821e-278,
    -2.03855e-282, -5.99335e-283, -7.17554e-284, -3.11744e-309,
    -0.0,          0.0,           2.22507e-308,  1.30127e-270,
    7.62898e-260,  4.00313e-249,  3.16829e-233,  1.85244e-228,
    2.03544e-129,  1.35126e-110,  1.01182e-106,  5.26333e-94,
    1.35292e-90,   2.85394e-83,   1.78323e-77,   5.4967e-57,
    1.03207e-25,   4.57401e-25,   1.58738e-05,   2,
    125,           2310,          9636,          14802,
    17168,         28945,         29305,         4.81336e+07,
    1.41207e+08,   4.65962e+08,   1.40499e+09,   2.12648e+09,
    8.80006e+30,   1.4446e+45,    1.12164e+54,   2.48188e+89,
    6.71121e+102,  3.074e+112,    4.9699e+152,   5.58383e+166,
    4.30654e+172,  7.08824e+185,  9.6586e+214,   2.028e+223,
    6.63277e+243,  1.56192e+261,  1.23202e+269,  5.72883e+289,
    8.5798e+290,   1.40256e+294,  1.79769e+308,  V8_INFINITY};

const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0,  -42.0,
                                 -1.0,         0.0,     1.0,      42.0,
                                 1000.0,       INT_MAX, UINT_MAX, V8_INFINITY};

}  // namespace

class ConstantFoldingReducerTest : public TypedGraphTest {
 public:
  ConstantFoldingReducerTest()
65
      : TypedGraphTest(3),
66
        broker_(isolate(), zone()),
67
        simplified_(zone()),
68
        deps_(&broker_, zone()) {}
69
  ~ConstantFoldingReducerTest() override = default;
70 71 72 73 74 75 76

 protected:
  Reduction Reduce(Node* node) {
    MachineOperatorBuilder machine(zone());
    JSOperatorBuilder javascript(zone());
    JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
                    &machine);
77
    GraphReducer graph_reducer(zone(), graph(), tick_counter(), broker());
78
    ConstantFoldingReducer reducer(&graph_reducer, &jsgraph, broker());
79 80 81
    return reducer.Reduce(node);
  }

82 83 84 85 86 87
  Node* UseValue(Node* node) {
    Node* start = graph()->NewNode(common()->Start(1));
    Node* zero = graph()->NewNode(common()->NumberConstant(0));
    return graph()->NewNode(common()->Return(), zero, node, start, start);
  }

88
  SimplifiedOperatorBuilder* simplified() { return &simplified_; }
89
  JSHeapBroker* broker() { return &broker_; }
90 91

 private:
92
  JSHeapBroker broker_;
93 94 95 96 97 98
  SimplifiedOperatorBuilder simplified_;
  CompilationDependencies deps_;
};

TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
  {
99 100 101 102
    Node* node = Parameter(
        Type::Constant(broker(), factory()->minus_zero_value(), zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
103
    ASSERT_TRUE(r.Changed());
104
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0));
105 106
  }
  {
107 108 109
    Node* node = Parameter(Type::MinusZero());
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
110
    ASSERT_TRUE(r.Changed());
111
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0));
112 113
  }
  {
114
    Node* node = Parameter(Type::Union(
115
        Type::MinusZero(),
116 117 118
        Type::Constant(broker(), factory()->NewNumber(0), zone()), zone()));
    UseValue(node);
    Reduction r = Reduce(node);
119 120 121 122 123 124 125
    EXPECT_FALSE(r.Changed());
  }
}

TEST_F(ConstantFoldingReducerTest, ParameterWithNull) {
  Handle<HeapObject> null = factory()->null_value();
  {
126 127 128
    Node* node = Parameter(Type::Constant(broker(), null, zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
129
    ASSERT_TRUE(r.Changed());
130
    EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null));
131 132
  }
  {
133 134 135
    Node* node = Parameter(Type::Null());
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
136
    ASSERT_TRUE(r.Changed());
137
    EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null));
138 139 140 141 142 143 144 145 146
  }
}

TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
  const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
                          std::numeric_limits<double>::quiet_NaN(),
                          std::numeric_limits<double>::signaling_NaN()};
  TRACED_FOREACH(double, nan, kNaNs) {
    Handle<Object> constant = factory()->NewNumber(nan);
147 148 149
    Node* node = Parameter(Type::Constant(broker(), constant, zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
150
    ASSERT_TRUE(r.Changed());
151
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
152 153
  }
  {
154 155 156 157
    Node* node =
        Parameter(Type::Constant(broker(), factory()->nan_value(), zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
158
    ASSERT_TRUE(r.Changed());
159
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
160 161
  }
  {
162 163 164
    Node* node = Parameter(Type::NaN());
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
165
    ASSERT_TRUE(r.Changed());
166
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
167 168 169 170 171 172
  }
}

TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) {
  TRACED_FOREACH(double, value, kFloat64Values) {
    Handle<Object> constant = factory()->NewNumber(value);
173 174 175
    Node* node = Parameter(Type::Constant(broker(), constant, zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
176
    ASSERT_TRUE(r.Changed());
177
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value));
178 179
  }
  TRACED_FOREACH(double, value, kIntegerValues) {
180 181 182
    Node* node = Parameter(Type::Range(value, value, zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
183
    ASSERT_TRUE(r.Changed());
184
    EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value));
185 186 187 188 189 190
  }
}

TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) {
  Handle<HeapObject> undefined = factory()->undefined_value();
  {
191 192 193
    Node* node = Parameter(Type::Undefined());
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
194
    ASSERT_TRUE(r.Changed());
195
    EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant());
196 197
  }
  {
198 199 200
    Node* node = Parameter(Type::Constant(broker(), undefined, zone()));
    Node* use_value = UseValue(node);
    Reduction r = Reduce(node);
201
    ASSERT_TRUE(r.Changed());
202
    EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant());
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  }
}

// -----------------------------------------------------------------------------
// ToBoolean

TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
  Node* input = Parameter(
      Type::Union(
          Type::MinusZero(),
          Type::Union(
              Type::NaN(),
              Type::Union(
                  Type::Null(),
                  Type::Union(
                      Type::Undefined(),
                      Type::Union(
                          Type::Undetectable(),
221
                          Type::Union(
222 223
                              Type::Constant(broker(), factory()->false_value(),
                                             zone()),
224
                              Type::Range(0.0, 0.0, zone()), zone()),
225 226 227 228 229 230
                          zone()),
                      zone()),
                  zone()),
              zone()),
          zone()),
      0);
231 232 233
  Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
  Node* use_value = UseValue(node);
  Reduction r = Reduce(node);
234
  ASSERT_TRUE(r.Changed());
235
  EXPECT_THAT(use_value->InputAt(1), IsFalseConstant());
236 237 238 239 240
}

TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
  Node* input = Parameter(
      Type::Union(
241
          Type::Constant(broker(), factory()->true_value(), zone()),
242 243 244
          Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
          zone()),
      0);
245 246 247
  Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
  Node* use_value = UseValue(node);
  Reduction r = Reduce(node);
248
  ASSERT_TRUE(r.Changed());
249
  EXPECT_THAT(use_value->InputAt(1), IsTrueConstant());
250 251 252 253
}

TEST_F(ConstantFoldingReducerTest, ToBooleanWithNonZeroPlainNumber) {
  Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
254 255 256
  Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
  Node* use_value = UseValue(node);
  Reduction r = Reduce(node);
257
  ASSERT_TRUE(r.Changed());
258
  EXPECT_THAT(use_value->InputAt(1), IsTrueConstant());
259 260 261 262 263 264
}

}  // namespace constant_folding_reducer_unittest
}  // namespace compiler
}  // namespace internal
}  // namespace v8