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/compiler/opcodes.h"
      6 #include "src/compiler/operator.h"
      7 #include "src/compiler/operator-properties.h"
      8 #include "src/compiler/simplified-operator.h"
      9 #include "src/types-inl.h"
     10 #include "test/unittests/test-utils.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace compiler {
     15 
     16 // -----------------------------------------------------------------------------
     17 // Pure operators.
     18 
     19 
     20 namespace {
     21 
     22 struct PureOperator {
     23   const Operator* (SimplifiedOperatorBuilder::*constructor)();
     24   IrOpcode::Value opcode;
     25   Operator::Properties properties;
     26   int value_input_count;
     27 };
     28 
     29 
     30 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
     31   return os << IrOpcode::Mnemonic(pop.opcode);
     32 }
     33 
     34 
     35 const PureOperator kPureOperators[] = {
     36 #define PURE(Name, properties, input_count)              \
     37   {                                                      \
     38     &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
     39         Operator::kPure | properties, input_count        \
     40   }
     41     PURE(BooleanNot, Operator::kNoProperties, 1),
     42     PURE(BooleanToNumber, Operator::kNoProperties, 1),
     43     PURE(NumberEqual, Operator::kCommutative, 2),
     44     PURE(NumberLessThan, Operator::kNoProperties, 2),
     45     PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
     46     PURE(NumberAdd, Operator::kCommutative, 2),
     47     PURE(NumberSubtract, Operator::kNoProperties, 2),
     48     PURE(NumberMultiply, Operator::kCommutative, 2),
     49     PURE(NumberDivide, Operator::kNoProperties, 2),
     50     PURE(NumberModulus, Operator::kNoProperties, 2),
     51     PURE(NumberBitwiseOr, Operator::kCommutative, 2),
     52     PURE(NumberBitwiseXor, Operator::kCommutative, 2),
     53     PURE(NumberBitwiseAnd, Operator::kCommutative, 2),
     54     PURE(NumberShiftLeft, Operator::kNoProperties, 2),
     55     PURE(NumberShiftRight, Operator::kNoProperties, 2),
     56     PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
     57     PURE(NumberToInt32, Operator::kNoProperties, 1),
     58     PURE(NumberToUint32, Operator::kNoProperties, 1),
     59     PURE(PlainPrimitiveToNumber, Operator::kNoProperties, 1),
     60     PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
     61     PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
     62     PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
     63     PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
     64     PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
     65     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
     66     PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
     67     PURE(ChangeBitToBool, Operator::kNoProperties, 1),
     68     PURE(ObjectIsSmi, Operator::kNoProperties, 1)
     69 #undef PURE
     70 };
     71 
     72 }  // namespace
     73 
     74 
     75 class SimplifiedPureOperatorTest
     76     : public TestWithZone,
     77       public ::testing::WithParamInterface<PureOperator> {};
     78 
     79 
     80 TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
     81   const PureOperator& pop = GetParam();
     82   SimplifiedOperatorBuilder simplified1(zone());
     83   SimplifiedOperatorBuilder simplified2(zone());
     84   EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
     85 }
     86 
     87 
     88 TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
     89   SimplifiedOperatorBuilder simplified(zone());
     90   const PureOperator& pop = GetParam();
     91   const Operator* op = (simplified.*pop.constructor)();
     92 
     93   EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
     94   EXPECT_EQ(0, op->EffectInputCount());
     95   EXPECT_EQ(0, op->ControlInputCount());
     96   EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
     97 
     98   EXPECT_EQ(1, op->ValueOutputCount());
     99   EXPECT_EQ(0, op->EffectOutputCount());
    100   EXPECT_EQ(0, op->ControlOutputCount());
    101 }
    102 
    103 
    104 TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
    105   SimplifiedOperatorBuilder simplified(zone());
    106   const PureOperator& pop = GetParam();
    107   const Operator* op = (simplified.*pop.constructor)();
    108   EXPECT_EQ(pop.opcode, op->opcode());
    109 }
    110 
    111 
    112 TEST_P(SimplifiedPureOperatorTest, Properties) {
    113   SimplifiedOperatorBuilder simplified(zone());
    114   const PureOperator& pop = GetParam();
    115   const Operator* op = (simplified.*pop.constructor)();
    116   EXPECT_EQ(pop.properties, op->properties() & pop.properties);
    117 }
    118 
    119 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
    120                         ::testing::ValuesIn(kPureOperators));
    121 
    122 
    123 // -----------------------------------------------------------------------------
    124 // Buffer access operators.
    125 
    126 
    127 namespace {
    128 
    129 const ExternalArrayType kExternalArrayTypes[] = {
    130     kExternalUint8Array,   kExternalInt8Array,   kExternalUint16Array,
    131     kExternalInt16Array,   kExternalUint32Array, kExternalInt32Array,
    132     kExternalFloat32Array, kExternalFloat64Array};
    133 
    134 }  // namespace
    135 
    136 
    137 class SimplifiedBufferAccessOperatorTest
    138     : public TestWithZone,
    139       public ::testing::WithParamInterface<ExternalArrayType> {};
    140 
    141 
    142 TEST_P(SimplifiedBufferAccessOperatorTest, InstancesAreGloballyShared) {
    143   BufferAccess const access(GetParam());
    144   SimplifiedOperatorBuilder simplified1(zone());
    145   SimplifiedOperatorBuilder simplified2(zone());
    146   EXPECT_EQ(simplified1.LoadBuffer(access), simplified2.LoadBuffer(access));
    147   EXPECT_EQ(simplified1.StoreBuffer(access), simplified2.StoreBuffer(access));
    148 }
    149 
    150 
    151 TEST_P(SimplifiedBufferAccessOperatorTest, LoadBuffer) {
    152   SimplifiedOperatorBuilder simplified(zone());
    153   BufferAccess const access(GetParam());
    154   const Operator* op = simplified.LoadBuffer(access);
    155 
    156   EXPECT_EQ(IrOpcode::kLoadBuffer, op->opcode());
    157   EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
    158   EXPECT_EQ(access, BufferAccessOf(op));
    159 
    160   EXPECT_EQ(3, op->ValueInputCount());
    161   EXPECT_EQ(1, op->EffectInputCount());
    162   EXPECT_EQ(1, op->ControlInputCount());
    163   EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
    164 
    165   EXPECT_EQ(1, op->ValueOutputCount());
    166   EXPECT_EQ(1, op->EffectOutputCount());
    167   EXPECT_EQ(0, op->ControlOutputCount());
    168 }
    169 
    170 
    171 TEST_P(SimplifiedBufferAccessOperatorTest, StoreBuffer) {
    172   SimplifiedOperatorBuilder simplified(zone());
    173   BufferAccess const access(GetParam());
    174   const Operator* op = simplified.StoreBuffer(access);
    175 
    176   EXPECT_EQ(IrOpcode::kStoreBuffer, op->opcode());
    177   EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
    178   EXPECT_EQ(access, BufferAccessOf(op));
    179 
    180   EXPECT_EQ(4, op->ValueInputCount());
    181   EXPECT_EQ(1, op->EffectInputCount());
    182   EXPECT_EQ(1, op->ControlInputCount());
    183   EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op));
    184 
    185   EXPECT_EQ(0, op->ValueOutputCount());
    186   EXPECT_EQ(1, op->EffectOutputCount());
    187   EXPECT_EQ(0, op->ControlOutputCount());
    188 }
    189 
    190 
    191 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
    192                         SimplifiedBufferAccessOperatorTest,
    193                         ::testing::ValuesIn(kExternalArrayTypes));
    194 
    195 
    196 // -----------------------------------------------------------------------------
    197 // Element access operators.
    198 
    199 
    200 namespace {
    201 
    202 const ElementAccess kElementAccesses[] = {
    203     {kTaggedBase, FixedArray::kHeaderSize, Type::Any(),
    204      MachineType::AnyTagged()},
    205     {kUntaggedBase, 0, Type::Any(), MachineType::Int8()},
    206     {kUntaggedBase, 0, Type::Any(), MachineType::Int16()},
    207     {kUntaggedBase, 0, Type::Any(), MachineType::Int32()},
    208     {kUntaggedBase, 0, Type::Any(), MachineType::Uint8()},
    209     {kUntaggedBase, 0, Type::Any(), MachineType::Uint16()},
    210     {kUntaggedBase, 0, Type::Any(), MachineType::Uint32()},
    211     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8()},
    212     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8()},
    213     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16()},
    214     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16()},
    215     {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32()},
    216     {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32()},
    217     {kUntaggedBase, 0, Type::Number(),
    218      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
    219     {kUntaggedBase, 0, Type::Number(),
    220      MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone)},
    221     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    222      MachineType::Int8()},
    223     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    224      MachineType::Uint8()},
    225     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    226      MachineType::Int16()},
    227     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    228      MachineType::Uint16()},
    229     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    230      MachineType::Int32()},
    231     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    232      MachineType::Uint32()},
    233     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
    234      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
    235     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
    236      MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)}};
    237 
    238 }  // namespace
    239 
    240 
    241 class SimplifiedElementAccessOperatorTest
    242     : public TestWithZone,
    243       public ::testing::WithParamInterface<ElementAccess> {};
    244 
    245 
    246 TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
    247   SimplifiedOperatorBuilder simplified(zone());
    248   const ElementAccess& access = GetParam();
    249   const Operator* op = simplified.LoadElement(access);
    250 
    251   EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
    252   EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
    253   EXPECT_EQ(access, ElementAccessOf(op));
    254 
    255   EXPECT_EQ(2, op->ValueInputCount());
    256   EXPECT_EQ(1, op->EffectInputCount());
    257   EXPECT_EQ(1, op->ControlInputCount());
    258   EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
    259 
    260   EXPECT_EQ(1, op->ValueOutputCount());
    261   EXPECT_EQ(1, op->EffectOutputCount());
    262   EXPECT_EQ(0, op->ControlOutputCount());
    263 }
    264 
    265 
    266 TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
    267   SimplifiedOperatorBuilder simplified(zone());
    268   const ElementAccess& access = GetParam();
    269   const Operator* op = simplified.StoreElement(access);
    270 
    271   EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
    272   EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
    273   EXPECT_EQ(access, ElementAccessOf(op));
    274 
    275   EXPECT_EQ(3, op->ValueInputCount());
    276   EXPECT_EQ(1, op->EffectInputCount());
    277   EXPECT_EQ(1, op->ControlInputCount());
    278   EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op));
    279 
    280   EXPECT_EQ(0, op->ValueOutputCount());
    281   EXPECT_EQ(1, op->EffectOutputCount());
    282   EXPECT_EQ(0, op->ControlOutputCount());
    283 }
    284 
    285 
    286 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
    287                         SimplifiedElementAccessOperatorTest,
    288                         ::testing::ValuesIn(kElementAccesses));
    289 
    290 }  // namespace compiler
    291 }  // namespace internal
    292 }  // namespace v8
    293