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/common-operator.h" 6 7 #include <limits> 8 9 #include "src/compiler/operator-properties-inl.h" 10 #include "src/test/test-utils.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace compiler { 15 16 17 // ----------------------------------------------------------------------------- 18 // Shared operators. 19 20 21 namespace { 22 23 struct SharedOperator { 24 const Operator* (CommonOperatorBuilder::*constructor)(); 25 IrOpcode::Value opcode; 26 Operator::Properties properties; 27 int value_input_count; 28 int effect_input_count; 29 int control_input_count; 30 int effect_output_count; 31 int control_output_count; 32 }; 33 34 35 std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) { 36 return os << IrOpcode::Mnemonic(fop.opcode); 37 } 38 39 40 const SharedOperator kSharedOperators[] = { 41 #define SHARED(Name, properties, value_input_count, effect_input_count, \ 42 control_input_count, effect_output_count, control_output_count) \ 43 { \ 44 &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties, \ 45 value_input_count, effect_input_count, control_input_count, \ 46 effect_output_count, control_output_count \ 47 } 48 SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 1), 49 SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0), 50 SHARED(Branch, Operator::kFoldable, 1, 0, 1, 0, 2), 51 SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1), 52 SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1), 53 SHARED(Throw, Operator::kFoldable, 1, 0, 1, 0, 1), 54 SHARED(Return, Operator::kNoProperties, 1, 1, 1, 1, 1), 55 SHARED(ControlEffect, Operator::kPure, 0, 0, 1, 1, 0) 56 #undef SHARED 57 }; 58 59 60 class CommonSharedOperatorTest 61 : public TestWithZone, 62 public ::testing::WithParamInterface<SharedOperator> {}; 63 64 } // namespace 65 66 67 TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) { 68 const SharedOperator& sop = GetParam(); 69 CommonOperatorBuilder common1(zone()); 70 CommonOperatorBuilder common2(zone()); 71 EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)()); 72 } 73 74 75 TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) { 76 CommonOperatorBuilder common(zone()); 77 const SharedOperator& sop = GetParam(); 78 const Operator* op = (common.*sop.constructor)(); 79 80 EXPECT_EQ(sop.value_input_count, OperatorProperties::GetValueInputCount(op)); 81 EXPECT_EQ(sop.effect_input_count, 82 OperatorProperties::GetEffectInputCount(op)); 83 EXPECT_EQ(sop.control_input_count, 84 OperatorProperties::GetControlInputCount(op)); 85 EXPECT_EQ( 86 sop.value_input_count + sop.effect_input_count + sop.control_input_count, 87 OperatorProperties::GetTotalInputCount(op)); 88 89 EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op)); 90 EXPECT_EQ(sop.effect_output_count, 91 OperatorProperties::GetEffectOutputCount(op)); 92 EXPECT_EQ(sop.control_output_count, 93 OperatorProperties::GetControlOutputCount(op)); 94 } 95 96 97 TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) { 98 CommonOperatorBuilder common(zone()); 99 const SharedOperator& sop = GetParam(); 100 const Operator* op = (common.*sop.constructor)(); 101 EXPECT_EQ(sop.opcode, op->opcode()); 102 } 103 104 105 TEST_P(CommonSharedOperatorTest, Properties) { 106 CommonOperatorBuilder common(zone()); 107 const SharedOperator& sop = GetParam(); 108 const Operator* op = (common.*sop.constructor)(); 109 EXPECT_EQ(sop.properties, op->properties()); 110 } 111 112 113 INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest, 114 ::testing::ValuesIn(kSharedOperators)); 115 116 117 // ----------------------------------------------------------------------------- 118 // Other operators. 119 120 121 namespace { 122 123 class CommonOperatorTest : public TestWithZone { 124 public: 125 CommonOperatorTest() : common_(zone()) {} 126 virtual ~CommonOperatorTest() {} 127 128 CommonOperatorBuilder* common() { return &common_; } 129 130 private: 131 CommonOperatorBuilder common_; 132 }; 133 134 135 const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt}; 136 137 const float kFloat32Values[] = { 138 std::numeric_limits<float>::min(), -1.0f, -0.0f, 0.0f, 1.0f, 139 std::numeric_limits<float>::max()}; 140 141 } // namespace 142 143 144 TEST_F(CommonOperatorTest, Float32Constant) { 145 TRACED_FOREACH(float, value, kFloat32Values) { 146 const Operator* op = common()->Float32Constant(value); 147 EXPECT_FLOAT_EQ(value, OpParameter<float>(op)); 148 EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op)); 149 EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op)); 150 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); 151 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); 152 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); 153 } 154 } 155 156 157 TEST_F(CommonOperatorTest, ValueEffect) { 158 TRACED_FOREACH(int, arguments, kArguments) { 159 const Operator* op = common()->ValueEffect(arguments); 160 EXPECT_EQ(arguments, OperatorProperties::GetValueInputCount(op)); 161 EXPECT_EQ(arguments, OperatorProperties::GetTotalInputCount(op)); 162 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); 163 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op)); 164 EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op)); 165 } 166 } 167 168 169 TEST_F(CommonOperatorTest, Finish) { 170 TRACED_FOREACH(int, arguments, kArguments) { 171 const Operator* op = common()->Finish(arguments); 172 EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op)); 173 EXPECT_EQ(arguments, OperatorProperties::GetEffectInputCount(op)); 174 EXPECT_EQ(arguments + 1, OperatorProperties::GetTotalInputCount(op)); 175 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); 176 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); 177 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); 178 } 179 } 180 181 } // namespace compiler 182 } // namespace internal 183 } // namespace v8 184