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