1 // Copyright 2013 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.
5 #ifndef V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
6 #define V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
8 #include "src/compiler/common-operator.h"
9 #include "src/compiler/js-operator.h"
10 #include "src/compiler/opcodes.h"
11 #include "src/compiler/operator-properties.h"
17 inline bool OperatorProperties::HasValueInput(const Operator* op) {
18 return OperatorProperties::GetValueInputCount(op) > 0;
21 inline bool OperatorProperties::HasContextInput(const Operator* op) {
22 IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
23 return IrOpcode::IsJsOpcode(opcode);
26 inline bool OperatorProperties::HasEffectInput(const Operator* op) {
27 return OperatorProperties::GetEffectInputCount(op) > 0;
30 inline bool OperatorProperties::HasControlInput(const Operator* op) {
31 return OperatorProperties::GetControlInputCount(op) > 0;
34 inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
35 if (!FLAG_turbo_deoptimization) {
39 switch (op->opcode()) {
40 case IrOpcode::kFrameState:
42 case IrOpcode::kJSCallRuntime: {
43 Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(op);
44 return Linkage::NeedsFrameState(function);
47 // Strict equality cannot lazily deoptimize.
48 case IrOpcode::kJSStrictEqual:
49 case IrOpcode::kJSStrictNotEqual:
53 case IrOpcode::kJSCallFunction:
54 case IrOpcode::kJSCallConstruct:
57 case IrOpcode::kJSEqual:
58 case IrOpcode::kJSNotEqual:
59 case IrOpcode::kJSLessThan:
60 case IrOpcode::kJSGreaterThan:
61 case IrOpcode::kJSLessThanOrEqual:
62 case IrOpcode::kJSGreaterThanOrEqual:
65 case IrOpcode::kJSBitwiseOr:
66 case IrOpcode::kJSBitwiseXor:
67 case IrOpcode::kJSBitwiseAnd:
68 case IrOpcode::kJSShiftLeft:
69 case IrOpcode::kJSShiftRight:
70 case IrOpcode::kJSShiftRightLogical:
71 case IrOpcode::kJSAdd:
72 case IrOpcode::kJSSubtract:
73 case IrOpcode::kJSMultiply:
74 case IrOpcode::kJSDivide:
75 case IrOpcode::kJSModulus:
76 case IrOpcode::kJSLoadProperty:
77 case IrOpcode::kJSStoreProperty:
78 case IrOpcode::kJSLoadNamed:
79 case IrOpcode::kJSStoreNamed:
87 inline int OperatorProperties::GetValueInputCount(const Operator* op) {
88 return op->InputCount();
91 inline int OperatorProperties::GetContextInputCount(const Operator* op) {
92 return OperatorProperties::HasContextInput(op) ? 1 : 0;
95 inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
96 return OperatorProperties::HasFrameStateInput(op) ? 1 : 0;
99 inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
100 if (op->opcode() == IrOpcode::kEffectPhi ||
101 op->opcode() == IrOpcode::kFinish) {
102 return OpParameter<int>(op);
104 if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
105 return 0; // no effects.
109 inline int OperatorProperties::GetControlInputCount(const Operator* op) {
110 switch (op->opcode()) {
112 case IrOpcode::kEffectPhi:
113 case IrOpcode::kControlEffect:
115 #define OPCODE_CASE(x) case IrOpcode::k##x:
116 CONTROL_OP_LIST(OPCODE_CASE)
118 // Control operators are Operator1<int>.
119 return OpParameter<int>(op);
121 // Operators that have write effects must have a control
122 // dependency. Effect dependencies only ensure the correct order of
123 // write/read operations without consideration of control flow. Without an
124 // explicit control dependency writes can be float in the schedule too
125 // early along a path that shouldn't generate a side-effect.
126 return op->HasProperty(Operator::kNoWrite) ? 0 : 1;
131 inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
132 return GetValueInputCount(op) + GetContextInputCount(op) +
133 GetFrameStateInputCount(op) + GetEffectInputCount(op) +
134 GetControlInputCount(op);
137 // -----------------------------------------------------------------------------
138 // Output properties.
140 inline bool OperatorProperties::HasValueOutput(const Operator* op) {
141 return GetValueOutputCount(op) > 0;
144 inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
145 return op->opcode() == IrOpcode::kStart ||
146 op->opcode() == IrOpcode::kControlEffect ||
147 op->opcode() == IrOpcode::kValueEffect ||
148 (op->opcode() != IrOpcode::kFinish && GetEffectInputCount(op) > 0);
151 inline bool OperatorProperties::HasControlOutput(const Operator* op) {
152 IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
153 return (opcode != IrOpcode::kEnd && IrOpcode::IsControlOpcode(opcode));
157 inline int OperatorProperties::GetValueOutputCount(const Operator* op) {
158 return op->OutputCount();
161 inline int OperatorProperties::GetEffectOutputCount(const Operator* op) {
162 return HasEffectOutput(op) ? 1 : 0;
165 inline int OperatorProperties::GetControlOutputCount(const Operator* node) {
166 return node->opcode() == IrOpcode::kBranch ? 2 : HasControlOutput(node) ? 1
171 inline bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
172 uint8_t opcode = op->opcode();
173 return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd ||
174 opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop ||
175 opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue ||
176 opcode == IrOpcode::kIfFalse;
179 } // namespace compiler
180 } // namespace internal
183 #endif // V8_COMPILER_OPERATOR_PROPERTIES_INL_H_