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/simplified-operator.h"
      6 
      7 #include "src/compiler/operator-properties-inl.h"
      8 #include "src/test/test-utils.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 namespace compiler {
     13 
     14 // TODO(bmeurer): Drop once we use std::ostream instead of our OStream.
     15 inline std::ostream& operator<<(std::ostream& os, const ElementAccess& access) {
     16   OStringStream ost;
     17   ost << access;
     18   return os << ost.c_str();
     19 }
     20 
     21 
     22 // -----------------------------------------------------------------------------
     23 // Pure operators.
     24 
     25 
     26 namespace {
     27 
     28 struct PureOperator {
     29   const Operator* (SimplifiedOperatorBuilder::*constructor)();
     30   IrOpcode::Value opcode;
     31   Operator::Properties properties;
     32   int value_input_count;
     33 };
     34 
     35 
     36 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
     37   return os << IrOpcode::Mnemonic(pop.opcode);
     38 }
     39 
     40 
     41 const PureOperator kPureOperators[] = {
     42 #define PURE(Name, properties, input_count)              \
     43   {                                                      \
     44     &SimplifiedOperatorBuilder::Name, IrOpcode::k##Name, \
     45         Operator::kPure | properties, input_count        \
     46   }
     47     PURE(BooleanNot, Operator::kNoProperties, 1),
     48     PURE(NumberEqual, Operator::kCommutative, 2),
     49     PURE(NumberLessThan, Operator::kNoProperties, 2),
     50     PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
     51     PURE(NumberAdd, Operator::kCommutative, 2),
     52     PURE(NumberSubtract, Operator::kNoProperties, 2),
     53     PURE(NumberMultiply, Operator::kCommutative, 2),
     54     PURE(NumberDivide, Operator::kNoProperties, 2),
     55     PURE(NumberModulus, Operator::kNoProperties, 2),
     56     PURE(NumberToInt32, Operator::kNoProperties, 1),
     57     PURE(NumberToUint32, Operator::kNoProperties, 1),
     58     PURE(StringEqual, Operator::kCommutative, 2),
     59     PURE(StringLessThan, Operator::kNoProperties, 2),
     60     PURE(StringLessThanOrEqual, Operator::kNoProperties, 2),
     61     PURE(StringAdd, Operator::kNoProperties, 2),
     62     PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
     63     PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
     64     PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
     65     PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
     66     PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
     67     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
     68     PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
     69     PURE(ChangeBitToBool, Operator::kNoProperties, 1)
     70 #undef PURE
     71 };
     72 
     73 }  // namespace
     74 
     75 
     76 class SimplifiedPureOperatorTest
     77     : public TestWithZone,
     78       public ::testing::WithParamInterface<PureOperator> {};
     79 
     80 
     81 TEST_P(SimplifiedPureOperatorTest, InstancesAreGloballyShared) {
     82   const PureOperator& pop = GetParam();
     83   SimplifiedOperatorBuilder simplified1(zone());
     84   SimplifiedOperatorBuilder simplified2(zone());
     85   EXPECT_EQ((simplified1.*pop.constructor)(), (simplified2.*pop.constructor)());
     86 }
     87 
     88 
     89 TEST_P(SimplifiedPureOperatorTest, NumberOfInputsAndOutputs) {
     90   SimplifiedOperatorBuilder simplified(zone());
     91   const PureOperator& pop = GetParam();
     92   const Operator* op = (simplified.*pop.constructor)();
     93 
     94   EXPECT_EQ(pop.value_input_count, OperatorProperties::GetValueInputCount(op));
     95   EXPECT_EQ(0, OperatorProperties::GetEffectInputCount(op));
     96   EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op));
     97   EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
     98 
     99   EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
    100   EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
    101   EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
    102 }
    103 
    104 
    105 TEST_P(SimplifiedPureOperatorTest, OpcodeIsCorrect) {
    106   SimplifiedOperatorBuilder simplified(zone());
    107   const PureOperator& pop = GetParam();
    108   const Operator* op = (simplified.*pop.constructor)();
    109   EXPECT_EQ(pop.opcode, op->opcode());
    110 }
    111 
    112 
    113 TEST_P(SimplifiedPureOperatorTest, Properties) {
    114   SimplifiedOperatorBuilder simplified(zone());
    115   const PureOperator& pop = GetParam();
    116   const Operator* op = (simplified.*pop.constructor)();
    117   EXPECT_EQ(pop.properties, op->properties() & pop.properties);
    118 }
    119 
    120 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest,
    121                         ::testing::ValuesIn(kPureOperators));
    122 
    123 
    124 // -----------------------------------------------------------------------------
    125 // Element access operators.
    126 
    127 namespace {
    128 
    129 const ElementAccess kElementAccesses[] = {
    130     {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged},
    131     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    132      kMachInt8},
    133     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    134      kMachInt16},
    135     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    136      kMachInt32},
    137     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    138      kMachUint8},
    139     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    140      kMachUint16},
    141     {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
    142      kMachUint32},
    143     {kUntaggedBase, 0, Type::Signed32(), kMachInt8},
    144     {kUntaggedBase, 0, Type::Unsigned32(), kMachUint8},
    145     {kUntaggedBase, 0, Type::Signed32(), kMachInt16},
    146     {kUntaggedBase, 0, Type::Unsigned32(), kMachUint16},
    147     {kUntaggedBase, 0, Type::Signed32(), kMachInt32},
    148     {kUntaggedBase, 0, Type::Unsigned32(), kMachUint32},
    149     {kUntaggedBase, 0, Type::Number(), kRepFloat32},
    150     {kUntaggedBase, 0, Type::Number(), kRepFloat64},
    151     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    152      kMachInt8},
    153     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    154      kMachUint8},
    155     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    156      kMachInt16},
    157     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    158      kMachUint16},
    159     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
    160      kMachInt32},
    161     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
    162      kMachUint32},
    163     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
    164      kRepFloat32},
    165     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
    166      kRepFloat64}};
    167 
    168 }  // namespace
    169 
    170 
    171 class SimplifiedElementAccessOperatorTest
    172     : public TestWithZone,
    173       public ::testing::WithParamInterface<ElementAccess> {};
    174 
    175 
    176 TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) {
    177   SimplifiedOperatorBuilder simplified(zone());
    178   const ElementAccess& access = GetParam();
    179   const Operator* op = simplified.LoadElement(access);
    180 
    181   EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
    182   EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
    183   EXPECT_EQ(access, ElementAccessOf(op));
    184 
    185   EXPECT_EQ(3, OperatorProperties::GetValueInputCount(op));
    186   EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op));
    187   EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op));
    188   EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op));
    189 
    190   EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
    191   EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
    192   EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
    193 }
    194 
    195 
    196 TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) {
    197   SimplifiedOperatorBuilder simplified(zone());
    198   const ElementAccess& access = GetParam();
    199   const Operator* op = simplified.StoreElement(access);
    200 
    201   EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
    202   EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
    203   EXPECT_EQ(access, ElementAccessOf(op));
    204 
    205   EXPECT_EQ(4, OperatorProperties::GetValueInputCount(op));
    206   EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op));
    207   EXPECT_EQ(1, OperatorProperties::GetControlInputCount(op));
    208   EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op));
    209 
    210   EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
    211   EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
    212   EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
    213 }
    214 
    215 
    216 INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest,
    217                         SimplifiedElementAccessOperatorTest,
    218                         ::testing::ValuesIn(kElementAccesses));
    219 
    220 }  // namespace compiler
    221 }  // namespace internal
    222 }  // namespace v8
    223