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 <limits>
      6 
      7 #include "src/compiler/common-operator.h"
      8 #include "src/compiler/opcodes.h"
      9 #include "src/compiler/operator.h"
     10 #include "src/compiler/operator-properties.h"
     11 #include "test/unittests/test-utils.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace compiler {
     16 
     17 
     18 // -----------------------------------------------------------------------------
     19 // Shared operators.
     20 
     21 
     22 namespace {
     23 
     24 struct SharedOperator {
     25   const Operator* (CommonOperatorBuilder::*constructor)();
     26   IrOpcode::Value opcode;
     27   Operator::Properties properties;
     28   int value_input_count;
     29   int effect_input_count;
     30   int control_input_count;
     31   int value_output_count;
     32   int effect_output_count;
     33   int control_output_count;
     34 };
     35 
     36 
     37 std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
     38   return os << IrOpcode::Mnemonic(fop.opcode);
     39 }
     40 
     41 
     42 const SharedOperator kSharedOperators[] = {
     43 #define SHARED(Name, properties, value_input_count, effect_input_count,      \
     44                control_input_count, value_output_count, effect_output_count, \
     45                control_output_count)                                         \
     46   {                                                                          \
     47     &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties,             \
     48         value_input_count, effect_input_count, control_input_count,          \
     49         value_output_count, effect_output_count, control_output_count        \
     50   }
     51     SHARED(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1),
     52     SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
     53     SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
     54     SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
     55     SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
     56     SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
     57 #undef SHARED
     58 };
     59 
     60 
     61 class CommonSharedOperatorTest
     62     : public TestWithZone,
     63       public ::testing::WithParamInterface<SharedOperator> {};
     64 
     65 }  // namespace
     66 
     67 
     68 TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
     69   const SharedOperator& sop = GetParam();
     70   CommonOperatorBuilder common1(zone());
     71   CommonOperatorBuilder common2(zone());
     72   EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
     73 }
     74 
     75 
     76 TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
     77   CommonOperatorBuilder common(zone());
     78   const SharedOperator& sop = GetParam();
     79   const Operator* op = (common.*sop.constructor)();
     80 
     81   EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
     82   EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
     83   EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
     84   EXPECT_EQ(
     85       sop.value_input_count + sop.effect_input_count + sop.control_input_count,
     86       OperatorProperties::GetTotalInputCount(op));
     87 
     88   EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
     89   EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
     90   EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
     91 }
     92 
     93 
     94 TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
     95   CommonOperatorBuilder common(zone());
     96   const SharedOperator& sop = GetParam();
     97   const Operator* op = (common.*sop.constructor)();
     98   EXPECT_EQ(sop.opcode, op->opcode());
     99 }
    100 
    101 
    102 TEST_P(CommonSharedOperatorTest, Properties) {
    103   CommonOperatorBuilder common(zone());
    104   const SharedOperator& sop = GetParam();
    105   const Operator* op = (common.*sop.constructor)();
    106   EXPECT_EQ(sop.properties, op->properties());
    107 }
    108 
    109 
    110 INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
    111                         ::testing::ValuesIn(kSharedOperators));
    112 
    113 
    114 // -----------------------------------------------------------------------------
    115 // Other operators.
    116 
    117 
    118 namespace {
    119 
    120 class CommonOperatorTest : public TestWithZone {
    121  public:
    122   CommonOperatorTest() : common_(zone()) {}
    123   ~CommonOperatorTest() override {}
    124 
    125   CommonOperatorBuilder* common() { return &common_; }
    126 
    127  private:
    128   CommonOperatorBuilder common_;
    129 };
    130 
    131 
    132 const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
    133 
    134 
    135 const size_t kCases[] = {3, 4, 100, 255, 1024, 65000};
    136 
    137 
    138 const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
    139                               std::numeric_limits<float>::min(),
    140                               -1.0f,
    141                               -0.0f,
    142                               0.0f,
    143                               1.0f,
    144                               std::numeric_limits<float>::max(),
    145                               std::numeric_limits<float>::infinity(),
    146                               std::numeric_limits<float>::quiet_NaN(),
    147                               std::numeric_limits<float>::signaling_NaN()};
    148 
    149 
    150 const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
    151 
    152 
    153 const int32_t kInt32Values[] = {
    154     std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386,
    155     -1577976073, -1573998034, -1529085059, -1499540537, -1299205097,
    156     -1090814845, -938186388, -806828902, -750927650, -520676892, -513661538,
    157     -453036354, -433622833, -282638793, -28375, -27788, -22770, -18806, -14173,
    158     -11956, -11200, -10212, -8160, -3751, -2758, -1522, -121, -120, -118, -117,
    159     -106, -84, -80, -74, -59, -52, -48, -39, -35, -17, -11, -10, -9, -7, -5, 0,
    160     9, 12, 17, 23, 29, 31, 33, 35, 40, 47, 55, 56, 62, 64, 67, 68, 69, 74, 79,
    161     84, 89, 90, 97, 104, 118, 124, 126, 127, 7278, 17787, 24136, 24202, 25570,
    162     26680, 30242, 32399, 420886487, 642166225, 821912648, 822577803, 851385718,
    163     1212241078, 1411419304, 1589626102, 1596437184, 1876245816, 1954730266,
    164     2008792749, 2045320228, std::numeric_limits<int32_t>::max()};
    165 
    166 
    167 const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue,
    168                                    BranchHint::kFalse};
    169 
    170 }  // namespace
    171 
    172 
    173 TEST_F(CommonOperatorTest, End) {
    174   TRACED_FOREACH(size_t, input_count, kInputCounts) {
    175     const Operator* const op = common()->End(input_count);
    176     EXPECT_EQ(IrOpcode::kEnd, op->opcode());
    177     EXPECT_EQ(Operator::kKontrol, op->properties());
    178     EXPECT_EQ(0, op->ValueInputCount());
    179     EXPECT_EQ(0, op->EffectInputCount());
    180     EXPECT_EQ(input_count, static_cast<uint32_t>(op->ControlInputCount()));
    181     EXPECT_EQ(input_count, static_cast<uint32_t>(
    182                                OperatorProperties::GetTotalInputCount(op)));
    183     EXPECT_EQ(0, op->ValueOutputCount());
    184     EXPECT_EQ(0, op->EffectOutputCount());
    185     EXPECT_EQ(0, op->ControlOutputCount());
    186   }
    187 }
    188 
    189 
    190 TEST_F(CommonOperatorTest, Return) {
    191   TRACED_FOREACH(int, input_count, kArguments) {
    192     const Operator* const op = common()->Return(input_count);
    193     EXPECT_EQ(IrOpcode::kReturn, op->opcode());
    194     EXPECT_EQ(Operator::kNoThrow, op->properties());
    195     EXPECT_EQ(input_count, op->ValueInputCount());
    196     EXPECT_EQ(1, op->EffectInputCount());
    197     EXPECT_EQ(1, op->ControlInputCount());
    198     EXPECT_EQ(2 + input_count, OperatorProperties::GetTotalInputCount(op));
    199     EXPECT_EQ(0, op->ValueOutputCount());
    200     EXPECT_EQ(0, op->EffectOutputCount());
    201     EXPECT_EQ(1, op->ControlOutputCount());
    202   }
    203 }
    204 
    205 
    206 TEST_F(CommonOperatorTest, Branch) {
    207   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
    208     const Operator* const op = common()->Branch(hint);
    209     EXPECT_EQ(IrOpcode::kBranch, op->opcode());
    210     EXPECT_EQ(Operator::kKontrol, op->properties());
    211     EXPECT_EQ(hint, BranchHintOf(op));
    212     EXPECT_EQ(1, op->ValueInputCount());
    213     EXPECT_EQ(0, op->EffectInputCount());
    214     EXPECT_EQ(1, op->ControlInputCount());
    215     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
    216     EXPECT_EQ(0, op->ValueOutputCount());
    217     EXPECT_EQ(0, op->EffectOutputCount());
    218     EXPECT_EQ(2, op->ControlOutputCount());
    219   }
    220 }
    221 
    222 
    223 TEST_F(CommonOperatorTest, IfException) {
    224   static const IfExceptionHint kIfExceptionHints[] = {
    225       IfExceptionHint::kLocallyCaught, IfExceptionHint::kLocallyUncaught};
    226   TRACED_FOREACH(IfExceptionHint, hint, kIfExceptionHints) {
    227     const Operator* const op = common()->IfException(hint);
    228     EXPECT_EQ(IrOpcode::kIfException, op->opcode());
    229     EXPECT_EQ(Operator::kKontrol, op->properties());
    230     EXPECT_EQ(0, op->ValueInputCount());
    231     EXPECT_EQ(1, op->EffectInputCount());
    232     EXPECT_EQ(1, op->ControlInputCount());
    233     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
    234     EXPECT_EQ(1, op->ValueOutputCount());
    235     EXPECT_EQ(1, op->EffectOutputCount());
    236     EXPECT_EQ(1, op->ControlOutputCount());
    237   }
    238 }
    239 
    240 
    241 TEST_F(CommonOperatorTest, Switch) {
    242   TRACED_FOREACH(size_t, cases, kCases) {
    243     const Operator* const op = common()->Switch(cases);
    244     EXPECT_EQ(IrOpcode::kSwitch, op->opcode());
    245     EXPECT_EQ(Operator::kKontrol, op->properties());
    246     EXPECT_EQ(1, op->ValueInputCount());
    247     EXPECT_EQ(0, op->EffectInputCount());
    248     EXPECT_EQ(1, op->ControlInputCount());
    249     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
    250     EXPECT_EQ(0, op->ValueOutputCount());
    251     EXPECT_EQ(0, op->EffectOutputCount());
    252     EXPECT_EQ(static_cast<int>(cases), op->ControlOutputCount());
    253   }
    254 }
    255 
    256 
    257 TEST_F(CommonOperatorTest, IfValue) {
    258   TRACED_FOREACH(int32_t, value, kInt32Values) {
    259     const Operator* const op = common()->IfValue(value);
    260     EXPECT_EQ(IrOpcode::kIfValue, op->opcode());
    261     EXPECT_EQ(Operator::kKontrol, op->properties());
    262     EXPECT_EQ(value, OpParameter<int32_t>(op));
    263     EXPECT_EQ(0, op->ValueInputCount());
    264     EXPECT_EQ(0, op->EffectInputCount());
    265     EXPECT_EQ(1, op->ControlInputCount());
    266     EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
    267     EXPECT_EQ(0, op->ValueOutputCount());
    268     EXPECT_EQ(0, op->EffectOutputCount());
    269     EXPECT_EQ(1, op->ControlOutputCount());
    270   }
    271 }
    272 
    273 
    274 TEST_F(CommonOperatorTest, Select) {
    275   static const MachineRepresentation kMachineRepresentations[] = {
    276       MachineRepresentation::kBit,     MachineRepresentation::kWord8,
    277       MachineRepresentation::kWord16,  MachineRepresentation::kWord32,
    278       MachineRepresentation::kWord64,  MachineRepresentation::kFloat32,
    279       MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
    280 
    281 
    282   TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
    283     TRACED_FOREACH(BranchHint, hint, kBranchHints) {
    284       const Operator* const op = common()->Select(rep, hint);
    285       EXPECT_EQ(IrOpcode::kSelect, op->opcode());
    286       EXPECT_EQ(Operator::kPure, op->properties());
    287       EXPECT_EQ(rep, SelectParametersOf(op).representation());
    288       EXPECT_EQ(hint, SelectParametersOf(op).hint());
    289       EXPECT_EQ(3, op->ValueInputCount());
    290       EXPECT_EQ(0, op->EffectInputCount());
    291       EXPECT_EQ(0, op->ControlInputCount());
    292       EXPECT_EQ(3, OperatorProperties::GetTotalInputCount(op));
    293       EXPECT_EQ(1, op->ValueOutputCount());
    294       EXPECT_EQ(0, op->EffectOutputCount());
    295       EXPECT_EQ(0, op->ControlOutputCount());
    296     }
    297   }
    298 }
    299 
    300 
    301 TEST_F(CommonOperatorTest, Float32Constant) {
    302   TRACED_FOREACH(float, value, kFloatValues) {
    303     const Operator* op = common()->Float32Constant(value);
    304     EXPECT_PRED2(base::bit_equal_to<float>(), value, OpParameter<float>(op));
    305     EXPECT_EQ(0, op->ValueInputCount());
    306     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
    307     EXPECT_EQ(0, op->ControlOutputCount());
    308     EXPECT_EQ(0, op->EffectOutputCount());
    309     EXPECT_EQ(1, op->ValueOutputCount());
    310   }
    311   TRACED_FOREACH(float, v1, kFloatValues) {
    312     TRACED_FOREACH(float, v2, kFloatValues) {
    313       const Operator* op1 = common()->Float32Constant(v1);
    314       const Operator* op2 = common()->Float32Constant(v2);
    315       EXPECT_EQ(bit_cast<uint32_t>(v1) == bit_cast<uint32_t>(v2),
    316                 op1->Equals(op2));
    317     }
    318   }
    319 }
    320 
    321 
    322 TEST_F(CommonOperatorTest, Float64Constant) {
    323   TRACED_FOREACH(double, value, kFloatValues) {
    324     const Operator* op = common()->Float64Constant(value);
    325     EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
    326     EXPECT_EQ(0, op->ValueInputCount());
    327     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
    328     EXPECT_EQ(0, op->ControlOutputCount());
    329     EXPECT_EQ(0, op->EffectOutputCount());
    330     EXPECT_EQ(1, op->ValueOutputCount());
    331   }
    332   TRACED_FOREACH(double, v1, kFloatValues) {
    333     TRACED_FOREACH(double, v2, kFloatValues) {
    334       const Operator* op1 = common()->Float64Constant(v1);
    335       const Operator* op2 = common()->Float64Constant(v2);
    336       EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
    337                 op1->Equals(op2));
    338     }
    339   }
    340 }
    341 
    342 
    343 TEST_F(CommonOperatorTest, NumberConstant) {
    344   TRACED_FOREACH(double, value, kFloatValues) {
    345     const Operator* op = common()->NumberConstant(value);
    346     EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
    347     EXPECT_EQ(0, op->ValueInputCount());
    348     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
    349     EXPECT_EQ(0, op->ControlOutputCount());
    350     EXPECT_EQ(0, op->EffectOutputCount());
    351     EXPECT_EQ(1, op->ValueOutputCount());
    352   }
    353   TRACED_FOREACH(double, v1, kFloatValues) {
    354     TRACED_FOREACH(double, v2, kFloatValues) {
    355       const Operator* op1 = common()->NumberConstant(v1);
    356       const Operator* op2 = common()->NumberConstant(v2);
    357       EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
    358                 op1->Equals(op2));
    359     }
    360   }
    361 }
    362 
    363 
    364 TEST_F(CommonOperatorTest, BeginRegion) {
    365   {
    366     const Operator* op =
    367         common()->BeginRegion(RegionObservability::kObservable);
    368     EXPECT_EQ(1, op->EffectInputCount());
    369     EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
    370     EXPECT_EQ(0, op->ControlOutputCount());
    371     EXPECT_EQ(1, op->EffectOutputCount());
    372     EXPECT_EQ(0, op->ValueOutputCount());
    373   }
    374   {
    375     const Operator* op =
    376         common()->BeginRegion(RegionObservability::kNotObservable);
    377     EXPECT_EQ(1, op->EffectInputCount());
    378     EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
    379     EXPECT_EQ(0, op->ControlOutputCount());
    380     EXPECT_EQ(1, op->EffectOutputCount());
    381     EXPECT_EQ(0, op->ValueOutputCount());
    382   }
    383 }
    384 
    385 TEST_F(CommonOperatorTest, FinishRegion) {
    386   const Operator* op = common()->FinishRegion();
    387   EXPECT_EQ(1, op->ValueInputCount());
    388   EXPECT_EQ(1, op->EffectInputCount());
    389   EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
    390   EXPECT_EQ(0, op->ControlOutputCount());
    391   EXPECT_EQ(1, op->EffectOutputCount());
    392   EXPECT_EQ(1, op->ValueOutputCount());
    393 }
    394 
    395 TEST_F(CommonOperatorTest, Projection) {
    396   TRACED_FORRANGE(size_t, index, 0, 3) {
    397     const Operator* op = common()->Projection(index);
    398     EXPECT_EQ(index, ProjectionIndexOf(op));
    399     EXPECT_EQ(1, op->ValueInputCount());
    400     EXPECT_EQ(1, op->ControlInputCount());
    401     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
    402     EXPECT_EQ(0, op->ControlOutputCount());
    403     EXPECT_EQ(0, op->EffectOutputCount());
    404     EXPECT_EQ(1, op->ValueOutputCount());
    405   }
    406 }
    407 
    408 }  // namespace compiler
    409 }  // namespace internal
    410 }  // namespace v8
    411